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.
Files changed (414) hide show
  1. package/CHANGELOG.md +197 -29
  2. package/LICENSE +1 -1
  3. package/README.md +185 -309
  4. package/dist/cli.js +7 -1
  5. package/dist/commands/ambient.d.ts +18 -0
  6. package/dist/commands/ambient.js +136 -0
  7. package/dist/commands/init.d.ts +23 -0
  8. package/dist/commands/init.js +393 -571
  9. package/dist/commands/list.d.ts +3 -0
  10. package/dist/commands/list.js +20 -0
  11. package/dist/commands/memory.d.ts +22 -0
  12. package/dist/commands/memory.js +175 -0
  13. package/dist/commands/uninstall.d.ts +10 -0
  14. package/dist/commands/uninstall.js +418 -78
  15. package/dist/plugins.d.ts +46 -0
  16. package/dist/plugins.js +169 -0
  17. package/dist/utils/cli.d.ts +5 -0
  18. package/dist/utils/cli.js +14 -0
  19. package/dist/utils/installer.d.ts +41 -0
  20. package/dist/utils/installer.js +177 -0
  21. package/dist/utils/paths.d.ts +10 -0
  22. package/dist/utils/paths.js +23 -3
  23. package/dist/utils/post-install.d.ts +80 -0
  24. package/dist/utils/post-install.js +508 -0
  25. package/dist/utils/safe-delete-install.d.ts +29 -0
  26. package/dist/utils/safe-delete-install.js +191 -0
  27. package/dist/utils/safe-delete.d.ts +12 -0
  28. package/dist/utils/safe-delete.js +83 -0
  29. package/package.json +18 -8
  30. package/plugins/devflow-ambient/.claude-plugin/plugin.json +7 -0
  31. package/plugins/devflow-ambient/README.md +49 -0
  32. package/plugins/devflow-ambient/commands/ambient.md +110 -0
  33. package/plugins/devflow-ambient/skills/ambient-router/SKILL.md +89 -0
  34. package/plugins/devflow-ambient/skills/ambient-router/references/skill-catalog.md +64 -0
  35. package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +7 -0
  36. package/plugins/devflow-audit-claude/README.md +46 -0
  37. package/plugins/devflow-audit-claude/agents/claude-md-auditor.md +134 -0
  38. package/plugins/devflow-audit-claude/commands/audit-claude.md +85 -0
  39. package/plugins/devflow-code-review/.claude-plugin/plugin.json +31 -0
  40. package/plugins/devflow-code-review/README.md +73 -0
  41. package/plugins/devflow-code-review/agents/git.md +272 -0
  42. package/plugins/devflow-code-review/agents/reviewer.md +119 -0
  43. package/plugins/devflow-code-review/agents/synthesizer.md +204 -0
  44. package/plugins/devflow-code-review/commands/code-review-teams.md +262 -0
  45. package/plugins/devflow-code-review/commands/code-review.md +141 -0
  46. package/plugins/devflow-code-review/skills/accessibility/SKILL.md +229 -0
  47. package/plugins/devflow-code-review/skills/accessibility/references/detection.md +171 -0
  48. package/plugins/devflow-code-review/skills/accessibility/references/patterns.md +670 -0
  49. package/plugins/devflow-code-review/skills/accessibility/references/violations.md +419 -0
  50. package/plugins/devflow-code-review/skills/agent-teams/SKILL.md +124 -0
  51. package/plugins/devflow-code-review/skills/agent-teams/references/cleanup.md +104 -0
  52. package/plugins/devflow-code-review/skills/agent-teams/references/communication.md +122 -0
  53. package/plugins/devflow-code-review/skills/agent-teams/references/team-patterns.md +217 -0
  54. package/plugins/devflow-code-review/skills/architecture-patterns/SKILL.md +153 -0
  55. package/plugins/devflow-code-review/skills/architecture-patterns/references/detection.md +337 -0
  56. package/plugins/devflow-code-review/skills/architecture-patterns/references/patterns.md +873 -0
  57. package/plugins/devflow-code-review/skills/architecture-patterns/references/violations.md +575 -0
  58. package/plugins/devflow-code-review/skills/complexity-patterns/SKILL.md +143 -0
  59. package/plugins/devflow-code-review/skills/complexity-patterns/references/detection.md +264 -0
  60. package/plugins/devflow-code-review/skills/complexity-patterns/references/patterns.md +487 -0
  61. package/plugins/devflow-code-review/skills/complexity-patterns/references/violations.md +361 -0
  62. package/plugins/devflow-code-review/skills/consistency-patterns/SKILL.md +140 -0
  63. package/plugins/devflow-code-review/skills/consistency-patterns/references/detection.md +207 -0
  64. package/plugins/devflow-code-review/skills/consistency-patterns/references/patterns.md +202 -0
  65. package/plugins/devflow-code-review/skills/consistency-patterns/references/violations.md +213 -0
  66. package/plugins/devflow-code-review/skills/database-patterns/SKILL.md +134 -0
  67. package/plugins/devflow-code-review/skills/database-patterns/references/detection.md +208 -0
  68. package/plugins/devflow-code-review/skills/database-patterns/references/patterns.md +394 -0
  69. package/plugins/devflow-code-review/skills/database-patterns/references/violations.md +332 -0
  70. package/plugins/devflow-code-review/skills/dependencies-patterns/SKILL.md +141 -0
  71. package/plugins/devflow-code-review/skills/dependencies-patterns/references/detection.md +181 -0
  72. package/plugins/devflow-code-review/skills/dependencies-patterns/references/patterns.md +225 -0
  73. package/plugins/devflow-code-review/skills/dependencies-patterns/references/violations.md +247 -0
  74. package/plugins/devflow-code-review/skills/documentation-patterns/SKILL.md +125 -0
  75. package/plugins/devflow-code-review/skills/documentation-patterns/references/detection.md +190 -0
  76. package/plugins/devflow-code-review/skills/documentation-patterns/references/patterns.md +189 -0
  77. package/plugins/devflow-code-review/skills/documentation-patterns/references/violations.md +163 -0
  78. package/plugins/devflow-code-review/skills/frontend-design/SKILL.md +254 -0
  79. package/plugins/devflow-code-review/skills/frontend-design/references/detection.md +184 -0
  80. package/plugins/devflow-code-review/skills/frontend-design/references/patterns.md +511 -0
  81. package/plugins/devflow-code-review/skills/frontend-design/references/violations.md +453 -0
  82. package/plugins/devflow-code-review/skills/performance-patterns/SKILL.md +154 -0
  83. package/plugins/devflow-code-review/skills/performance-patterns/references/detection.md +351 -0
  84. package/plugins/devflow-code-review/skills/performance-patterns/references/patterns.md +503 -0
  85. package/plugins/devflow-code-review/skills/performance-patterns/references/violations.md +354 -0
  86. package/plugins/devflow-code-review/skills/react/SKILL.md +276 -0
  87. package/plugins/devflow-code-review/skills/react/references/patterns.md +1331 -0
  88. package/plugins/devflow-code-review/skills/react/references/violations.md +565 -0
  89. package/plugins/devflow-code-review/skills/regression-patterns/SKILL.md +146 -0
  90. package/plugins/devflow-code-review/skills/regression-patterns/references/detection.md +237 -0
  91. package/plugins/devflow-code-review/skills/regression-patterns/references/patterns.md +226 -0
  92. package/plugins/devflow-code-review/skills/regression-patterns/references/violations.md +225 -0
  93. package/plugins/devflow-code-review/skills/review-methodology/SKILL.md +119 -0
  94. package/plugins/devflow-code-review/skills/review-methodology/references/patterns.md +186 -0
  95. package/plugins/devflow-code-review/skills/review-methodology/references/report-template.md +142 -0
  96. package/plugins/devflow-code-review/skills/review-methodology/references/violations.md +125 -0
  97. package/plugins/devflow-code-review/skills/security-patterns/SKILL.md +156 -0
  98. package/plugins/devflow-code-review/skills/security-patterns/references/detection.md +287 -0
  99. package/plugins/devflow-code-review/skills/security-patterns/references/patterns.md +507 -0
  100. package/plugins/devflow-code-review/skills/security-patterns/references/violations.md +237 -0
  101. package/plugins/devflow-code-review/skills/test-patterns/SKILL.md +183 -0
  102. package/plugins/devflow-code-review/skills/test-patterns/references/detection.md +149 -0
  103. package/plugins/devflow-code-review/skills/test-patterns/references/patterns.md +220 -0
  104. package/plugins/devflow-code-review/skills/test-patterns/references/report-template.md +108 -0
  105. package/plugins/devflow-code-review/skills/test-patterns/references/violations.md +221 -0
  106. package/plugins/devflow-core-skills/.claude-plugin/plugin.json +28 -0
  107. package/plugins/devflow-core-skills/README.md +50 -0
  108. package/plugins/devflow-core-skills/skills/accessibility/SKILL.md +229 -0
  109. package/plugins/devflow-core-skills/skills/accessibility/references/detection.md +171 -0
  110. package/plugins/devflow-core-skills/skills/accessibility/references/patterns.md +670 -0
  111. package/plugins/devflow-core-skills/skills/accessibility/references/violations.md +419 -0
  112. package/plugins/devflow-core-skills/skills/core-patterns/SKILL.md +162 -0
  113. package/plugins/devflow-core-skills/skills/core-patterns/references/checklist.md +276 -0
  114. package/plugins/devflow-core-skills/skills/core-patterns/references/code-smell-violations.md +144 -0
  115. package/plugins/devflow-core-skills/skills/core-patterns/references/detection.md +303 -0
  116. package/plugins/devflow-core-skills/skills/core-patterns/references/patterns.md +576 -0
  117. package/plugins/devflow-core-skills/skills/core-patterns/references/violations.md +369 -0
  118. package/plugins/devflow-core-skills/skills/docs-framework/SKILL.md +138 -0
  119. package/plugins/devflow-core-skills/skills/docs-framework/references/patterns.md +346 -0
  120. package/plugins/devflow-core-skills/skills/docs-framework/references/violations.md +221 -0
  121. package/plugins/devflow-core-skills/skills/frontend-design/SKILL.md +254 -0
  122. package/plugins/devflow-core-skills/skills/frontend-design/references/detection.md +184 -0
  123. package/plugins/devflow-core-skills/skills/frontend-design/references/patterns.md +511 -0
  124. package/plugins/devflow-core-skills/skills/frontend-design/references/violations.md +453 -0
  125. package/plugins/devflow-core-skills/skills/git-safety/SKILL.md +122 -0
  126. package/plugins/devflow-core-skills/skills/git-safety/references/detection.md +290 -0
  127. package/plugins/devflow-core-skills/skills/git-safety/references/patterns.md +289 -0
  128. package/plugins/devflow-core-skills/skills/git-safety/references/violations.md +18 -0
  129. package/plugins/devflow-core-skills/skills/git-workflow/SKILL.md +158 -0
  130. package/plugins/devflow-core-skills/skills/git-workflow/references/commit-patterns.md +115 -0
  131. package/plugins/devflow-core-skills/skills/git-workflow/references/commit-violations.md +77 -0
  132. package/plugins/devflow-core-skills/skills/git-workflow/references/pr-patterns.md +127 -0
  133. package/plugins/devflow-core-skills/skills/git-workflow/references/pr-violations.md +96 -0
  134. package/plugins/devflow-core-skills/skills/github-patterns/SKILL.md +153 -0
  135. package/plugins/devflow-core-skills/skills/github-patterns/references/patterns.md +572 -0
  136. package/plugins/devflow-core-skills/skills/github-patterns/references/violations.md +298 -0
  137. package/plugins/devflow-core-skills/skills/input-validation/SKILL.md +148 -0
  138. package/plugins/devflow-core-skills/skills/input-validation/references/detection.md +283 -0
  139. package/plugins/devflow-core-skills/skills/input-validation/references/patterns.md +361 -0
  140. package/plugins/devflow-core-skills/skills/input-validation/references/violations.md +224 -0
  141. package/plugins/devflow-core-skills/skills/react/SKILL.md +276 -0
  142. package/plugins/devflow-core-skills/skills/react/references/patterns.md +1331 -0
  143. package/plugins/devflow-core-skills/skills/react/references/violations.md +565 -0
  144. package/plugins/devflow-core-skills/skills/test-driven-development/SKILL.md +139 -0
  145. package/plugins/devflow-core-skills/skills/test-driven-development/references/rationalization-prevention.md +111 -0
  146. package/plugins/devflow-core-skills/skills/test-patterns/SKILL.md +183 -0
  147. package/plugins/devflow-core-skills/skills/test-patterns/references/detection.md +149 -0
  148. package/plugins/devflow-core-skills/skills/test-patterns/references/patterns.md +220 -0
  149. package/plugins/devflow-core-skills/skills/test-patterns/references/report-template.md +108 -0
  150. package/plugins/devflow-core-skills/skills/test-patterns/references/violations.md +221 -0
  151. package/plugins/devflow-core-skills/skills/typescript/SKILL.md +176 -0
  152. package/plugins/devflow-core-skills/skills/typescript/references/patterns.md +1105 -0
  153. package/plugins/devflow-core-skills/skills/typescript/references/violations.md +433 -0
  154. package/plugins/devflow-debug/.claude-plugin/plugin.json +18 -0
  155. package/plugins/devflow-debug/README.md +65 -0
  156. package/plugins/devflow-debug/agents/git.md +272 -0
  157. package/plugins/devflow-debug/commands/debug-teams.md +231 -0
  158. package/plugins/devflow-debug/commands/debug.md +160 -0
  159. package/plugins/devflow-debug/skills/agent-teams/SKILL.md +124 -0
  160. package/plugins/devflow-debug/skills/agent-teams/references/cleanup.md +104 -0
  161. package/plugins/devflow-debug/skills/agent-teams/references/communication.md +122 -0
  162. package/plugins/devflow-debug/skills/agent-teams/references/team-patterns.md +217 -0
  163. package/plugins/devflow-debug/skills/git-safety/SKILL.md +122 -0
  164. package/plugins/devflow-debug/skills/git-safety/references/detection.md +290 -0
  165. package/plugins/devflow-debug/skills/git-safety/references/patterns.md +289 -0
  166. package/plugins/devflow-debug/skills/git-safety/references/violations.md +18 -0
  167. package/plugins/devflow-implement/.claude-plugin/plugin.json +21 -0
  168. package/plugins/devflow-implement/README.md +71 -0
  169. package/plugins/devflow-implement/agents/coder.md +122 -0
  170. package/plugins/devflow-implement/agents/git.md +272 -0
  171. package/plugins/devflow-implement/agents/scrutinizer.md +80 -0
  172. package/plugins/devflow-implement/agents/shepherd.md +94 -0
  173. package/plugins/devflow-implement/agents/simplifier.md +62 -0
  174. package/plugins/devflow-implement/agents/skimmer.md +88 -0
  175. package/plugins/devflow-implement/agents/synthesizer.md +204 -0
  176. package/plugins/devflow-implement/agents/validator.md +86 -0
  177. package/plugins/devflow-implement/commands/implement-teams.md +608 -0
  178. package/plugins/devflow-implement/commands/implement.md +426 -0
  179. package/plugins/devflow-implement/skills/accessibility/SKILL.md +229 -0
  180. package/plugins/devflow-implement/skills/accessibility/references/detection.md +171 -0
  181. package/plugins/devflow-implement/skills/accessibility/references/patterns.md +670 -0
  182. package/plugins/devflow-implement/skills/accessibility/references/violations.md +419 -0
  183. package/plugins/devflow-implement/skills/agent-teams/SKILL.md +124 -0
  184. package/plugins/devflow-implement/skills/agent-teams/references/cleanup.md +104 -0
  185. package/plugins/devflow-implement/skills/agent-teams/references/communication.md +122 -0
  186. package/plugins/devflow-implement/skills/agent-teams/references/team-patterns.md +217 -0
  187. package/plugins/devflow-implement/skills/frontend-design/SKILL.md +254 -0
  188. package/plugins/devflow-implement/skills/frontend-design/references/detection.md +184 -0
  189. package/plugins/devflow-implement/skills/frontend-design/references/patterns.md +511 -0
  190. package/plugins/devflow-implement/skills/frontend-design/references/violations.md +453 -0
  191. package/plugins/devflow-implement/skills/implementation-patterns/SKILL.md +162 -0
  192. package/plugins/devflow-implement/skills/implementation-patterns/references/patterns.md +1063 -0
  193. package/plugins/devflow-implement/skills/implementation-patterns/references/violations.md +483 -0
  194. package/plugins/devflow-implement/skills/self-review/SKILL.md +149 -0
  195. package/plugins/devflow-implement/skills/self-review/references/patterns.md +405 -0
  196. package/plugins/devflow-implement/skills/self-review/references/report-template.md +253 -0
  197. package/plugins/devflow-implement/skills/self-review/references/violations.md +308 -0
  198. package/plugins/devflow-resolve/.claude-plugin/plugin.json +19 -0
  199. package/plugins/devflow-resolve/README.md +65 -0
  200. package/plugins/devflow-resolve/agents/git.md +272 -0
  201. package/plugins/devflow-resolve/agents/resolver.md +131 -0
  202. package/plugins/devflow-resolve/agents/simplifier.md +62 -0
  203. package/plugins/devflow-resolve/commands/resolve-teams.md +298 -0
  204. package/plugins/devflow-resolve/commands/resolve.md +237 -0
  205. package/plugins/devflow-resolve/skills/agent-teams/SKILL.md +124 -0
  206. package/plugins/devflow-resolve/skills/agent-teams/references/cleanup.md +104 -0
  207. package/plugins/devflow-resolve/skills/agent-teams/references/communication.md +122 -0
  208. package/plugins/devflow-resolve/skills/agent-teams/references/team-patterns.md +217 -0
  209. package/plugins/devflow-resolve/skills/implementation-patterns/SKILL.md +162 -0
  210. package/plugins/devflow-resolve/skills/implementation-patterns/references/patterns.md +1063 -0
  211. package/plugins/devflow-resolve/skills/implementation-patterns/references/violations.md +483 -0
  212. package/plugins/devflow-resolve/skills/security-patterns/SKILL.md +156 -0
  213. package/plugins/devflow-resolve/skills/security-patterns/references/detection.md +287 -0
  214. package/plugins/devflow-resolve/skills/security-patterns/references/patterns.md +507 -0
  215. package/plugins/devflow-resolve/skills/security-patterns/references/violations.md +237 -0
  216. package/plugins/devflow-self-review/.claude-plugin/plugin.json +7 -0
  217. package/plugins/devflow-self-review/README.md +38 -0
  218. package/plugins/devflow-self-review/agents/scrutinizer.md +80 -0
  219. package/plugins/devflow-self-review/agents/simplifier.md +62 -0
  220. package/plugins/devflow-self-review/agents/validator.md +86 -0
  221. package/plugins/devflow-self-review/commands/self-review.md +126 -0
  222. package/plugins/devflow-self-review/skills/core-patterns/SKILL.md +162 -0
  223. package/plugins/devflow-self-review/skills/core-patterns/references/checklist.md +276 -0
  224. package/plugins/devflow-self-review/skills/core-patterns/references/code-smell-violations.md +144 -0
  225. package/plugins/devflow-self-review/skills/core-patterns/references/detection.md +303 -0
  226. package/plugins/devflow-self-review/skills/core-patterns/references/patterns.md +576 -0
  227. package/plugins/devflow-self-review/skills/core-patterns/references/violations.md +369 -0
  228. package/plugins/devflow-self-review/skills/self-review/SKILL.md +149 -0
  229. package/plugins/devflow-self-review/skills/self-review/references/patterns.md +405 -0
  230. package/plugins/devflow-self-review/skills/self-review/references/report-template.md +253 -0
  231. package/plugins/devflow-self-review/skills/self-review/references/violations.md +308 -0
  232. package/plugins/devflow-specify/.claude-plugin/plugin.json +15 -0
  233. package/plugins/devflow-specify/README.md +46 -0
  234. package/plugins/devflow-specify/agents/skimmer.md +88 -0
  235. package/plugins/devflow-specify/agents/synthesizer.md +204 -0
  236. package/plugins/devflow-specify/commands/specify-teams.md +314 -0
  237. package/plugins/devflow-specify/commands/specify.md +179 -0
  238. package/plugins/devflow-specify/skills/agent-teams/SKILL.md +124 -0
  239. package/plugins/devflow-specify/skills/agent-teams/references/cleanup.md +104 -0
  240. package/plugins/devflow-specify/skills/agent-teams/references/communication.md +122 -0
  241. package/plugins/devflow-specify/skills/agent-teams/references/team-patterns.md +217 -0
  242. package/scripts/hooks/ambient-prompt.sh +48 -0
  243. package/scripts/hooks/background-memory-update.sh +208 -0
  244. package/scripts/hooks/ensure-memory-gitignore.sh +17 -0
  245. package/scripts/hooks/pre-compact-memory.sh +87 -0
  246. package/scripts/hooks/session-start-memory.sh +126 -0
  247. package/scripts/hooks/stop-update-memory.sh +85 -0
  248. package/shared/agents/coder.md +122 -0
  249. package/shared/agents/git.md +272 -0
  250. package/shared/agents/resolver.md +131 -0
  251. package/shared/agents/reviewer.md +119 -0
  252. package/shared/agents/scrutinizer.md +80 -0
  253. package/shared/agents/shepherd.md +94 -0
  254. package/shared/agents/simplifier.md +62 -0
  255. package/shared/agents/skimmer.md +88 -0
  256. package/shared/agents/synthesizer.md +204 -0
  257. package/shared/agents/validator.md +86 -0
  258. package/shared/skills/accessibility/SKILL.md +229 -0
  259. package/shared/skills/accessibility/references/detection.md +171 -0
  260. package/shared/skills/accessibility/references/patterns.md +670 -0
  261. package/shared/skills/accessibility/references/violations.md +419 -0
  262. package/shared/skills/agent-teams/SKILL.md +124 -0
  263. package/shared/skills/agent-teams/references/cleanup.md +104 -0
  264. package/shared/skills/agent-teams/references/communication.md +122 -0
  265. package/shared/skills/agent-teams/references/team-patterns.md +217 -0
  266. package/shared/skills/ambient-router/SKILL.md +89 -0
  267. package/shared/skills/ambient-router/references/skill-catalog.md +64 -0
  268. package/shared/skills/architecture-patterns/SKILL.md +153 -0
  269. package/shared/skills/architecture-patterns/references/detection.md +337 -0
  270. package/shared/skills/architecture-patterns/references/patterns.md +873 -0
  271. package/shared/skills/architecture-patterns/references/violations.md +575 -0
  272. package/shared/skills/complexity-patterns/SKILL.md +143 -0
  273. package/shared/skills/complexity-patterns/references/detection.md +264 -0
  274. package/shared/skills/complexity-patterns/references/patterns.md +487 -0
  275. package/shared/skills/complexity-patterns/references/violations.md +361 -0
  276. package/shared/skills/consistency-patterns/SKILL.md +140 -0
  277. package/shared/skills/consistency-patterns/references/detection.md +207 -0
  278. package/shared/skills/consistency-patterns/references/patterns.md +202 -0
  279. package/shared/skills/consistency-patterns/references/violations.md +213 -0
  280. package/shared/skills/core-patterns/SKILL.md +162 -0
  281. package/shared/skills/core-patterns/references/checklist.md +276 -0
  282. package/shared/skills/core-patterns/references/code-smell-violations.md +144 -0
  283. package/shared/skills/core-patterns/references/detection.md +303 -0
  284. package/shared/skills/core-patterns/references/patterns.md +576 -0
  285. package/shared/skills/core-patterns/references/violations.md +369 -0
  286. package/shared/skills/database-patterns/SKILL.md +134 -0
  287. package/shared/skills/database-patterns/references/detection.md +208 -0
  288. package/shared/skills/database-patterns/references/patterns.md +394 -0
  289. package/shared/skills/database-patterns/references/violations.md +332 -0
  290. package/shared/skills/dependencies-patterns/SKILL.md +141 -0
  291. package/shared/skills/dependencies-patterns/references/detection.md +181 -0
  292. package/shared/skills/dependencies-patterns/references/patterns.md +225 -0
  293. package/shared/skills/dependencies-patterns/references/violations.md +247 -0
  294. package/shared/skills/docs-framework/SKILL.md +138 -0
  295. package/shared/skills/docs-framework/references/patterns.md +346 -0
  296. package/shared/skills/docs-framework/references/violations.md +221 -0
  297. package/shared/skills/documentation-patterns/SKILL.md +125 -0
  298. package/shared/skills/documentation-patterns/references/detection.md +190 -0
  299. package/shared/skills/documentation-patterns/references/patterns.md +189 -0
  300. package/shared/skills/documentation-patterns/references/violations.md +163 -0
  301. package/shared/skills/frontend-design/SKILL.md +254 -0
  302. package/shared/skills/frontend-design/references/detection.md +184 -0
  303. package/shared/skills/frontend-design/references/patterns.md +511 -0
  304. package/shared/skills/frontend-design/references/violations.md +453 -0
  305. package/shared/skills/git-safety/SKILL.md +122 -0
  306. package/shared/skills/git-safety/references/detection.md +290 -0
  307. package/shared/skills/git-safety/references/patterns.md +289 -0
  308. package/shared/skills/git-safety/references/violations.md +18 -0
  309. package/shared/skills/git-workflow/SKILL.md +158 -0
  310. package/shared/skills/git-workflow/references/commit-patterns.md +115 -0
  311. package/shared/skills/git-workflow/references/commit-violations.md +77 -0
  312. package/shared/skills/git-workflow/references/pr-patterns.md +127 -0
  313. package/shared/skills/git-workflow/references/pr-violations.md +96 -0
  314. package/shared/skills/github-patterns/SKILL.md +153 -0
  315. package/shared/skills/github-patterns/references/patterns.md +572 -0
  316. package/shared/skills/github-patterns/references/violations.md +298 -0
  317. package/shared/skills/implementation-patterns/SKILL.md +162 -0
  318. package/shared/skills/implementation-patterns/references/patterns.md +1063 -0
  319. package/shared/skills/implementation-patterns/references/violations.md +483 -0
  320. package/shared/skills/input-validation/SKILL.md +148 -0
  321. package/shared/skills/input-validation/references/detection.md +283 -0
  322. package/shared/skills/input-validation/references/patterns.md +361 -0
  323. package/shared/skills/input-validation/references/violations.md +224 -0
  324. package/shared/skills/performance-patterns/SKILL.md +154 -0
  325. package/shared/skills/performance-patterns/references/detection.md +351 -0
  326. package/shared/skills/performance-patterns/references/patterns.md +503 -0
  327. package/shared/skills/performance-patterns/references/violations.md +354 -0
  328. package/shared/skills/react/SKILL.md +276 -0
  329. package/shared/skills/react/references/patterns.md +1331 -0
  330. package/shared/skills/react/references/violations.md +565 -0
  331. package/shared/skills/regression-patterns/SKILL.md +146 -0
  332. package/shared/skills/regression-patterns/references/detection.md +237 -0
  333. package/shared/skills/regression-patterns/references/patterns.md +226 -0
  334. package/shared/skills/regression-patterns/references/violations.md +225 -0
  335. package/shared/skills/review-methodology/SKILL.md +119 -0
  336. package/shared/skills/review-methodology/references/patterns.md +186 -0
  337. package/shared/skills/review-methodology/references/report-template.md +142 -0
  338. package/shared/skills/review-methodology/references/violations.md +125 -0
  339. package/shared/skills/security-patterns/SKILL.md +156 -0
  340. package/shared/skills/security-patterns/references/detection.md +287 -0
  341. package/shared/skills/security-patterns/references/patterns.md +507 -0
  342. package/shared/skills/security-patterns/references/violations.md +237 -0
  343. package/shared/skills/self-review/SKILL.md +149 -0
  344. package/shared/skills/self-review/references/patterns.md +405 -0
  345. package/shared/skills/self-review/references/report-template.md +253 -0
  346. package/shared/skills/self-review/references/violations.md +308 -0
  347. package/shared/skills/test-driven-development/SKILL.md +139 -0
  348. package/shared/skills/test-driven-development/references/rationalization-prevention.md +111 -0
  349. package/shared/skills/test-patterns/SKILL.md +183 -0
  350. package/shared/skills/test-patterns/references/detection.md +149 -0
  351. package/shared/skills/test-patterns/references/patterns.md +220 -0
  352. package/shared/skills/test-patterns/references/report-template.md +108 -0
  353. package/shared/skills/test-patterns/references/violations.md +221 -0
  354. package/shared/skills/typescript/SKILL.md +176 -0
  355. package/shared/skills/typescript/references/patterns.md +1105 -0
  356. package/shared/skills/typescript/references/violations.md +433 -0
  357. package/src/templates/claudeignore.template +188 -0
  358. package/src/templates/managed-settings.json +160 -0
  359. package/src/templates/settings.json +59 -0
  360. package/dist/cli.d.ts.map +0 -1
  361. package/dist/cli.js.map +0 -1
  362. package/dist/commands/init.d.ts.map +0 -1
  363. package/dist/commands/init.js.map +0 -1
  364. package/dist/commands/uninstall.d.ts.map +0 -1
  365. package/dist/commands/uninstall.js.map +0 -1
  366. package/dist/utils/git.d.ts.map +0 -1
  367. package/dist/utils/git.js.map +0 -1
  368. package/dist/utils/paths.d.ts.map +0 -1
  369. package/dist/utils/paths.js.map +0 -1
  370. package/src/claude/CLAUDE.md +0 -400
  371. package/src/claude/agents/devflow/audit-architecture.md +0 -132
  372. package/src/claude/agents/devflow/audit-complexity.md +0 -132
  373. package/src/claude/agents/devflow/audit-database.md +0 -132
  374. package/src/claude/agents/devflow/audit-dependencies.md +0 -132
  375. package/src/claude/agents/devflow/audit-documentation.md +0 -132
  376. package/src/claude/agents/devflow/audit-performance.md +0 -256
  377. package/src/claude/agents/devflow/audit-security.md +0 -259
  378. package/src/claude/agents/devflow/audit-tests.md +0 -132
  379. package/src/claude/agents/devflow/audit-typescript.md +0 -132
  380. package/src/claude/agents/devflow/brainstorm.md +0 -279
  381. package/src/claude/agents/devflow/catch-up.md +0 -345
  382. package/src/claude/agents/devflow/code-review.md +0 -307
  383. package/src/claude/agents/devflow/commit.md +0 -380
  384. package/src/claude/agents/devflow/debug.md +0 -476
  385. package/src/claude/agents/devflow/design.md +0 -491
  386. package/src/claude/agents/devflow/get-issue.md +0 -286
  387. package/src/claude/agents/devflow/pr-comments.md +0 -285
  388. package/src/claude/agents/devflow/project-state.md +0 -419
  389. package/src/claude/agents/devflow/pull-request.md +0 -493
  390. package/src/claude/agents/devflow/release.md +0 -1137
  391. package/src/claude/agents/devflow/tech-debt.md +0 -338
  392. package/src/claude/commands/devflow/brainstorm.md +0 -68
  393. package/src/claude/commands/devflow/breakdown.md +0 -125
  394. package/src/claude/commands/devflow/catch-up.md +0 -29
  395. package/src/claude/commands/devflow/code-review.md +0 -237
  396. package/src/claude/commands/devflow/commit.md +0 -17
  397. package/src/claude/commands/devflow/debug.md +0 -56
  398. package/src/claude/commands/devflow/design.md +0 -82
  399. package/src/claude/commands/devflow/devlog.md +0 -408
  400. package/src/claude/commands/devflow/get-issue.md +0 -16
  401. package/src/claude/commands/devflow/implement.md +0 -100
  402. package/src/claude/commands/devflow/plan.md +0 -223
  403. package/src/claude/commands/devflow/pull-request.md +0 -20
  404. package/src/claude/commands/devflow/release.md +0 -251
  405. package/src/claude/commands/devflow/resolve-comments.md +0 -583
  406. package/src/claude/scripts/statusline.sh +0 -47
  407. package/src/claude/settings.json +0 -6
  408. package/src/claude/skills/devflow/code-smell/SKILL.md +0 -428
  409. package/src/claude/skills/devflow/debug/SKILL.md +0 -119
  410. package/src/claude/skills/devflow/error-handling/SKILL.md +0 -597
  411. package/src/claude/skills/devflow/input-validation/SKILL.md +0 -514
  412. package/src/claude/skills/devflow/pattern-check/SKILL.md +0 -238
  413. package/src/claude/skills/devflow/research/SKILL.md +0 -138
  414. package/src/claude/skills/devflow/test-design/SKILL.md +0 -384
