devflow-kit 0.9.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +197 -29
- package/LICENSE +1 -1
- package/README.md +185 -309
- package/dist/cli.js +7 -1
- package/dist/commands/ambient.d.ts +18 -0
- package/dist/commands/ambient.js +136 -0
- package/dist/commands/init.d.ts +23 -0
- package/dist/commands/init.js +393 -571
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.js +20 -0
- package/dist/commands/memory.d.ts +22 -0
- package/dist/commands/memory.js +175 -0
- package/dist/commands/uninstall.d.ts +10 -0
- package/dist/commands/uninstall.js +418 -78
- package/dist/plugins.d.ts +46 -0
- package/dist/plugins.js +169 -0
- package/dist/utils/cli.d.ts +5 -0
- package/dist/utils/cli.js +14 -0
- package/dist/utils/installer.d.ts +41 -0
- package/dist/utils/installer.js +177 -0
- package/dist/utils/paths.d.ts +10 -0
- package/dist/utils/paths.js +23 -3
- package/dist/utils/post-install.d.ts +80 -0
- package/dist/utils/post-install.js +508 -0
- package/dist/utils/safe-delete-install.d.ts +29 -0
- package/dist/utils/safe-delete-install.js +191 -0
- package/dist/utils/safe-delete.d.ts +12 -0
- package/dist/utils/safe-delete.js +83 -0
- package/package.json +18 -8
- package/plugins/devflow-ambient/.claude-plugin/plugin.json +7 -0
- package/plugins/devflow-ambient/README.md +49 -0
- package/plugins/devflow-ambient/commands/ambient.md +110 -0
- package/plugins/devflow-ambient/skills/ambient-router/SKILL.md +89 -0
- package/plugins/devflow-ambient/skills/ambient-router/references/skill-catalog.md +64 -0
- package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +7 -0
- package/plugins/devflow-audit-claude/README.md +46 -0
- package/plugins/devflow-audit-claude/agents/claude-md-auditor.md +134 -0
- package/plugins/devflow-audit-claude/commands/audit-claude.md +85 -0
- package/plugins/devflow-code-review/.claude-plugin/plugin.json +31 -0
- package/plugins/devflow-code-review/README.md +73 -0
- package/plugins/devflow-code-review/agents/git.md +272 -0
- package/plugins/devflow-code-review/agents/reviewer.md +119 -0
- package/plugins/devflow-code-review/agents/synthesizer.md +204 -0
- package/plugins/devflow-code-review/commands/code-review-teams.md +262 -0
- package/plugins/devflow-code-review/commands/code-review.md +141 -0
- package/plugins/devflow-code-review/skills/accessibility/SKILL.md +229 -0
- package/plugins/devflow-code-review/skills/accessibility/references/detection.md +171 -0
- package/plugins/devflow-code-review/skills/accessibility/references/patterns.md +670 -0
- package/plugins/devflow-code-review/skills/accessibility/references/violations.md +419 -0
- package/plugins/devflow-code-review/skills/agent-teams/SKILL.md +124 -0
- package/plugins/devflow-code-review/skills/agent-teams/references/cleanup.md +104 -0
- package/plugins/devflow-code-review/skills/agent-teams/references/communication.md +122 -0
- package/plugins/devflow-code-review/skills/agent-teams/references/team-patterns.md +217 -0
- package/plugins/devflow-code-review/skills/architecture-patterns/SKILL.md +153 -0
- package/plugins/devflow-code-review/skills/architecture-patterns/references/detection.md +337 -0
- package/plugins/devflow-code-review/skills/architecture-patterns/references/patterns.md +873 -0
- package/plugins/devflow-code-review/skills/architecture-patterns/references/violations.md +575 -0
- package/plugins/devflow-code-review/skills/complexity-patterns/SKILL.md +143 -0
- package/plugins/devflow-code-review/skills/complexity-patterns/references/detection.md +264 -0
- package/plugins/devflow-code-review/skills/complexity-patterns/references/patterns.md +487 -0
- package/plugins/devflow-code-review/skills/complexity-patterns/references/violations.md +361 -0
- package/plugins/devflow-code-review/skills/consistency-patterns/SKILL.md +140 -0
- package/plugins/devflow-code-review/skills/consistency-patterns/references/detection.md +207 -0
- package/plugins/devflow-code-review/skills/consistency-patterns/references/patterns.md +202 -0
- package/plugins/devflow-code-review/skills/consistency-patterns/references/violations.md +213 -0
- package/plugins/devflow-code-review/skills/database-patterns/SKILL.md +134 -0
- package/plugins/devflow-code-review/skills/database-patterns/references/detection.md +208 -0
- package/plugins/devflow-code-review/skills/database-patterns/references/patterns.md +394 -0
- package/plugins/devflow-code-review/skills/database-patterns/references/violations.md +332 -0
- package/plugins/devflow-code-review/skills/dependencies-patterns/SKILL.md +141 -0
- package/plugins/devflow-code-review/skills/dependencies-patterns/references/detection.md +181 -0
- package/plugins/devflow-code-review/skills/dependencies-patterns/references/patterns.md +225 -0
- package/plugins/devflow-code-review/skills/dependencies-patterns/references/violations.md +247 -0
- package/plugins/devflow-code-review/skills/documentation-patterns/SKILL.md +125 -0
- package/plugins/devflow-code-review/skills/documentation-patterns/references/detection.md +190 -0
- package/plugins/devflow-code-review/skills/documentation-patterns/references/patterns.md +189 -0
- package/plugins/devflow-code-review/skills/documentation-patterns/references/violations.md +163 -0
- package/plugins/devflow-code-review/skills/frontend-design/SKILL.md +254 -0
- package/plugins/devflow-code-review/skills/frontend-design/references/detection.md +184 -0
- package/plugins/devflow-code-review/skills/frontend-design/references/patterns.md +511 -0
- package/plugins/devflow-code-review/skills/frontend-design/references/violations.md +453 -0
- package/plugins/devflow-code-review/skills/performance-patterns/SKILL.md +154 -0
- package/plugins/devflow-code-review/skills/performance-patterns/references/detection.md +351 -0
- package/plugins/devflow-code-review/skills/performance-patterns/references/patterns.md +503 -0
- package/plugins/devflow-code-review/skills/performance-patterns/references/violations.md +354 -0
- package/plugins/devflow-code-review/skills/react/SKILL.md +276 -0
- package/plugins/devflow-code-review/skills/react/references/patterns.md +1331 -0
- package/plugins/devflow-code-review/skills/react/references/violations.md +565 -0
- package/plugins/devflow-code-review/skills/regression-patterns/SKILL.md +146 -0
- package/plugins/devflow-code-review/skills/regression-patterns/references/detection.md +237 -0
- package/plugins/devflow-code-review/skills/regression-patterns/references/patterns.md +226 -0
- package/plugins/devflow-code-review/skills/regression-patterns/references/violations.md +225 -0
- package/plugins/devflow-code-review/skills/review-methodology/SKILL.md +119 -0
- package/plugins/devflow-code-review/skills/review-methodology/references/patterns.md +186 -0
- package/plugins/devflow-code-review/skills/review-methodology/references/report-template.md +142 -0
- package/plugins/devflow-code-review/skills/review-methodology/references/violations.md +125 -0
- package/plugins/devflow-code-review/skills/security-patterns/SKILL.md +156 -0
- package/plugins/devflow-code-review/skills/security-patterns/references/detection.md +287 -0
- package/plugins/devflow-code-review/skills/security-patterns/references/patterns.md +507 -0
- package/plugins/devflow-code-review/skills/security-patterns/references/violations.md +237 -0
- package/plugins/devflow-code-review/skills/test-patterns/SKILL.md +183 -0
- package/plugins/devflow-code-review/skills/test-patterns/references/detection.md +149 -0
- package/plugins/devflow-code-review/skills/test-patterns/references/patterns.md +220 -0
- package/plugins/devflow-code-review/skills/test-patterns/references/report-template.md +108 -0
- package/plugins/devflow-code-review/skills/test-patterns/references/violations.md +221 -0
- package/plugins/devflow-core-skills/.claude-plugin/plugin.json +28 -0
- package/plugins/devflow-core-skills/README.md +50 -0
- package/plugins/devflow-core-skills/skills/accessibility/SKILL.md +229 -0
- package/plugins/devflow-core-skills/skills/accessibility/references/detection.md +171 -0
- package/plugins/devflow-core-skills/skills/accessibility/references/patterns.md +670 -0
- package/plugins/devflow-core-skills/skills/accessibility/references/violations.md +419 -0
- package/plugins/devflow-core-skills/skills/core-patterns/SKILL.md +162 -0
- package/plugins/devflow-core-skills/skills/core-patterns/references/checklist.md +276 -0
- package/plugins/devflow-core-skills/skills/core-patterns/references/code-smell-violations.md +144 -0
- package/plugins/devflow-core-skills/skills/core-patterns/references/detection.md +303 -0
- package/plugins/devflow-core-skills/skills/core-patterns/references/patterns.md +576 -0
- package/plugins/devflow-core-skills/skills/core-patterns/references/violations.md +369 -0
- package/plugins/devflow-core-skills/skills/docs-framework/SKILL.md +138 -0
- package/plugins/devflow-core-skills/skills/docs-framework/references/patterns.md +346 -0
- package/plugins/devflow-core-skills/skills/docs-framework/references/violations.md +221 -0
- package/plugins/devflow-core-skills/skills/frontend-design/SKILL.md +254 -0
- package/plugins/devflow-core-skills/skills/frontend-design/references/detection.md +184 -0
- package/plugins/devflow-core-skills/skills/frontend-design/references/patterns.md +511 -0
- package/plugins/devflow-core-skills/skills/frontend-design/references/violations.md +453 -0
- package/plugins/devflow-core-skills/skills/git-safety/SKILL.md +122 -0
- package/plugins/devflow-core-skills/skills/git-safety/references/detection.md +290 -0
- package/plugins/devflow-core-skills/skills/git-safety/references/patterns.md +289 -0
- package/plugins/devflow-core-skills/skills/git-safety/references/violations.md +18 -0
- package/plugins/devflow-core-skills/skills/git-workflow/SKILL.md +158 -0
- package/plugins/devflow-core-skills/skills/git-workflow/references/commit-patterns.md +115 -0
- package/plugins/devflow-core-skills/skills/git-workflow/references/commit-violations.md +77 -0
- package/plugins/devflow-core-skills/skills/git-workflow/references/pr-patterns.md +127 -0
- package/plugins/devflow-core-skills/skills/git-workflow/references/pr-violations.md +96 -0
- package/plugins/devflow-core-skills/skills/github-patterns/SKILL.md +153 -0
- package/plugins/devflow-core-skills/skills/github-patterns/references/patterns.md +572 -0
- package/plugins/devflow-core-skills/skills/github-patterns/references/violations.md +298 -0
- package/plugins/devflow-core-skills/skills/input-validation/SKILL.md +148 -0
- package/plugins/devflow-core-skills/skills/input-validation/references/detection.md +283 -0
- package/plugins/devflow-core-skills/skills/input-validation/references/patterns.md +361 -0
- package/plugins/devflow-core-skills/skills/input-validation/references/violations.md +224 -0
- package/plugins/devflow-core-skills/skills/react/SKILL.md +276 -0
- package/plugins/devflow-core-skills/skills/react/references/patterns.md +1331 -0
- package/plugins/devflow-core-skills/skills/react/references/violations.md +565 -0
- package/plugins/devflow-core-skills/skills/test-driven-development/SKILL.md +139 -0
- package/plugins/devflow-core-skills/skills/test-driven-development/references/rationalization-prevention.md +111 -0
- package/plugins/devflow-core-skills/skills/test-patterns/SKILL.md +183 -0
- package/plugins/devflow-core-skills/skills/test-patterns/references/detection.md +149 -0
- package/plugins/devflow-core-skills/skills/test-patterns/references/patterns.md +220 -0
- package/plugins/devflow-core-skills/skills/test-patterns/references/report-template.md +108 -0
- package/plugins/devflow-core-skills/skills/test-patterns/references/violations.md +221 -0
- package/plugins/devflow-core-skills/skills/typescript/SKILL.md +176 -0
- package/plugins/devflow-core-skills/skills/typescript/references/patterns.md +1105 -0
- package/plugins/devflow-core-skills/skills/typescript/references/violations.md +433 -0
- package/plugins/devflow-debug/.claude-plugin/plugin.json +18 -0
- package/plugins/devflow-debug/README.md +65 -0
- package/plugins/devflow-debug/agents/git.md +272 -0
- package/plugins/devflow-debug/commands/debug-teams.md +231 -0
- package/plugins/devflow-debug/commands/debug.md +160 -0
- package/plugins/devflow-debug/skills/agent-teams/SKILL.md +124 -0
- package/plugins/devflow-debug/skills/agent-teams/references/cleanup.md +104 -0
- package/plugins/devflow-debug/skills/agent-teams/references/communication.md +122 -0
- package/plugins/devflow-debug/skills/agent-teams/references/team-patterns.md +217 -0
- package/plugins/devflow-debug/skills/git-safety/SKILL.md +122 -0
- package/plugins/devflow-debug/skills/git-safety/references/detection.md +290 -0
- package/plugins/devflow-debug/skills/git-safety/references/patterns.md +289 -0
- package/plugins/devflow-debug/skills/git-safety/references/violations.md +18 -0
- package/plugins/devflow-implement/.claude-plugin/plugin.json +21 -0
- package/plugins/devflow-implement/README.md +71 -0
- package/plugins/devflow-implement/agents/coder.md +122 -0
- package/plugins/devflow-implement/agents/git.md +272 -0
- package/plugins/devflow-implement/agents/scrutinizer.md +80 -0
- package/plugins/devflow-implement/agents/shepherd.md +94 -0
- package/plugins/devflow-implement/agents/simplifier.md +62 -0
- package/plugins/devflow-implement/agents/skimmer.md +88 -0
- package/plugins/devflow-implement/agents/synthesizer.md +204 -0
- package/plugins/devflow-implement/agents/validator.md +86 -0
- package/plugins/devflow-implement/commands/implement-teams.md +608 -0
- package/plugins/devflow-implement/commands/implement.md +426 -0
- package/plugins/devflow-implement/skills/accessibility/SKILL.md +229 -0
- package/plugins/devflow-implement/skills/accessibility/references/detection.md +171 -0
- package/plugins/devflow-implement/skills/accessibility/references/patterns.md +670 -0
- package/plugins/devflow-implement/skills/accessibility/references/violations.md +419 -0
- package/plugins/devflow-implement/skills/agent-teams/SKILL.md +124 -0
- package/plugins/devflow-implement/skills/agent-teams/references/cleanup.md +104 -0
- package/plugins/devflow-implement/skills/agent-teams/references/communication.md +122 -0
- package/plugins/devflow-implement/skills/agent-teams/references/team-patterns.md +217 -0
- package/plugins/devflow-implement/skills/frontend-design/SKILL.md +254 -0
- package/plugins/devflow-implement/skills/frontend-design/references/detection.md +184 -0
- package/plugins/devflow-implement/skills/frontend-design/references/patterns.md +511 -0
- package/plugins/devflow-implement/skills/frontend-design/references/violations.md +453 -0
- package/plugins/devflow-implement/skills/implementation-patterns/SKILL.md +162 -0
- package/plugins/devflow-implement/skills/implementation-patterns/references/patterns.md +1063 -0
- package/plugins/devflow-implement/skills/implementation-patterns/references/violations.md +483 -0
- package/plugins/devflow-implement/skills/self-review/SKILL.md +149 -0
- package/plugins/devflow-implement/skills/self-review/references/patterns.md +405 -0
- package/plugins/devflow-implement/skills/self-review/references/report-template.md +253 -0
- package/plugins/devflow-implement/skills/self-review/references/violations.md +308 -0
- package/plugins/devflow-resolve/.claude-plugin/plugin.json +19 -0
- package/plugins/devflow-resolve/README.md +65 -0
- package/plugins/devflow-resolve/agents/git.md +272 -0
- package/plugins/devflow-resolve/agents/resolver.md +131 -0
- package/plugins/devflow-resolve/agents/simplifier.md +62 -0
- package/plugins/devflow-resolve/commands/resolve-teams.md +298 -0
- package/plugins/devflow-resolve/commands/resolve.md +237 -0
- package/plugins/devflow-resolve/skills/agent-teams/SKILL.md +124 -0
- package/plugins/devflow-resolve/skills/agent-teams/references/cleanup.md +104 -0
- package/plugins/devflow-resolve/skills/agent-teams/references/communication.md +122 -0
- package/plugins/devflow-resolve/skills/agent-teams/references/team-patterns.md +217 -0
- package/plugins/devflow-resolve/skills/implementation-patterns/SKILL.md +162 -0
- package/plugins/devflow-resolve/skills/implementation-patterns/references/patterns.md +1063 -0
- package/plugins/devflow-resolve/skills/implementation-patterns/references/violations.md +483 -0
- package/plugins/devflow-resolve/skills/security-patterns/SKILL.md +156 -0
- package/plugins/devflow-resolve/skills/security-patterns/references/detection.md +287 -0
- package/plugins/devflow-resolve/skills/security-patterns/references/patterns.md +507 -0
- package/plugins/devflow-resolve/skills/security-patterns/references/violations.md +237 -0
- package/plugins/devflow-self-review/.claude-plugin/plugin.json +7 -0
- package/plugins/devflow-self-review/README.md +38 -0
- package/plugins/devflow-self-review/agents/scrutinizer.md +80 -0
- package/plugins/devflow-self-review/agents/simplifier.md +62 -0
- package/plugins/devflow-self-review/agents/validator.md +86 -0
- package/plugins/devflow-self-review/commands/self-review.md +126 -0
- package/plugins/devflow-self-review/skills/core-patterns/SKILL.md +162 -0
- package/plugins/devflow-self-review/skills/core-patterns/references/checklist.md +276 -0
- package/plugins/devflow-self-review/skills/core-patterns/references/code-smell-violations.md +144 -0
- package/plugins/devflow-self-review/skills/core-patterns/references/detection.md +303 -0
- package/plugins/devflow-self-review/skills/core-patterns/references/patterns.md +576 -0
- package/plugins/devflow-self-review/skills/core-patterns/references/violations.md +369 -0
- package/plugins/devflow-self-review/skills/self-review/SKILL.md +149 -0
- package/plugins/devflow-self-review/skills/self-review/references/patterns.md +405 -0
- package/plugins/devflow-self-review/skills/self-review/references/report-template.md +253 -0
- package/plugins/devflow-self-review/skills/self-review/references/violations.md +308 -0
- package/plugins/devflow-specify/.claude-plugin/plugin.json +15 -0
- package/plugins/devflow-specify/README.md +46 -0
- package/plugins/devflow-specify/agents/skimmer.md +88 -0
- package/plugins/devflow-specify/agents/synthesizer.md +204 -0
- package/plugins/devflow-specify/commands/specify-teams.md +314 -0
- package/plugins/devflow-specify/commands/specify.md +179 -0
- package/plugins/devflow-specify/skills/agent-teams/SKILL.md +124 -0
- package/plugins/devflow-specify/skills/agent-teams/references/cleanup.md +104 -0
- package/plugins/devflow-specify/skills/agent-teams/references/communication.md +122 -0
- package/plugins/devflow-specify/skills/agent-teams/references/team-patterns.md +217 -0
- package/scripts/hooks/ambient-prompt.sh +48 -0
- package/scripts/hooks/background-memory-update.sh +208 -0
- package/scripts/hooks/ensure-memory-gitignore.sh +17 -0
- package/scripts/hooks/pre-compact-memory.sh +87 -0
- package/scripts/hooks/session-start-memory.sh +126 -0
- package/scripts/hooks/stop-update-memory.sh +85 -0
- package/shared/agents/coder.md +122 -0
- package/shared/agents/git.md +272 -0
- package/shared/agents/resolver.md +131 -0
- package/shared/agents/reviewer.md +119 -0
- package/shared/agents/scrutinizer.md +80 -0
- package/shared/agents/shepherd.md +94 -0
- package/shared/agents/simplifier.md +62 -0
- package/shared/agents/skimmer.md +88 -0
- package/shared/agents/synthesizer.md +204 -0
- package/shared/agents/validator.md +86 -0
- package/shared/skills/accessibility/SKILL.md +229 -0
- package/shared/skills/accessibility/references/detection.md +171 -0
- package/shared/skills/accessibility/references/patterns.md +670 -0
- package/shared/skills/accessibility/references/violations.md +419 -0
- package/shared/skills/agent-teams/SKILL.md +124 -0
- package/shared/skills/agent-teams/references/cleanup.md +104 -0
- package/shared/skills/agent-teams/references/communication.md +122 -0
- package/shared/skills/agent-teams/references/team-patterns.md +217 -0
- package/shared/skills/ambient-router/SKILL.md +89 -0
- package/shared/skills/ambient-router/references/skill-catalog.md +64 -0
- package/shared/skills/architecture-patterns/SKILL.md +153 -0
- package/shared/skills/architecture-patterns/references/detection.md +337 -0
- package/shared/skills/architecture-patterns/references/patterns.md +873 -0
- package/shared/skills/architecture-patterns/references/violations.md +575 -0
- package/shared/skills/complexity-patterns/SKILL.md +143 -0
- package/shared/skills/complexity-patterns/references/detection.md +264 -0
- package/shared/skills/complexity-patterns/references/patterns.md +487 -0
- package/shared/skills/complexity-patterns/references/violations.md +361 -0
- package/shared/skills/consistency-patterns/SKILL.md +140 -0
- package/shared/skills/consistency-patterns/references/detection.md +207 -0
- package/shared/skills/consistency-patterns/references/patterns.md +202 -0
- package/shared/skills/consistency-patterns/references/violations.md +213 -0
- package/shared/skills/core-patterns/SKILL.md +162 -0
- package/shared/skills/core-patterns/references/checklist.md +276 -0
- package/shared/skills/core-patterns/references/code-smell-violations.md +144 -0
- package/shared/skills/core-patterns/references/detection.md +303 -0
- package/shared/skills/core-patterns/references/patterns.md +576 -0
- package/shared/skills/core-patterns/references/violations.md +369 -0
- package/shared/skills/database-patterns/SKILL.md +134 -0
- package/shared/skills/database-patterns/references/detection.md +208 -0
- package/shared/skills/database-patterns/references/patterns.md +394 -0
- package/shared/skills/database-patterns/references/violations.md +332 -0
- package/shared/skills/dependencies-patterns/SKILL.md +141 -0
- package/shared/skills/dependencies-patterns/references/detection.md +181 -0
- package/shared/skills/dependencies-patterns/references/patterns.md +225 -0
- package/shared/skills/dependencies-patterns/references/violations.md +247 -0
- package/shared/skills/docs-framework/SKILL.md +138 -0
- package/shared/skills/docs-framework/references/patterns.md +346 -0
- package/shared/skills/docs-framework/references/violations.md +221 -0
- package/shared/skills/documentation-patterns/SKILL.md +125 -0
- package/shared/skills/documentation-patterns/references/detection.md +190 -0
- package/shared/skills/documentation-patterns/references/patterns.md +189 -0
- package/shared/skills/documentation-patterns/references/violations.md +163 -0
- package/shared/skills/frontend-design/SKILL.md +254 -0
- package/shared/skills/frontend-design/references/detection.md +184 -0
- package/shared/skills/frontend-design/references/patterns.md +511 -0
- package/shared/skills/frontend-design/references/violations.md +453 -0
- package/shared/skills/git-safety/SKILL.md +122 -0
- package/shared/skills/git-safety/references/detection.md +290 -0
- package/shared/skills/git-safety/references/patterns.md +289 -0
- package/shared/skills/git-safety/references/violations.md +18 -0
- package/shared/skills/git-workflow/SKILL.md +158 -0
- package/shared/skills/git-workflow/references/commit-patterns.md +115 -0
- package/shared/skills/git-workflow/references/commit-violations.md +77 -0
- package/shared/skills/git-workflow/references/pr-patterns.md +127 -0
- package/shared/skills/git-workflow/references/pr-violations.md +96 -0
- package/shared/skills/github-patterns/SKILL.md +153 -0
- package/shared/skills/github-patterns/references/patterns.md +572 -0
- package/shared/skills/github-patterns/references/violations.md +298 -0
- package/shared/skills/implementation-patterns/SKILL.md +162 -0
- package/shared/skills/implementation-patterns/references/patterns.md +1063 -0
- package/shared/skills/implementation-patterns/references/violations.md +483 -0
- package/shared/skills/input-validation/SKILL.md +148 -0
- package/shared/skills/input-validation/references/detection.md +283 -0
- package/shared/skills/input-validation/references/patterns.md +361 -0
- package/shared/skills/input-validation/references/violations.md +224 -0
- package/shared/skills/performance-patterns/SKILL.md +154 -0
- package/shared/skills/performance-patterns/references/detection.md +351 -0
- package/shared/skills/performance-patterns/references/patterns.md +503 -0
- package/shared/skills/performance-patterns/references/violations.md +354 -0
- package/shared/skills/react/SKILL.md +276 -0
- package/shared/skills/react/references/patterns.md +1331 -0
- package/shared/skills/react/references/violations.md +565 -0
- package/shared/skills/regression-patterns/SKILL.md +146 -0
- package/shared/skills/regression-patterns/references/detection.md +237 -0
- package/shared/skills/regression-patterns/references/patterns.md +226 -0
- package/shared/skills/regression-patterns/references/violations.md +225 -0
- package/shared/skills/review-methodology/SKILL.md +119 -0
- package/shared/skills/review-methodology/references/patterns.md +186 -0
- package/shared/skills/review-methodology/references/report-template.md +142 -0
- package/shared/skills/review-methodology/references/violations.md +125 -0
- package/shared/skills/security-patterns/SKILL.md +156 -0
- package/shared/skills/security-patterns/references/detection.md +287 -0
- package/shared/skills/security-patterns/references/patterns.md +507 -0
- package/shared/skills/security-patterns/references/violations.md +237 -0
- package/shared/skills/self-review/SKILL.md +149 -0
- package/shared/skills/self-review/references/patterns.md +405 -0
- package/shared/skills/self-review/references/report-template.md +253 -0
- package/shared/skills/self-review/references/violations.md +308 -0
- package/shared/skills/test-driven-development/SKILL.md +139 -0
- package/shared/skills/test-driven-development/references/rationalization-prevention.md +111 -0
- package/shared/skills/test-patterns/SKILL.md +183 -0
- package/shared/skills/test-patterns/references/detection.md +149 -0
- package/shared/skills/test-patterns/references/patterns.md +220 -0
- package/shared/skills/test-patterns/references/report-template.md +108 -0
- package/shared/skills/test-patterns/references/violations.md +221 -0
- package/shared/skills/typescript/SKILL.md +176 -0
- package/shared/skills/typescript/references/patterns.md +1105 -0
- package/shared/skills/typescript/references/violations.md +433 -0
- package/src/templates/claudeignore.template +188 -0
- package/src/templates/managed-settings.json +160 -0
- package/src/templates/settings.json +59 -0
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/uninstall.d.ts.map +0 -1
- package/dist/commands/uninstall.js.map +0 -1
- package/dist/utils/git.d.ts.map +0 -1
- package/dist/utils/git.js.map +0 -1
- package/dist/utils/paths.d.ts.map +0 -1
- package/dist/utils/paths.js.map +0 -1
- package/src/claude/CLAUDE.md +0 -400
- package/src/claude/agents/devflow/audit-architecture.md +0 -132
- package/src/claude/agents/devflow/audit-complexity.md +0 -132
- package/src/claude/agents/devflow/audit-database.md +0 -132
- package/src/claude/agents/devflow/audit-dependencies.md +0 -132
- package/src/claude/agents/devflow/audit-documentation.md +0 -132
- package/src/claude/agents/devflow/audit-performance.md +0 -256
- package/src/claude/agents/devflow/audit-security.md +0 -259
- package/src/claude/agents/devflow/audit-tests.md +0 -132
- package/src/claude/agents/devflow/audit-typescript.md +0 -132
- package/src/claude/agents/devflow/brainstorm.md +0 -279
- package/src/claude/agents/devflow/catch-up.md +0 -345
- package/src/claude/agents/devflow/code-review.md +0 -307
- package/src/claude/agents/devflow/commit.md +0 -380
- package/src/claude/agents/devflow/debug.md +0 -476
- package/src/claude/agents/devflow/design.md +0 -491
- package/src/claude/agents/devflow/get-issue.md +0 -286
- package/src/claude/agents/devflow/pr-comments.md +0 -285
- package/src/claude/agents/devflow/project-state.md +0 -419
- package/src/claude/agents/devflow/pull-request.md +0 -493
- package/src/claude/agents/devflow/release.md +0 -1137
- package/src/claude/agents/devflow/tech-debt.md +0 -338
- package/src/claude/commands/devflow/brainstorm.md +0 -68
- package/src/claude/commands/devflow/breakdown.md +0 -125
- package/src/claude/commands/devflow/catch-up.md +0 -29
- package/src/claude/commands/devflow/code-review.md +0 -237
- package/src/claude/commands/devflow/commit.md +0 -17
- package/src/claude/commands/devflow/debug.md +0 -56
- package/src/claude/commands/devflow/design.md +0 -82
- package/src/claude/commands/devflow/devlog.md +0 -408
- package/src/claude/commands/devflow/get-issue.md +0 -16
- package/src/claude/commands/devflow/implement.md +0 -100
- package/src/claude/commands/devflow/plan.md +0 -223
- package/src/claude/commands/devflow/pull-request.md +0 -20
- package/src/claude/commands/devflow/release.md +0 -251
- package/src/claude/commands/devflow/resolve-comments.md +0 -583
- package/src/claude/scripts/statusline.sh +0 -47
- package/src/claude/settings.json +0 -6
- package/src/claude/skills/devflow/code-smell/SKILL.md +0 -428
- package/src/claude/skills/devflow/debug/SKILL.md +0 -119
- package/src/claude/skills/devflow/error-handling/SKILL.md +0 -597
- package/src/claude/skills/devflow/input-validation/SKILL.md +0 -514
- package/src/claude/skills/devflow/pattern-check/SKILL.md +0 -238
- package/src/claude/skills/devflow/research/SKILL.md +0 -138
- package/src/claude/skills/devflow/test-design/SKILL.md +0 -384
package/dist/commands/init.js
CHANGED
|
@@ -3,126 +3,68 @@ import { promises as fs } from 'fs';
|
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { dirname } from 'path';
|
|
6
|
-
import * as
|
|
6
|
+
import * as p from '@clack/prompts';
|
|
7
|
+
import color from 'picocolors';
|
|
7
8
|
import { getInstallationPaths } from '../utils/paths.js';
|
|
8
9
|
import { getGitRoot } from '../utils/git.js';
|
|
10
|
+
import { isClaudeCliAvailable } from '../utils/cli.js';
|
|
11
|
+
import { installViaCli, installViaFileCopy } from '../utils/installer.js';
|
|
12
|
+
import { installSettings, installManagedSettings, installClaudeignore, updateGitignore, createDocsStructure, createMemoryDir, migrateMemoryFiles, } from '../utils/post-install.js';
|
|
13
|
+
import { DEVFLOW_PLUGINS, LEGACY_SKILL_NAMES, LEGACY_COMMAND_NAMES, buildAssetMaps } from '../plugins.js';
|
|
14
|
+
import { detectPlatform, detectShell, getProfilePath, getSafeDeleteInfo, hasSafeDelete } from '../utils/safe-delete.js';
|
|
15
|
+
import { generateSafeDeleteBlock, installToProfile, removeFromProfile, getInstalledVersion, SAFE_DELETE_BLOCK_VERSION } from '../utils/safe-delete-install.js';
|
|
16
|
+
import { addAmbientHook } from './ambient.js';
|
|
17
|
+
import { addMemoryHooks, removeMemoryHooks } from './memory.js';
|
|
18
|
+
// Re-export pure functions for tests (canonical source is post-install.ts)
|
|
19
|
+
export { substituteSettingsTemplate, computeGitignoreAppend, applyTeamsConfig, stripTeamsConfig, mergeDenyList } from '../utils/post-install.js';
|
|
20
|
+
export { addAmbientHook, removeAmbientHook, hasAmbientHook } from './ambient.js';
|
|
21
|
+
export { addMemoryHooks, removeMemoryHooks, hasMemoryHooks } from './memory.js';
|
|
9
22
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
23
|
const __dirname = dirname(__filename);
|
|
11
|
-
function isNodeSystemError(error) {
|
|
12
|
-
return (error instanceof Error &&
|
|
13
|
-
'code' in error &&
|
|
14
|
-
typeof error.code === 'string');
|
|
15
|
-
}
|
|
16
24
|
/**
|
|
17
|
-
*
|
|
25
|
+
* Parse a comma-separated plugin selection string into normalized plugin names.
|
|
26
|
+
* Validates against known plugins; returns invalid names as errors.
|
|
18
27
|
*/
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
});
|
|
24
|
-
return new Promise((resolve) => {
|
|
25
|
-
rl.question(question, (answer) => {
|
|
26
|
-
rl.close();
|
|
27
|
-
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
28
|
-
});
|
|
28
|
+
export function parsePluginSelection(input, validPlugins) {
|
|
29
|
+
const selected = input.split(',').map(p => {
|
|
30
|
+
const trimmed = p.trim();
|
|
31
|
+
return trimmed.startsWith('devflow-') ? trimmed : `devflow-${trimmed}`;
|
|
29
32
|
});
|
|
33
|
+
const validNames = validPlugins.map(p => p.name);
|
|
34
|
+
const invalid = selected.filter(p => !validNames.includes(p));
|
|
35
|
+
return { selected, invalid };
|
|
30
36
|
}
|
|
31
37
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*/
|
|
35
|
-
const DEVFLOW_COMMANDS = [
|
|
36
|
-
{ name: '/catch-up', description: 'Get up to speed on project state' },
|
|
37
|
-
{ name: '/brainstorm', description: 'Explore design decisions' },
|
|
38
|
-
{ name: '/design', description: 'Create implementation plan' },
|
|
39
|
-
{ name: '/plan', description: 'Triage issues from discussion' },
|
|
40
|
-
{ name: '/breakdown', description: 'Break down tasks quickly' },
|
|
41
|
-
{ name: '/get-issue', description: 'Fetch issue and create branch' },
|
|
42
|
-
{ name: '/implement', description: 'Interactive implementation' },
|
|
43
|
-
{ name: '/code-review', description: 'Comprehensive code review' },
|
|
44
|
-
{ name: '/commit', description: 'Smart atomic commits' },
|
|
45
|
-
{ name: '/pull-request', description: 'Create PR with description' },
|
|
46
|
-
{ name: '/release', description: 'Automated releases' },
|
|
47
|
-
{ name: '/devlog', description: 'Document session progress' },
|
|
48
|
-
{ name: '/debug', description: 'Systematic debugging' },
|
|
49
|
-
{ name: '/resolve-comments', description: 'Address PR feedback' },
|
|
50
|
-
];
|
|
51
|
-
/**
|
|
52
|
-
* DevFlow skills with descriptions.
|
|
53
|
-
* Displayed only in verbose mode to show auto-activating capabilities.
|
|
38
|
+
* Build the list of configuration extras available for the given scope/git context.
|
|
39
|
+
* Pure function — no I/O, no side effects.
|
|
54
40
|
*/
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
{ name: 'input-validation', description: 'Boundary validation' },
|
|
62
|
-
{ name: 'error-handling', description: 'Result type consistency' },
|
|
63
|
-
];
|
|
64
|
-
/**
|
|
65
|
-
* Render clean, minimal output for default (non-verbose) mode.
|
|
66
|
-
* Shows only essential information: version, available commands, and docs link.
|
|
67
|
-
*
|
|
68
|
-
* @param version - The DevFlow version string to display
|
|
69
|
-
*/
|
|
70
|
-
function renderCleanOutput(version) {
|
|
71
|
-
console.log(`\n✓ DevFlow v${version} installed\n`);
|
|
72
|
-
console.log('Commands available:');
|
|
73
|
-
// Calculate max command name length for alignment
|
|
74
|
-
const maxLen = Math.max(...DEVFLOW_COMMANDS.map(c => c.name.length));
|
|
75
|
-
for (const cmd of DEVFLOW_COMMANDS) {
|
|
76
|
-
const padding = ' '.repeat(maxLen - cmd.name.length + 2);
|
|
77
|
-
console.log(` ${cmd.name}${padding}${cmd.description}`);
|
|
78
|
-
}
|
|
79
|
-
console.log('\nRun any command in Claude Code to get started.');
|
|
80
|
-
console.log('\nDocs: https://github.com/dean0x/devflow');
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Render detailed output for verbose mode.
|
|
84
|
-
* Shows full installation details including paths, merge instructions, and skills.
|
|
85
|
-
*
|
|
86
|
-
* @param version - The DevFlow version string to display
|
|
87
|
-
* @param scope - Installation scope ('user' for user-wide, 'local' for project-only)
|
|
88
|
-
* @param claudeDir - Path to the Claude Code directory
|
|
89
|
-
* @param devflowDir - Path to the DevFlow directory
|
|
90
|
-
* @param settingsExists - Whether existing settings.json was preserved
|
|
91
|
-
* @param claudeMdExists - Whether existing CLAUDE.md was preserved
|
|
92
|
-
*/
|
|
93
|
-
function renderVerboseOutput(version, scope, claudeDir, devflowDir, settingsExists, claudeMdExists) {
|
|
94
|
-
console.log(`\n✅ DevFlow v${version} installed!\n`);
|
|
95
|
-
console.log(`📍 Installation scope: ${scope}`);
|
|
96
|
-
console.log(` Claude dir: ${claudeDir}`);
|
|
97
|
-
console.log(` DevFlow dir: ${devflowDir}\n`);
|
|
98
|
-
// Show manual merge instructions if needed
|
|
99
|
-
if (settingsExists || claudeMdExists) {
|
|
100
|
-
console.log('📝 Manual merge recommended:\n');
|
|
101
|
-
if (settingsExists) {
|
|
102
|
-
console.log(' Settings: Review settings.devflow.json and merge desired config into settings.json');
|
|
103
|
-
console.log(' Key setting: statusLine configuration for DevFlow statusline\n');
|
|
104
|
-
}
|
|
105
|
-
if (claudeMdExists) {
|
|
106
|
-
console.log(' Instructions: Review CLAUDE.devflow.md and adopt desired practices');
|
|
107
|
-
console.log(" This contains DevFlow's recommended development patterns\n");
|
|
108
|
-
}
|
|
41
|
+
export function buildExtrasOptions(scope, gitRoot) {
|
|
42
|
+
const options = [
|
|
43
|
+
{ value: 'settings', label: 'Settings & Working Memory', hint: 'Model defaults, session memory hooks, status line' },
|
|
44
|
+
];
|
|
45
|
+
if (gitRoot) {
|
|
46
|
+
options.push({ value: 'claudeignore', label: '.claudeignore', hint: 'Exclude secrets, deps, build artifacts from Claude context' });
|
|
109
47
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
console.log(` ${cmd.name.padEnd(18)}${cmd.description}`);
|
|
48
|
+
if (scope === 'local' && gitRoot) {
|
|
49
|
+
options.push({ value: 'gitignore', label: '.gitignore entries', hint: 'Add .claude/ and .devflow/ to .gitignore' });
|
|
113
50
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
console.log(` ${skill.name.padEnd(18)}${skill.description}`);
|
|
51
|
+
if (scope === 'local') {
|
|
52
|
+
options.push({ value: 'docs', label: '.docs/ directory', hint: 'Review reports, dev logs, status tracking for this project' });
|
|
117
53
|
}
|
|
118
|
-
|
|
119
|
-
|
|
54
|
+
options.push({ value: 'safe-delete', label: 'Safe-delete (rm → trash)', hint: 'Override rm to use trash CLI — prevents accidental deletion' });
|
|
55
|
+
return options;
|
|
120
56
|
}
|
|
121
57
|
export const initCommand = new Command('init')
|
|
122
58
|
.description('Initialize DevFlow for Claude Code')
|
|
123
|
-
.option('--
|
|
124
|
-
.option('--scope <type>', 'Installation scope: user (user-wide) or local (project-only)', /^(user|local)$/i)
|
|
59
|
+
.option('--scope <type>', 'Installation scope: user or local (project-only)', /^(user|local)$/i)
|
|
125
60
|
.option('--verbose', 'Show detailed installation output')
|
|
61
|
+
.option('--plugin <names>', 'Install specific plugin(s), comma-separated (e.g., implement,code-review)')
|
|
62
|
+
.option('--teams', 'Enable Agent Teams (peer debate, adversarial review)')
|
|
63
|
+
.option('--no-teams', 'Disable Agent Teams (use parallel subagents instead)')
|
|
64
|
+
.option('--ambient', 'Enable ambient mode (auto-loads relevant skills for every prompt)')
|
|
65
|
+
.option('--no-ambient', 'Disable ambient mode')
|
|
66
|
+
.option('--memory', 'Enable working memory (session context preservation)')
|
|
67
|
+
.option('--no-memory', 'Disable working memory hooks')
|
|
126
68
|
.action(async (options) => {
|
|
127
69
|
// Get package version
|
|
128
70
|
const packageJsonPath = path.resolve(__dirname, '../../package.json');
|
|
@@ -135,68 +77,147 @@ export const initCommand = new Command('init')
|
|
|
135
77
|
version = 'unknown';
|
|
136
78
|
}
|
|
137
79
|
const verbose = options.verbose ?? false;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
80
|
+
// Start the CLI flow
|
|
81
|
+
p.intro(color.bgCyan(color.black(` DevFlow v${version} `)));
|
|
141
82
|
// Determine installation scope
|
|
142
|
-
let scope = 'user';
|
|
83
|
+
let scope = 'user';
|
|
143
84
|
if (options.scope) {
|
|
144
85
|
const normalizedScope = options.scope.toLowerCase();
|
|
145
|
-
// Runtime validation (Commander regex already validates, but be defensive)
|
|
146
86
|
if (normalizedScope !== 'user' && normalizedScope !== 'local') {
|
|
147
|
-
|
|
87
|
+
p.log.error('Invalid scope. Use "user" or "local"');
|
|
148
88
|
process.exit(1);
|
|
149
89
|
}
|
|
150
90
|
scope = normalizedScope;
|
|
151
91
|
}
|
|
92
|
+
else if (!process.stdin.isTTY) {
|
|
93
|
+
p.log.info('Non-interactive mode detected, using scope: user');
|
|
94
|
+
scope = 'user';
|
|
95
|
+
}
|
|
152
96
|
else {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
97
|
+
const selected = await p.select({
|
|
98
|
+
message: 'Installation scope',
|
|
99
|
+
options: [
|
|
100
|
+
{ value: 'user', label: 'User', hint: 'all projects (~/.claude/)' },
|
|
101
|
+
{ value: 'local', label: 'Local', hint: 'this project only (./.claude/)' },
|
|
102
|
+
],
|
|
103
|
+
});
|
|
104
|
+
if (p.isCancel(selected)) {
|
|
105
|
+
p.cancel('Installation cancelled.');
|
|
106
|
+
process.exit(0);
|
|
161
107
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
108
|
+
scope = selected;
|
|
109
|
+
}
|
|
110
|
+
// Select plugins to install
|
|
111
|
+
let selectedPlugins = [];
|
|
112
|
+
if (options.plugin) {
|
|
113
|
+
const { selected, invalid } = parsePluginSelection(options.plugin, DEVFLOW_PLUGINS);
|
|
114
|
+
selectedPlugins = selected;
|
|
115
|
+
if (invalid.length > 0) {
|
|
116
|
+
p.log.error(`Unknown plugin(s): ${invalid.join(', ')}`);
|
|
117
|
+
p.log.info(`Valid plugins: ${DEVFLOW_PLUGINS.map(pl => pl.name).join(', ')}`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else if (process.stdin.isTTY) {
|
|
122
|
+
const choices = DEVFLOW_PLUGINS
|
|
123
|
+
.filter(pl => pl.name !== 'devflow-core-skills')
|
|
124
|
+
.map(pl => ({
|
|
125
|
+
value: pl.name,
|
|
126
|
+
label: pl.name.replace('devflow-', ''),
|
|
127
|
+
hint: pl.description + (pl.optional ? ' (optional)' : ''),
|
|
128
|
+
}));
|
|
129
|
+
const preSelected = DEVFLOW_PLUGINS
|
|
130
|
+
.filter(pl => !pl.optional && pl.name !== 'devflow-core-skills')
|
|
131
|
+
.map(pl => pl.name);
|
|
132
|
+
const pluginSelection = await p.multiselect({
|
|
133
|
+
message: 'Select plugins to install',
|
|
134
|
+
options: choices,
|
|
135
|
+
initialValues: preSelected,
|
|
136
|
+
required: true,
|
|
137
|
+
});
|
|
138
|
+
if (p.isCancel(pluginSelection)) {
|
|
139
|
+
p.cancel('Installation cancelled.');
|
|
140
|
+
process.exit(0);
|
|
141
|
+
}
|
|
142
|
+
selectedPlugins = pluginSelection;
|
|
143
|
+
}
|
|
144
|
+
// Agent Teams variant selection
|
|
145
|
+
let teamsEnabled;
|
|
146
|
+
if (options.teams !== undefined) {
|
|
147
|
+
teamsEnabled = options.teams;
|
|
148
|
+
}
|
|
149
|
+
else if (!process.stdin.isTTY) {
|
|
150
|
+
teamsEnabled = false;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
const teamsChoice = await p.confirm({
|
|
154
|
+
message: 'Enable Agent Teams? (peer debate in review, exploration, debugging)',
|
|
155
|
+
initialValue: false,
|
|
156
|
+
});
|
|
157
|
+
if (p.isCancel(teamsChoice)) {
|
|
158
|
+
p.cancel('Installation cancelled.');
|
|
159
|
+
process.exit(0);
|
|
197
160
|
}
|
|
161
|
+
teamsEnabled = teamsChoice;
|
|
162
|
+
}
|
|
163
|
+
// Ambient mode selection
|
|
164
|
+
let ambientEnabled;
|
|
165
|
+
if (options.ambient !== undefined) {
|
|
166
|
+
ambientEnabled = options.ambient;
|
|
167
|
+
}
|
|
168
|
+
else if (!process.stdin.isTTY) {
|
|
169
|
+
ambientEnabled = false;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
const ambientChoice = await p.confirm({
|
|
173
|
+
message: 'Enable ambient mode? (auto-loads relevant skills based on each prompt)',
|
|
174
|
+
initialValue: false,
|
|
175
|
+
});
|
|
176
|
+
if (p.isCancel(ambientChoice)) {
|
|
177
|
+
p.cancel('Installation cancelled.');
|
|
178
|
+
process.exit(0);
|
|
179
|
+
}
|
|
180
|
+
ambientEnabled = ambientChoice;
|
|
181
|
+
}
|
|
182
|
+
// Working memory selection (defaults ON — foundational, unlike ambient's false)
|
|
183
|
+
let memoryEnabled;
|
|
184
|
+
if (options.memory !== undefined) {
|
|
185
|
+
memoryEnabled = options.memory;
|
|
186
|
+
}
|
|
187
|
+
else if (!process.stdin.isTTY) {
|
|
188
|
+
memoryEnabled = true;
|
|
198
189
|
}
|
|
199
|
-
|
|
190
|
+
else {
|
|
191
|
+
const memoryChoice = await p.confirm({
|
|
192
|
+
message: 'Enable working memory? (automatic session context preservation)',
|
|
193
|
+
initialValue: true,
|
|
194
|
+
});
|
|
195
|
+
if (p.isCancel(memoryChoice)) {
|
|
196
|
+
p.cancel('Installation cancelled.');
|
|
197
|
+
process.exit(0);
|
|
198
|
+
}
|
|
199
|
+
memoryEnabled = memoryChoice;
|
|
200
|
+
}
|
|
201
|
+
// Security deny list placement (user scope + TTY only)
|
|
202
|
+
let securityMode = 'user';
|
|
203
|
+
if (scope === 'user' && process.stdin.isTTY) {
|
|
204
|
+
const securityChoice = await p.select({
|
|
205
|
+
message: 'How should DevFlow install the security deny list?',
|
|
206
|
+
options: [
|
|
207
|
+
{ value: 'managed', label: 'Managed settings (Recommended)', hint: 'Cannot be overridden, requires admin' },
|
|
208
|
+
{ value: 'user', label: 'User settings', hint: 'Included in settings.json, editable' },
|
|
209
|
+
],
|
|
210
|
+
});
|
|
211
|
+
if (p.isCancel(securityChoice)) {
|
|
212
|
+
p.cancel('Installation cancelled.');
|
|
213
|
+
process.exit(0);
|
|
214
|
+
}
|
|
215
|
+
securityMode = securityChoice;
|
|
216
|
+
}
|
|
217
|
+
// Start spinner immediately after prompts — covers path resolution + git detection
|
|
218
|
+
const s = p.spinner();
|
|
219
|
+
s.start('Resolving paths');
|
|
220
|
+
// Get installation paths
|
|
200
221
|
let claudeDir;
|
|
201
222
|
let devflowDir;
|
|
202
223
|
let gitRoot = null;
|
|
@@ -204,468 +225,269 @@ export const initCommand = new Command('init')
|
|
|
204
225
|
const paths = await getInstallationPaths(scope);
|
|
205
226
|
claudeDir = paths.claudeDir;
|
|
206
227
|
devflowDir = paths.devflowDir;
|
|
207
|
-
|
|
208
|
-
gitRoot = await getGitRoot();
|
|
209
|
-
if (verbose) {
|
|
210
|
-
console.log(`📍 Installation scope: ${scope}`);
|
|
211
|
-
console.log(` Claude dir: ${claudeDir}`);
|
|
212
|
-
console.log(` DevFlow dir: ${devflowDir}\n`);
|
|
213
|
-
}
|
|
228
|
+
gitRoot = paths.gitRoot ?? await getGitRoot();
|
|
214
229
|
}
|
|
215
230
|
catch (error) {
|
|
216
|
-
|
|
231
|
+
s.stop('Path resolution failed');
|
|
232
|
+
p.log.error(`Path configuration error: ${error instanceof Error ? error.message : error}`);
|
|
217
233
|
process.exit(1);
|
|
218
234
|
}
|
|
219
|
-
//
|
|
220
|
-
|
|
235
|
+
// Validate target directory
|
|
236
|
+
s.message('Validating target directory');
|
|
237
|
+
if (scope === 'local') {
|
|
221
238
|
try {
|
|
222
|
-
await fs.
|
|
239
|
+
await fs.mkdir(claudeDir, { recursive: true });
|
|
223
240
|
}
|
|
224
|
-
catch {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
console.error(' Or set CLAUDE_CODE_DIR if installed elsewhere\n');
|
|
241
|
+
catch (error) {
|
|
242
|
+
s.stop('Installation failed');
|
|
243
|
+
p.log.error(`Failed to create ${claudeDir}: ${error}`);
|
|
228
244
|
process.exit(1);
|
|
229
245
|
}
|
|
230
|
-
if (verbose) {
|
|
231
|
-
console.log('✓ Claude Code detected');
|
|
232
|
-
}
|
|
233
246
|
}
|
|
234
247
|
else {
|
|
235
|
-
// Local scope - create .claude directory if it doesn't exist
|
|
236
248
|
try {
|
|
237
|
-
await fs.
|
|
238
|
-
if (verbose) {
|
|
239
|
-
console.log('✓ Local .claude directory ready');
|
|
240
|
-
}
|
|
249
|
+
await fs.access(claudeDir);
|
|
241
250
|
}
|
|
242
|
-
catch
|
|
243
|
-
|
|
251
|
+
catch {
|
|
252
|
+
s.stop('Installation failed');
|
|
253
|
+
p.log.error(`Claude Code not detected at ${claudeDir}`);
|
|
254
|
+
p.log.info('Install from: https://claude.ai/download');
|
|
244
255
|
process.exit(1);
|
|
245
256
|
}
|
|
246
257
|
}
|
|
247
|
-
//
|
|
258
|
+
// Resolve plugins and deduplication maps
|
|
259
|
+
s.message('Installing components');
|
|
248
260
|
const rootDir = path.resolve(__dirname, '../..');
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
target: path.join(claudeDir, 'skills'),
|
|
265
|
-
source: path.join(claudeSourceDir, 'skills', 'devflow'),
|
|
266
|
-
name: 'skills'
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
target: path.join(devflowDir, 'scripts'),
|
|
270
|
-
source: path.join(claudeSourceDir, 'scripts'),
|
|
271
|
-
name: 'scripts'
|
|
272
|
-
}
|
|
273
|
-
];
|
|
274
|
-
// Clean old DevFlow files before installing
|
|
275
|
-
for (const dir of devflowDirectories) {
|
|
276
|
-
if (dir.name === 'skills') {
|
|
277
|
-
// Special handling for skills: clean old nested structure and individual skills
|
|
278
|
-
// Remove old devflow/ subdirectory if it exists (migration from old structure)
|
|
279
|
-
const oldSkillsDir = path.join(claudeDir, 'skills', 'devflow');
|
|
280
|
-
try {
|
|
281
|
-
await fs.rm(oldSkillsDir, { recursive: true, force: true });
|
|
282
|
-
}
|
|
283
|
-
catch (e) {
|
|
284
|
-
// Directory might not exist
|
|
285
|
-
}
|
|
286
|
-
// Remove individual skill directories that we're about to reinstall
|
|
287
|
-
try {
|
|
288
|
-
const skillEntries = await fs.readdir(dir.source, { withFileTypes: true });
|
|
289
|
-
for (const entry of skillEntries) {
|
|
290
|
-
if (entry.isDirectory()) {
|
|
291
|
-
const skillTarget = path.join(dir.target, entry.name);
|
|
292
|
-
try {
|
|
293
|
-
await fs.rm(skillTarget, { recursive: true, force: true });
|
|
294
|
-
}
|
|
295
|
-
catch (e) {
|
|
296
|
-
// Skill might not exist
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
catch (e) {
|
|
302
|
-
// Source directory might not exist
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
else {
|
|
306
|
-
// For other components (commands, agents, scripts), clean the entire directory
|
|
307
|
-
try {
|
|
308
|
-
await fs.rm(dir.target, { recursive: true, force: true });
|
|
309
|
-
}
|
|
310
|
-
catch (e) {
|
|
311
|
-
// Directory might not exist on first install
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
// Install all DevFlow components
|
|
316
|
-
for (const dir of devflowDirectories) {
|
|
317
|
-
await fs.mkdir(dir.target, { recursive: true });
|
|
318
|
-
await copyDirectory(dir.source, dir.target);
|
|
319
|
-
}
|
|
320
|
-
// Make scripts executable
|
|
321
|
-
const scriptsDir = devflowDirectories.find(d => d.name === 'scripts').target;
|
|
322
|
-
const scripts = await fs.readdir(scriptsDir);
|
|
323
|
-
for (const script of scripts) {
|
|
324
|
-
await fs.chmod(path.join(scriptsDir, script), 0o755);
|
|
325
|
-
}
|
|
326
|
-
if (verbose) {
|
|
327
|
-
console.log('✓ Installing components... (commands, agents, skills, scripts)');
|
|
261
|
+
const pluginsDir = path.join(rootDir, 'plugins');
|
|
262
|
+
let pluginsToInstall = selectedPlugins.length > 0
|
|
263
|
+
? DEVFLOW_PLUGINS.filter(p => selectedPlugins.includes(p.name))
|
|
264
|
+
: DEVFLOW_PLUGINS.filter(p => !p.optional);
|
|
265
|
+
const coreSkillsPlugin = DEVFLOW_PLUGINS.find(p => p.name === 'devflow-core-skills');
|
|
266
|
+
if (pluginsToInstall.length > 0 && coreSkillsPlugin && !pluginsToInstall.includes(coreSkillsPlugin)) {
|
|
267
|
+
pluginsToInstall = [coreSkillsPlugin, ...pluginsToInstall];
|
|
268
|
+
}
|
|
269
|
+
const { skillsMap, agentsMap } = buildAssetMaps(pluginsToInstall);
|
|
270
|
+
// Install: try native CLI first, fall back to file copy
|
|
271
|
+
const cliAvailable = isClaudeCliAvailable();
|
|
272
|
+
const usedNativeCli = cliAvailable && installViaCli(pluginsToInstall, scope, s);
|
|
273
|
+
if (!usedNativeCli) {
|
|
274
|
+
if (cliAvailable && verbose) {
|
|
275
|
+
p.log.warn('Claude CLI installation failed, falling back to manual copy');
|
|
328
276
|
}
|
|
329
|
-
// Install settings.json - never override existing files (atomic operation)
|
|
330
|
-
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
331
|
-
const devflowSettingsPath = path.join(claudeDir, 'settings.devflow.json');
|
|
332
|
-
const sourceSettingsPath = path.join(claudeSourceDir, 'settings.json');
|
|
333
|
-
// Read template and replace ~ with actual home directory
|
|
334
|
-
const settingsTemplate = await fs.readFile(sourceSettingsPath, 'utf-8');
|
|
335
|
-
const settingsContent = settingsTemplate.replace(/~\/\.devflow\/scripts\/statusline\.sh/g, path.join(devflowDir, 'scripts', 'statusline.sh'));
|
|
336
|
-
let settingsExists = false;
|
|
337
277
|
try {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
278
|
+
await installViaFileCopy({
|
|
279
|
+
plugins: pluginsToInstall,
|
|
280
|
+
claudeDir,
|
|
281
|
+
pluginsDir,
|
|
282
|
+
rootDir,
|
|
283
|
+
devflowDir,
|
|
284
|
+
skillsMap,
|
|
285
|
+
agentsMap,
|
|
286
|
+
isPartialInstall: !!options.plugin,
|
|
287
|
+
teamsEnabled,
|
|
288
|
+
spinner: s,
|
|
289
|
+
});
|
|
343
290
|
}
|
|
344
291
|
catch (error) {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
await fs.writeFile(devflowSettingsPath, settingsContent, 'utf-8');
|
|
349
|
-
if (verbose) {
|
|
350
|
-
console.log('⚠️ Existing settings.json preserved → DevFlow config: settings.devflow.json');
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
else {
|
|
354
|
-
throw error;
|
|
355
|
-
}
|
|
292
|
+
s.stop('Installation failed');
|
|
293
|
+
p.log.error(`${error}`);
|
|
294
|
+
process.exit(1);
|
|
356
295
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
296
|
+
}
|
|
297
|
+
s.stop('Plugins installed');
|
|
298
|
+
// Clean up stale skills from previous installations
|
|
299
|
+
const skillsDir = path.join(claudeDir, 'skills');
|
|
300
|
+
let staleRemoved = 0;
|
|
301
|
+
for (const legacy of LEGACY_SKILL_NAMES) {
|
|
302
|
+
const legacyPath = path.join(skillsDir, legacy);
|
|
362
303
|
try {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
await fs.writeFile(claudeMdPath, content, { encoding: 'utf-8', flag: 'wx' });
|
|
366
|
-
if (verbose) {
|
|
367
|
-
console.log('✓ CLAUDE.md configured');
|
|
368
|
-
}
|
|
304
|
+
await fs.rm(legacyPath, { recursive: true });
|
|
305
|
+
staleRemoved++;
|
|
369
306
|
}
|
|
370
|
-
catch
|
|
371
|
-
|
|
372
|
-
// Existing CLAUDE.md found - install as CLAUDE.devflow.md
|
|
373
|
-
claudeMdExists = true;
|
|
374
|
-
await fs.copyFile(sourceClaudeMdPath, devflowClaudeMdPath);
|
|
375
|
-
if (verbose) {
|
|
376
|
-
console.log('⚠️ Existing CLAUDE.md preserved → DevFlow guide: CLAUDE.devflow.md');
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
else {
|
|
380
|
-
throw error;
|
|
381
|
-
}
|
|
307
|
+
catch {
|
|
308
|
+
// Doesn't exist — expected for most entries
|
|
382
309
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
310
|
+
}
|
|
311
|
+
if (staleRemoved > 0 && verbose) {
|
|
312
|
+
p.log.info(`Cleaned up ${staleRemoved} legacy skill(s)`);
|
|
313
|
+
}
|
|
314
|
+
// Clean up stale commands from previous installations (e.g., /review → /code-review)
|
|
315
|
+
const commandsDir = path.join(claudeDir, 'commands', 'devflow');
|
|
316
|
+
let staleCommandsRemoved = 0;
|
|
317
|
+
for (const legacy of LEGACY_COMMAND_NAMES) {
|
|
318
|
+
for (const suffix of ['.md', '-teams.md']) {
|
|
319
|
+
const legacyPath = path.join(commandsDir, `${legacy}${suffix}`);
|
|
320
|
+
try {
|
|
321
|
+
await fs.rm(legacyPath);
|
|
322
|
+
staleCommandsRemoved++;
|
|
323
|
+
}
|
|
324
|
+
catch {
|
|
325
|
+
// Doesn't exist — expected for most entries
|
|
389
326
|
}
|
|
390
|
-
const claudeignorePath = path.join(gitRoot, '.claudeignore');
|
|
391
|
-
// Atomic exclusive create - only create if doesn't exist
|
|
392
|
-
const claudeignoreContent = `# DevFlow .claudeignore - Protects against sensitive files and context pollution
|
|
393
|
-
# Generated by DevFlow - Edit as needed for your project
|
|
394
|
-
|
|
395
|
-
# === SECURITY: Sensitive Files ===
|
|
396
|
-
# Environment and secrets
|
|
397
|
-
.env
|
|
398
|
-
.env.*
|
|
399
|
-
.env.local
|
|
400
|
-
.env.*.local
|
|
401
|
-
*.env
|
|
402
|
-
.envrc
|
|
403
|
-
|
|
404
|
-
# Credentials and keys
|
|
405
|
-
*.key
|
|
406
|
-
*.pem
|
|
407
|
-
*.p12
|
|
408
|
-
*.pfx
|
|
409
|
-
*.cer
|
|
410
|
-
*.crt
|
|
411
|
-
*.der
|
|
412
|
-
id_rsa
|
|
413
|
-
id_dsa
|
|
414
|
-
id_ecdsa
|
|
415
|
-
id_ed25519
|
|
416
|
-
*.ppk
|
|
417
|
-
*_rsa
|
|
418
|
-
*_dsa
|
|
419
|
-
*secret*
|
|
420
|
-
*password*
|
|
421
|
-
*credential*
|
|
422
|
-
credentials.json
|
|
423
|
-
secrets.json
|
|
424
|
-
secrets.yaml
|
|
425
|
-
secrets.yml
|
|
426
|
-
|
|
427
|
-
# Cloud provider credentials
|
|
428
|
-
.aws/credentials
|
|
429
|
-
.aws/config
|
|
430
|
-
.gcp/credentials.json
|
|
431
|
-
.azure/credentials
|
|
432
|
-
|
|
433
|
-
# Package manager credentials
|
|
434
|
-
.npmrc
|
|
435
|
-
.pypirc
|
|
436
|
-
.gem/credentials
|
|
437
|
-
pip.conf
|
|
438
|
-
|
|
439
|
-
# Database
|
|
440
|
-
*.sql
|
|
441
|
-
*.db
|
|
442
|
-
*.sqlite
|
|
443
|
-
*.sqlite3
|
|
444
|
-
|
|
445
|
-
# === DEPENDENCIES & BUILD ===
|
|
446
|
-
# Node.js
|
|
447
|
-
node_modules/
|
|
448
|
-
npm-debug.log*
|
|
449
|
-
yarn-debug.log*
|
|
450
|
-
yarn-error.log*
|
|
451
|
-
pnpm-debug.log*
|
|
452
|
-
.pnpm-store/
|
|
453
|
-
|
|
454
|
-
# Python
|
|
455
|
-
__pycache__/
|
|
456
|
-
*.py[cod]
|
|
457
|
-
*$py.class
|
|
458
|
-
.Python
|
|
459
|
-
env/
|
|
460
|
-
venv/
|
|
461
|
-
ENV/
|
|
462
|
-
.venv/
|
|
463
|
-
pip-log.txt
|
|
464
|
-
pip-delete-this-directory.txt
|
|
465
|
-
.eggs/
|
|
466
|
-
*.egg-info/
|
|
467
|
-
dist/
|
|
468
|
-
build/
|
|
469
|
-
*.whl
|
|
470
|
-
|
|
471
|
-
# Ruby
|
|
472
|
-
vendor/bundle/
|
|
473
|
-
.bundle/
|
|
474
|
-
|
|
475
|
-
# Go
|
|
476
|
-
vendor/
|
|
477
|
-
go.sum
|
|
478
|
-
|
|
479
|
-
# Rust
|
|
480
|
-
target/
|
|
481
|
-
Cargo.lock
|
|
482
|
-
|
|
483
|
-
# Java
|
|
484
|
-
target/
|
|
485
|
-
*.class
|
|
486
|
-
*.jar
|
|
487
|
-
*.war
|
|
488
|
-
|
|
489
|
-
# PHP
|
|
490
|
-
vendor/
|
|
491
|
-
composer.lock
|
|
492
|
-
|
|
493
|
-
# === BUILD ARTIFACTS ===
|
|
494
|
-
dist/
|
|
495
|
-
build/
|
|
496
|
-
out/
|
|
497
|
-
.next/
|
|
498
|
-
.nuxt/
|
|
499
|
-
.output/
|
|
500
|
-
.vite/
|
|
501
|
-
.cache/
|
|
502
|
-
.parcel-cache/
|
|
503
|
-
.turbo/
|
|
504
|
-
*.tsbuildinfo
|
|
505
|
-
|
|
506
|
-
# === LOGS & TEMP FILES ===
|
|
507
|
-
logs/
|
|
508
|
-
*.log
|
|
509
|
-
*.tmp
|
|
510
|
-
*.temp
|
|
511
|
-
*.swp
|
|
512
|
-
*.swo
|
|
513
|
-
*~
|
|
514
|
-
.DS_Store
|
|
515
|
-
Thumbs.db
|
|
516
|
-
*.bak
|
|
517
|
-
*.orig
|
|
518
|
-
*.rej
|
|
519
|
-
.cache
|
|
520
|
-
|
|
521
|
-
# === VERSION CONTROL ===
|
|
522
|
-
.git/
|
|
523
|
-
.svn/
|
|
524
|
-
.hg/
|
|
525
|
-
.gitignore
|
|
526
|
-
|
|
527
|
-
# === IDE & EDITORS ===
|
|
528
|
-
.vscode/
|
|
529
|
-
.idea/
|
|
530
|
-
*.sublime-*
|
|
531
|
-
*.code-workspace
|
|
532
|
-
.project
|
|
533
|
-
.classpath
|
|
534
|
-
.settings/
|
|
535
|
-
|
|
536
|
-
# === TEST COVERAGE ===
|
|
537
|
-
coverage/
|
|
538
|
-
.nyc_output/
|
|
539
|
-
htmlcov/
|
|
540
|
-
.coverage
|
|
541
|
-
.pytest_cache/
|
|
542
|
-
.tox/
|
|
543
|
-
|
|
544
|
-
# === OS-SPECIFIC ===
|
|
545
|
-
.DS_Store
|
|
546
|
-
.AppleDouble
|
|
547
|
-
.LSOverride
|
|
548
|
-
Thumbs.db
|
|
549
|
-
ehthumbs.db
|
|
550
|
-
Desktop.ini
|
|
551
|
-
|
|
552
|
-
# === MEDIA & LARGE FILES ===
|
|
553
|
-
*.mp4
|
|
554
|
-
*.avi
|
|
555
|
-
*.mov
|
|
556
|
-
*.wmv
|
|
557
|
-
*.flv
|
|
558
|
-
*.mp3
|
|
559
|
-
*.wav
|
|
560
|
-
*.zip
|
|
561
|
-
*.tar.gz
|
|
562
|
-
*.rar
|
|
563
|
-
*.7z
|
|
564
|
-
*.dmg
|
|
565
|
-
*.iso
|
|
566
|
-
|
|
567
|
-
# === DOCUMENTATION BUILD ===
|
|
568
|
-
site/
|
|
569
|
-
_site/
|
|
570
|
-
.docusaurus/
|
|
571
|
-
.vuepress/dist/
|
|
572
|
-
|
|
573
|
-
# === LOCK FILES (usually not needed for AI context) ===
|
|
574
|
-
package-lock.json
|
|
575
|
-
yarn.lock
|
|
576
|
-
pnpm-lock.yaml
|
|
577
|
-
Gemfile.lock
|
|
578
|
-
poetry.lock
|
|
579
|
-
Pipfile.lock
|
|
580
|
-
`;
|
|
581
|
-
// Atomic exclusive create - fails if file already exists
|
|
582
|
-
await fs.writeFile(claudeignorePath, claudeignoreContent, { encoding: 'utf-8', flag: 'wx' });
|
|
583
|
-
claudeignoreCreated = true;
|
|
584
327
|
}
|
|
585
|
-
|
|
586
|
-
|
|
328
|
+
}
|
|
329
|
+
if (staleCommandsRemoved > 0 && verbose) {
|
|
330
|
+
p.log.info(`Cleaned up ${staleCommandsRemoved} legacy command(s)`);
|
|
331
|
+
}
|
|
332
|
+
// === Configuration extras ===
|
|
333
|
+
const extrasOptions = buildExtrasOptions(scope, gitRoot);
|
|
334
|
+
let selectedExtras;
|
|
335
|
+
if (process.stdin.isTTY) {
|
|
336
|
+
const extrasSelection = await p.multiselect({
|
|
337
|
+
message: 'Configure extras',
|
|
338
|
+
options: extrasOptions,
|
|
339
|
+
initialValues: extrasOptions.map(o => o.value),
|
|
340
|
+
required: false,
|
|
341
|
+
});
|
|
342
|
+
if (p.isCancel(extrasSelection)) {
|
|
343
|
+
p.cancel('Installation cancelled.');
|
|
344
|
+
process.exit(0);
|
|
587
345
|
}
|
|
588
|
-
|
|
589
|
-
|
|
346
|
+
selectedExtras = extrasSelection;
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
selectedExtras = extrasOptions.map(o => o.value);
|
|
350
|
+
}
|
|
351
|
+
// Settings may trigger its own TTY sub-prompt — run outside spinner
|
|
352
|
+
if (selectedExtras.includes('settings')) {
|
|
353
|
+
// Attempt managed settings write if user chose managed mode
|
|
354
|
+
let effectiveSecurityMode = securityMode;
|
|
355
|
+
if (securityMode === 'managed') {
|
|
356
|
+
const managed = await installManagedSettings(rootDir, verbose);
|
|
357
|
+
if (!managed) {
|
|
358
|
+
p.log.warn('Managed settings write failed — falling back to user settings');
|
|
359
|
+
effectiveSecurityMode = 'user';
|
|
360
|
+
}
|
|
590
361
|
}
|
|
591
|
-
|
|
592
|
-
|
|
362
|
+
await installSettings(claudeDir, rootDir, devflowDir, verbose, teamsEnabled, effectiveSecurityMode);
|
|
363
|
+
// Install ambient hook if enabled
|
|
364
|
+
if (ambientEnabled) {
|
|
365
|
+
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
593
366
|
try {
|
|
594
|
-
const
|
|
595
|
-
const
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
gitignoreContent = await fs.readFile(gitignorePath, 'utf-8');
|
|
599
|
-
}
|
|
600
|
-
catch {
|
|
601
|
-
// .gitignore doesn't exist, will create it
|
|
602
|
-
}
|
|
603
|
-
const linesToAdd = [];
|
|
604
|
-
for (const entry of entriesToAdd) {
|
|
605
|
-
// Check if entry already exists (exact match or pattern)
|
|
606
|
-
if (!gitignoreContent.split('\n').some(line => line.trim() === entry)) {
|
|
607
|
-
linesToAdd.push(entry);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
if (linesToAdd.length > 0) {
|
|
611
|
-
const newContent = gitignoreContent
|
|
612
|
-
? `${gitignoreContent.trimEnd()}\n\n# DevFlow local scope installation\n${linesToAdd.join('\n')}\n`
|
|
613
|
-
: `# DevFlow local scope installation\n${linesToAdd.join('\n')}\n`;
|
|
614
|
-
await fs.writeFile(gitignorePath, newContent, 'utf-8');
|
|
367
|
+
const content = await fs.readFile(settingsPath, 'utf-8');
|
|
368
|
+
const updated = addAmbientHook(content, devflowDir);
|
|
369
|
+
if (updated !== content) {
|
|
370
|
+
await fs.writeFile(settingsPath, updated, 'utf-8');
|
|
615
371
|
if (verbose) {
|
|
616
|
-
|
|
372
|
+
p.log.success('Ambient mode hook installed');
|
|
617
373
|
}
|
|
618
374
|
}
|
|
619
375
|
}
|
|
620
|
-
catch
|
|
376
|
+
catch { /* settings.json may not exist yet */ }
|
|
377
|
+
}
|
|
378
|
+
// Manage memory hooks based on user choice
|
|
379
|
+
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
380
|
+
try {
|
|
381
|
+
const content = await fs.readFile(settingsPath, 'utf-8');
|
|
382
|
+
const updated = memoryEnabled
|
|
383
|
+
? addMemoryHooks(content, devflowDir)
|
|
384
|
+
: removeMemoryHooks(content);
|
|
385
|
+
if (updated !== content) {
|
|
386
|
+
await fs.writeFile(settingsPath, updated, 'utf-8');
|
|
621
387
|
if (verbose) {
|
|
622
|
-
|
|
388
|
+
p.log.info(`Working memory ${memoryEnabled ? 'enabled' : 'disabled'}`);
|
|
623
389
|
}
|
|
624
390
|
}
|
|
625
391
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
if (
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
await fs.mkdir(path.join(docsDir, 'status', 'compact'), { recursive: true });
|
|
632
|
-
await fs.mkdir(path.join(docsDir, 'reviews'), { recursive: true });
|
|
633
|
-
await fs.mkdir(path.join(docsDir, 'audits', 'standalone'), { recursive: true });
|
|
634
|
-
await fs.mkdir(path.join(docsDir, 'releases'), { recursive: true });
|
|
635
|
-
docsCreated = true;
|
|
636
|
-
}
|
|
637
|
-
catch (error) {
|
|
638
|
-
// .docs/ structure may already exist
|
|
639
|
-
}
|
|
392
|
+
catch { /* settings.json may not exist yet */ }
|
|
393
|
+
// Ensure .memory/ exists when memory is enabled (hooks are no-ops without it)
|
|
394
|
+
if (memoryEnabled) {
|
|
395
|
+
await createMemoryDir(verbose);
|
|
396
|
+
await migrateMemoryFiles(verbose);
|
|
640
397
|
}
|
|
641
|
-
|
|
642
|
-
|
|
398
|
+
}
|
|
399
|
+
const fileExtras = selectedExtras.filter(e => e !== 'settings' && e !== 'safe-delete');
|
|
400
|
+
if (fileExtras.length > 0) {
|
|
401
|
+
const sExtras = p.spinner();
|
|
402
|
+
sExtras.start('Configuring extras');
|
|
403
|
+
if (selectedExtras.includes('claudeignore') && gitRoot) {
|
|
404
|
+
await installClaudeignore(gitRoot, rootDir, verbose);
|
|
643
405
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
renderVerboseOutput(version, scope, claudeDir, devflowDir, settingsExists, claudeMdExists);
|
|
406
|
+
if (selectedExtras.includes('gitignore') && gitRoot) {
|
|
407
|
+
await updateGitignore(gitRoot, verbose);
|
|
647
408
|
}
|
|
648
|
-
|
|
649
|
-
|
|
409
|
+
if (selectedExtras.includes('docs')) {
|
|
410
|
+
await createDocsStructure(verbose);
|
|
650
411
|
}
|
|
412
|
+
sExtras.stop('Extras configured');
|
|
651
413
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
414
|
+
// Summary output
|
|
415
|
+
if (usedNativeCli) {
|
|
416
|
+
p.log.success('Installed via Claude plugin system');
|
|
655
417
|
}
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
const
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
418
|
+
else if (!cliAvailable) {
|
|
419
|
+
p.log.info('Installed via file copy (Claude CLI not available)');
|
|
420
|
+
}
|
|
421
|
+
const installedCommands = pluginsToInstall.flatMap(p => p.commands).filter(c => c.length > 0);
|
|
422
|
+
if (installedCommands.length > 0) {
|
|
423
|
+
const commandsNote = installedCommands
|
|
424
|
+
.map(cmd => color.cyan(cmd))
|
|
425
|
+
.join(' ');
|
|
426
|
+
p.note(commandsNote, 'Available commands');
|
|
427
|
+
}
|
|
428
|
+
// Safe-delete auto-install (gated by extras selection)
|
|
429
|
+
if (selectedExtras.includes('safe-delete')) {
|
|
430
|
+
const platform = detectPlatform();
|
|
431
|
+
const shell = detectShell();
|
|
432
|
+
const safeDeleteInfo = getSafeDeleteInfo(platform);
|
|
433
|
+
const safeDeleteAvailable = hasSafeDelete(platform);
|
|
434
|
+
const profilePath = getProfilePath(shell);
|
|
435
|
+
if (process.stdin.isTTY && profilePath) {
|
|
436
|
+
if (!safeDeleteAvailable && safeDeleteInfo.installHint) {
|
|
437
|
+
p.log.info(`Install ${color.cyan(safeDeleteInfo.command ?? 'trash')} first: ${color.dim(safeDeleteInfo.installHint)}`);
|
|
438
|
+
p.log.info(`Then re-run ${color.cyan('devflow init')} to auto-configure safe-delete.`);
|
|
439
|
+
}
|
|
440
|
+
else if (safeDeleteAvailable) {
|
|
441
|
+
const trashCmd = safeDeleteInfo.command;
|
|
442
|
+
const block = generateSafeDeleteBlock(shell, process.platform, trashCmd);
|
|
443
|
+
if (block) {
|
|
444
|
+
const installedVersion = await getInstalledVersion(profilePath);
|
|
445
|
+
if (installedVersion === SAFE_DELETE_BLOCK_VERSION) {
|
|
446
|
+
p.log.info(`Safe-delete already configured in ${color.dim(profilePath)}`);
|
|
447
|
+
}
|
|
448
|
+
else if (installedVersion > 0) {
|
|
449
|
+
await removeFromProfile(profilePath);
|
|
450
|
+
await installToProfile(profilePath, block);
|
|
451
|
+
p.log.success(`Safe-delete upgraded in ${color.dim(profilePath)}`);
|
|
452
|
+
p.log.info('Restart your shell or run: ' + color.cyan(`source ${profilePath}`));
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
const confirm = await p.confirm({
|
|
456
|
+
message: `Install safe-delete to ${profilePath}? (overrides rm to use ${trashCmd ?? 'recycle bin'})`,
|
|
457
|
+
initialValue: true,
|
|
458
|
+
});
|
|
459
|
+
if (!p.isCancel(confirm) && confirm) {
|
|
460
|
+
await installToProfile(profilePath, block);
|
|
461
|
+
p.log.success(`Safe-delete installed to ${color.dim(profilePath)}`);
|
|
462
|
+
p.log.info('Restart your shell or run: ' + color.cyan(`source ${profilePath}`));
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
665
467
|
}
|
|
666
|
-
else {
|
|
667
|
-
|
|
468
|
+
else if (!process.stdin.isTTY) {
|
|
469
|
+
if (safeDeleteAvailable && safeDeleteInfo.command) {
|
|
470
|
+
p.log.info(`Safe-delete available (${safeDeleteInfo.command}). Run interactively to auto-install.`);
|
|
471
|
+
}
|
|
472
|
+
else if (safeDeleteInfo.installHint) {
|
|
473
|
+
p.log.info(`Protect against accidental ${color.red('rm -rf')}: ${color.cyan(safeDeleteInfo.installHint)}`);
|
|
474
|
+
}
|
|
668
475
|
}
|
|
669
476
|
}
|
|
670
|
-
|
|
477
|
+
// Verbose mode: show details
|
|
478
|
+
if (verbose) {
|
|
479
|
+
const pluginsList = pluginsToInstall
|
|
480
|
+
.map(plugin => `${color.yellow(plugin.name.padEnd(24))}${color.dim(plugin.description)}`)
|
|
481
|
+
.join('\n');
|
|
482
|
+
p.note(pluginsList, 'Installed plugins');
|
|
483
|
+
p.log.info(`Scope: ${scope}`);
|
|
484
|
+
p.log.info(`Claude dir: ${claudeDir}`);
|
|
485
|
+
p.log.info(`DevFlow dir: ${devflowDir}`);
|
|
486
|
+
const totalSkillDeclarations = pluginsToInstall.reduce((sum, p) => sum + p.skills.length, 0);
|
|
487
|
+
const totalAgentDeclarations = pluginsToInstall.reduce((sum, p) => sum + p.agents.length, 0);
|
|
488
|
+
p.log.info(`Deduplication: ${skillsMap.size} unique skills (from ${totalSkillDeclarations} declarations)`);
|
|
489
|
+
p.log.info(`Deduplication: ${agentsMap.size} unique agents (from ${totalAgentDeclarations} declarations)`);
|
|
490
|
+
}
|
|
491
|
+
p.outro(color.green('Ready! Run any command in Claude Code to get started.'));
|
|
492
|
+
});
|
|
671
493
|
//# sourceMappingURL=init.js.map
|