Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -414,18 +414,20 @@ src/
└── claude/ # Claude Code assets
├── agents/devflow/ # Sub-agent definitions
├── commands/devflow/ # Slash command definitions
├── skills/devflow/ # Auto-activate skill definitions
├── skills/devflow/ # Skill source (installed flat)
├── scripts/ # Supporting scripts
└── settings.json # Claude Code settings
```

### Installation Paths
- Commands: `~/.claude/commands/devflow/`
- Agents: `~/.claude/agents/devflow/`
- Skills: `~/.claude/skills/devflow/`
- Skills: `~/.claude/skills/` (flat structure - no devflow/ subdirectory)
- Scripts: `~/.devflow/scripts/`
- Settings: `~/.claude/settings.json`

**Note:** Skills are installed flat (directly under `skills/`) for Claude Code auto-discovery. Commands and agents use the `devflow/` subdirectory for namespacing.

## Testing Guidelines

### Command Testing
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ Covers patterns for all major languages and operating systems.
**User Scope** (default):
- Installs commands to `~/.claude/commands/devflow/`
- Installs sub-agents to `~/.claude/agents/devflow/`
- Installs skills to `~/.claude/skills/devflow/`
- Installs skills to `~/.claude/skills/`
- Installs scripts to `~/.devflow/scripts/`
- Updates `~/.claude/settings.json` (statusline and model)
- Creates `.claudeignore` at git repository root
Expand All @@ -211,7 +211,7 @@ Covers patterns for all major languages and operating systems.
**Local Scope** (`--scope local`):
- Installs commands to `<git-root>/.claude/commands/devflow/`
- Installs sub-agents to `<git-root>/.claude/agents/devflow/`
- Installs skills to `<git-root>/.claude/skills/devflow/`
- Installs skills to `<git-root>/.claude/skills/`
- Installs scripts to `<git-root>/.devflow/scripts/`
- Creates `<git-root>/.claude/settings.json` (statusline and model)
- Creates `.claudeignore` at git repository root
Expand Down Expand Up @@ -287,7 +287,7 @@ src/
└── claude/ # Claude Code configuration
├── agents/devflow/ # Sub-agent definitions (.md)
├── commands/devflow/ # Slash command definitions (.md)
├── skills/devflow/ # Auto-activate skill definitions (.md)
├── skills/devflow/ # Skill source (installed flat to ~/.claude/skills/)
├── scripts/ # statusline.sh
└── settings.json # Claude Code settings
```
Expand Down
39 changes: 34 additions & 5 deletions src/cli/commands/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export const initCommand = new Command('init')
name: 'agents'
},
{
target: path.join(claudeDir, 'skills', 'devflow'),
target: path.join(claudeDir, 'skills'),
source: path.join(claudeSourceDir, 'skills', 'devflow'),
name: 'skills'
},
Expand All @@ -177,10 +177,39 @@ export const initCommand = new Command('init')

// Clean old DevFlow files before installing
for (const dir of devflowDirectories) {
try {
await fs.rm(dir.target, { recursive: true, force: true });
} catch (e) {
// Directory might not exist on first install
if (dir.name === 'skills') {
// Special handling for skills: clean old nested structure and individual skills
// Remove old devflow/ subdirectory if it exists (migration from old structure)
const oldSkillsDir = path.join(claudeDir, 'skills', 'devflow');
try {
await fs.rm(oldSkillsDir, { recursive: true, force: true });
} catch (e) {
// Directory might not exist
}

// Remove individual skill directories that we're about to reinstall
try {
const skillEntries = await fs.readdir(dir.source, { withFileTypes: true });
for (const entry of skillEntries) {
if (entry.isDirectory()) {
const skillTarget = path.join(dir.target, entry.name);
try {
await fs.rm(skillTarget, { recursive: true, force: true });
} catch (e) {
// Skill might not exist
}
}
}
} catch (e) {
// Source directory might not exist
}
} else {
// For other components (commands, agents, scripts), clean the entire directory
try {
await fs.rm(dir.target, { recursive: true, force: true });
} catch (e) {
// Directory might not exist on first install
}
}
}

Expand Down
35 changes: 34 additions & 1 deletion src/cli/commands/uninstall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ export const uninstallCommand = new Command('uninstall')
const devflowDirectories = [
{ path: path.join(claudeDir, 'commands', 'devflow'), name: 'commands' },
{ path: path.join(claudeDir, 'agents', 'devflow'), name: 'agents' },
{ path: path.join(claudeDir, 'skills', 'devflow'), name: 'skills' },
{ path: devflowScriptsDir, name: 'scripts' }
];

Expand All @@ -100,6 +99,40 @@ export const uninstallCommand = new Command('uninstall')
}
}

// Remove individual DevFlow skills (flat structure)
const skillsDir = path.join(claudeDir, 'skills');
const devflowSkills = [
'pattern-check',
'test-design',
'code-smell',
'research',
'debug',
'input-validation',
'error-handling'
];

let skillsRemoved = 0;
for (const skillName of devflowSkills) {
try {
const skillPath = path.join(skillsDir, skillName);
await fs.rm(skillPath, { recursive: true, force: true });
skillsRemoved++;
} catch (error) {
// Skill might not exist, continue
}
}

if (skillsRemoved > 0) {
console.log(` ✅ Removed ${skillsRemoved} DevFlow skills`);
}

// Also remove old nested skills structure if it exists (migration cleanup)
try {
await fs.rm(path.join(claudeDir, 'skills', 'devflow'), { recursive: true, force: true });
} catch {
// Old structure doesn't exist, ignore
}

console.log();
}

Expand Down