@@ -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 readline from 'readline';
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
- * Prompt user for confirmation (async)
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
- async function promptUser(question) {
20
- const rl = readline.createInterface({
21
- input: process.stdin,
22
- output: process.stdout
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
- * DevFlow commands with user-friendly descriptions.
33
- * Used for displaying available commands in init output.
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
- const DEVFLOW_SKILLS = [
56
- { name: 'pattern-check', description: 'Architectural pattern validation' },
57
- { name: 'test-design', description: 'Test quality enforcement' },
58
- { name: 'code-smell', description: 'Anti-pattern detection' },
59
- { name: 'research', description: 'Pre-implementation planning (auto)' },
60
- { name: 'debug', description: 'Systematic debugging (auto)' },
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
- console.log('Available commands:');
111
- for (const cmd of DEVFLOW_COMMANDS) {
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
- console.log('\nInstalled skills (auto-activate):');
115
- for (const skill of DEVFLOW_SKILLS) {
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
- console.log('\nNote: debug exists as both command (manual) and skill (auto)');
119
- console.log('Docs: https://github.com/dean0x/devflow');
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('--skip-docs', 'Skip creating .docs/ structure')
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
- if (verbose) {
139
- console.log(`🚀 DevFlow v${version}\n`);
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'; // Default to user for backwards compatibility
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
- console.error('Invalid scope. Use "user" or "local"\n');
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
- // Check if running in interactive terminal (TTY)
154
- if (!process.stdin.isTTY) {
155
- // Non-interactive environment (CI/CD, scripts) - use default
156
- if (verbose) {
157
- console.log('📦 Non-interactive environment detected, using default scope: user');
158
- console.log(' To specify scope in CI/CD, use: devflow init --scope <user|local>\n');
159
- }
160
- scope = 'user';
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
- else {
163
- // Interactive prompt for scope
164
- if (verbose) {
165
- console.log('📦 Installation Scope:\n');
166
- console.log(' user - Install for all projects (user-wide)');
167
- console.log(' └─ ~/.claude/ and ~/.devflow/');
168
- console.log(' local - Install for current project only');
169
- console.log(' └─ <git-root>/.claude/ and <git-root>/.devflow/\n');
170
- }
171
- const rl = readline.createInterface({
172
- input: process.stdin,
173
- output: process.stdout
174
- });
175
- const prompt = verbose
176
- ? 'Choose scope (user/local) [user]: '
177
- : 'Install scope - user (all projects) or local (this project only) [user]: ';
178
- const answer = await new Promise((resolve) => {
179
- rl.question(prompt, (input) => {
180
- rl.close();
181
- resolve(input.trim().toLowerCase() || 'user');
182
- });
183
- });
184
- if (answer === 'local' || answer === 'l') {
185
- scope = 'local';
186
- }
187
- else if (answer === 'user' || answer === 'u' || answer === '') {
188
- scope = 'user';
189
- }
190
- else {
191
- console.error('❌ Invalid scope. Use "user" or "local"\n');
192
- process.exit(1);
193
- }
194
- if (verbose) {
195
- console.log();
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
- // Get installation paths with proper validation
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
- // Cache git root for later use (already computed in getInstallationPaths for local scope)
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
- console.error('Path configuration error:', error instanceof Error ? error.message : error);
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
- // Check for Claude Code (only for user scope)
220
- if (scope === 'user') {
235
+ // Validate target directory
236
+ s.message('Validating target directory');
237
+ if (scope === 'local') {
221
238
  try {
222
- await fs.access(claudeDir);
239
+ await fs.mkdir(claudeDir, { recursive: true });
223
240
  }
224
- catch {
225
- console.error(`❌ Claude Code not detected at ${claudeDir}`);
226
- console.error(' Install from: https://claude.com/claude-code');
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.mkdir(claudeDir, { recursive: true });
238
- if (verbose) {
239
- console.log('✓ Local .claude directory ready');
240
- }
249
+ await fs.access(claudeDir);
241
250
  }
242
- catch (error) {
243
- console.error(`❌ Failed to create ${claudeDir}:`, error);
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
- // Get the root directory of the devflow package
258
+ // Resolve plugins and deduplication maps
259
+ s.message('Installing components');
248
260
  const rootDir = path.resolve(__dirname, '../..');
249
- const claudeSourceDir = path.join(rootDir, 'src', 'claude');
250
- try {
251
- // DevFlow namespace directories (single source of truth)
252
- const devflowDirectories = [
253
- {
254
- target: path.join(claudeDir, 'commands', 'devflow'),
255
- source: path.join(claudeSourceDir, 'commands', 'devflow'),
256
- name: 'commands'
257
- },
258
- {
259
- target: path.join(claudeDir, 'agents', 'devflow'),
260
- source: path.join(claudeSourceDir, 'agents', 'devflow'),
261
- name: 'agents'
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
- // Atomic exclusive create - fails if file already exists
339
- await fs.writeFile(settingsPath, settingsContent, { encoding: 'utf-8', flag: 'wx' });
340
- if (verbose) {
341
- console.log('✓ Settings configured');
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
- if (isNodeSystemError(error) && error.code === 'EEXIST') {
346
- // Existing settings.json found - install as settings.devflow.json
347
- settingsExists = true;
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
- // Install CLAUDE.md - never override existing files (atomic operation)
358
- const claudeMdPath = path.join(claudeDir, 'CLAUDE.md');
359
- const devflowClaudeMdPath = path.join(claudeDir, 'CLAUDE.devflow.md');
360
- const sourceClaudeMdPath = path.join(claudeSourceDir, 'CLAUDE.md');
361
- let claudeMdExists = false;
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
- // Atomic exclusive create - fails if file already exists
364
- const content = await fs.readFile(sourceClaudeMdPath, 'utf-8');
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 (error) {
371
- if (isNodeSystemError(error) && error.code === 'EEXIST') {
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
- // Create .claudeignore in git repository root
384
- let claudeignoreCreated = false;
385
- try {
386
- // Use cached git root (already computed and validated earlier)
387
- if (!gitRoot) {
388
- throw new Error('Not in a git repository');
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
- catch (error) {
586
- // Not a git repository or other error - skip .claudeignore creation
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
- if (claudeignoreCreated && verbose) {
589
- console.log('✓ .claudeignore created');
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
- // For local scope, update .gitignore to exclude .claude/ and .devflow/
592
- if (scope === 'local' && gitRoot) {
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 gitignorePath = path.join(gitRoot, '.gitignore');
595
- const entriesToAdd = ['.claude/', '.devflow/'];
596
- let gitignoreContent = '';
597
- try {
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
- console.log(' .gitignore updated (excluded .claude/ and .devflow/)');
372
+ p.log.success('Ambient mode hook installed');
617
373
  }
618
374
  }
619
375
  }
620
- catch (error) {
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
- console.warn('⚠️ Could not update .gitignore:', error instanceof Error ? error.message : error);
388
+ p.log.info(`Working memory ${memoryEnabled ? 'enabled' : 'disabled'}`);
623
389
  }
624
390
  }
625
391
  }
626
- // Offer to install project documentation structure
627
- let docsCreated = false;
628
- if (!options.skipDocs) {
629
- const docsDir = path.join(process.cwd(), '.docs');
630
- try {
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
- if (docsCreated && verbose) {
642
- console.log(' .docs/ structure ready');
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
- // Render output based on verbose flag
645
- if (verbose) {
646
- renderVerboseOutput(version, scope, claudeDir, devflowDir, settingsExists, claudeMdExists);
406
+ if (selectedExtras.includes('gitignore') && gitRoot) {
407
+ await updateGitignore(gitRoot, verbose);
647
408
  }
648
- else {
649
- renderCleanOutput(version);
409
+ if (selectedExtras.includes('docs')) {
410
+ await createDocsStructure(verbose);
650
411
  }
412
+ sExtras.stop('Extras configured');
651
413
  }
652
- catch (error) {
653
- console.error('❌ Installation failed:', error);
654
- process.exit(1);
414
+ // Summary output
415
+ if (usedNativeCli) {
416
+ p.log.success('Installed via Claude plugin system');
655
417
  }
656
- });
657
- async function copyDirectory(src, dest) {
658
- await fs.mkdir(dest, { recursive: true });
659
- const entries = await fs.readdir(src, { withFileTypes: true });
660
- for (const entry of entries) {
661
- const srcPath = path.join(src, entry.name);
662
- const destPath = path.join(dest, entry.name);
663
- if (entry.isDirectory()) {
664
- await copyDirectory(srcPath, destPath);
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
- await fs.copyFile(srcPath, destPath);
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