@bonesofspring/ai-rules 0.2.2 → 0.2.3

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 (287) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +26 -4
  3. package/bin/cli.js +259 -72
  4. package/package.json +3 -2
  5. package/presets/claude/ios-swift/CLAUDE.md +28 -20
  6. package/presets/claude/ios-swift/README.md +16 -15
  7. package/presets/claude/ios-swift/agents/README.md +55 -0
  8. package/presets/claude/ios-swift/agents/accessibility-reviewer.md +67 -0
  9. package/presets/claude/ios-swift/agents/api-contract-reviewer.md +72 -0
  10. package/presets/claude/ios-swift/agents/build-verifier.md +64 -0
  11. package/presets/claude/ios-swift/agents/ci-investigator.md +73 -0
  12. package/presets/claude/ios-swift/agents/code-reviewer.md +75 -0
  13. package/presets/claude/ios-swift/agents/debugger.md +72 -0
  14. package/presets/claude/ios-swift/agents/feature-developer.md +35 -0
  15. package/presets/claude/ios-swift/agents/migration-specialist.md +73 -0
  16. package/presets/claude/ios-swift/agents/performance-auditor.md +72 -0
  17. package/presets/claude/ios-swift/agents/qa-tester.md +65 -0
  18. package/presets/claude/ios-swift/agents/security-reviewer.md +69 -0
  19. package/presets/claude/ios-swift/agents/solution-architect.md +17 -0
  20. package/presets/claude/ios-swift/agents/task-analyst.md +25 -0
  21. package/presets/claude/ios-swift/agents/task-router.md +62 -0
  22. package/presets/claude/ios-swift/agents/tech-writer.md +63 -0
  23. package/presets/claude/ios-swift/agents/unit-test-generator.md +54 -0
  24. package/presets/claude/ios-swift/agents/unit-test-healer.md +53 -0
  25. package/presets/claude/ios-swift/agents/unit-test-planner.md +64 -0
  26. package/presets/claude/ios-swift/agents/xcuitest-test-generator.md +47 -0
  27. package/presets/claude/ios-swift/agents/xcuitest-test-healer.md +47 -0
  28. package/presets/claude/ios-swift/agents/xcuitest-test-planner.md +67 -0
  29. package/presets/claude/ios-swift/commands/README.md +12 -2
  30. package/presets/claude/ios-swift/commands/feature-continue.md +51 -0
  31. package/presets/claude/ios-swift/commands/feature-start.md +30 -0
  32. package/presets/claude/ios-swift/commands/task-continue.md +49 -0
  33. package/presets/claude/ios-swift/commands/task.md +50 -0
  34. package/presets/claude/ios-swift/commands/technical-retro.md +58 -0
  35. package/presets/claude/ios-swift/hooks/README.md +10 -0
  36. package/presets/claude/ios-swift/hooks/chain-team-phases.sh +382 -0
  37. package/presets/claude/ios-swift/hooks/guard-shell-command.sh +79 -0
  38. package/presets/claude/ios-swift/rules/README.md +25 -14
  39. package/presets/claude/ios-swift/rules/api-and-data/README.md +2 -1
  40. package/presets/claude/ios-swift/rules/api-and-data/networking.md +2 -2
  41. package/presets/claude/ios-swift/rules/api-and-data/persistence.md +30 -0
  42. package/presets/claude/ios-swift/rules/architecture/README.md +3 -1
  43. package/presets/claude/ios-swift/rules/architecture/feature-delivery.md +10 -2
  44. package/presets/claude/ios-swift/rules/architecture/module-public-api.md +25 -0
  45. package/presets/claude/ios-swift/rules/architecture/reference-features.md +50 -0
  46. package/presets/claude/ios-swift/rules/stack/ios-app-core.md +2 -1
  47. package/presets/claude/ios-swift/rules/testing/ui.md +2 -0
  48. package/presets/claude/ios-swift/rules/tooling-and-review/README.md +6 -1
  49. package/presets/claude/ios-swift/rules/tooling-and-review/agent-team-intake.md +18 -0
  50. package/presets/claude/ios-swift/rules/tooling-and-review/agent-team-orchestrator.md +47 -0
  51. package/presets/claude/ios-swift/rules/tooling-and-review/code-review.md +5 -0
  52. package/presets/claude/ios-swift/rules/tooling-and-review/post-change-build.md +5 -0
  53. package/presets/claude/ios-swift/rules/tooling-and-review/security-ios.md +36 -0
  54. package/presets/claude/ios-swift/rules/tooling-and-review/technical-retro.md +14 -0
  55. package/presets/claude/ios-swift/rules/tooling-and-review/xcode-tooling.md +24 -0
  56. package/presets/claude/ios-swift/rules/ui-and-accessibility/README.md +2 -1
  57. package/presets/claude/ios-swift/rules/ui-and-accessibility/navigation.md +28 -0
  58. package/presets/claude/ios-swift/skills/README.md +13 -0
  59. package/presets/claude/ios-swift/skills/ci-investigation/SKILL.md +39 -0
  60. package/presets/claude/ios-swift/skills/code-review/SKILL.md +27 -0
  61. package/presets/claude/ios-swift/skills/debug-investigation/SKILL.md +30 -0
  62. package/presets/claude/ios-swift/skills/feature-delivery/SKILL.md +27 -0
  63. package/presets/claude/ios-swift/skills/technical-retro/SKILL.md +10 -0
  64. package/presets/claude/ios-swift/skills/unit-testing/SKILL.md +32 -0
  65. package/presets/claude/ios-swift/skills/xcuitest-e2e/SKILL.md +33 -0
  66. package/presets/claude/ios-swift/team/README.md +27 -0
  67. package/presets/claude/ios-swift/team/fixtures/bugfix-standard.json +33 -0
  68. package/presets/claude/ios-swift/team/fixtures/feature-full.json +48 -0
  69. package/presets/claude/ios-swift/team/fixtures/feature-light.json +36 -0
  70. package/presets/claude/next/CLAUDE.md +29 -5
  71. package/presets/claude/next/README.md +10 -0
  72. package/presets/claude/next/agents/README.md +155 -1
  73. package/presets/claude/next/agents/accessibility-reviewer.md +65 -0
  74. package/presets/claude/next/agents/api-contract-reviewer.md +69 -0
  75. package/presets/claude/next/agents/build-verifier.md +64 -0
  76. package/presets/claude/next/agents/ci-investigator.md +62 -0
  77. package/presets/claude/next/agents/code-reviewer.md +63 -0
  78. package/presets/claude/next/agents/debugger.md +63 -0
  79. package/presets/claude/next/agents/feature-developer.md +27 -0
  80. package/presets/claude/next/agents/migration-specialist.md +69 -0
  81. package/presets/claude/next/agents/performance-auditor.md +68 -0
  82. package/presets/claude/next/agents/qa-tester.md +56 -0
  83. package/presets/claude/next/agents/security-reviewer.md +64 -0
  84. package/presets/claude/next/agents/solution-architect.md +70 -0
  85. package/presets/claude/next/agents/task-analyst.md +111 -0
  86. package/presets/claude/next/agents/task-router.md +94 -0
  87. package/presets/claude/next/agents/tech-writer.md +61 -0
  88. package/presets/claude/next/agents/unit-test-generator.md +37 -0
  89. package/presets/claude/next/agents/unit-test-healer.md +38 -0
  90. package/presets/claude/next/agents/unit-test-planner.md +62 -0
  91. package/presets/claude/next/commands/README.md +10 -2
  92. package/presets/claude/next/commands/feature-continue.md +51 -0
  93. package/presets/claude/next/commands/feature-start.md +30 -0
  94. package/presets/claude/next/commands/task-continue.md +49 -0
  95. package/presets/claude/next/commands/task.md +50 -0
  96. package/presets/claude/next/commands/technical-retro.md +58 -0
  97. package/presets/claude/next/hooks/README.md +5 -2
  98. package/presets/claude/next/hooks/chain-team-phases.sh +380 -0
  99. package/presets/claude/next/hooks/guard-shell-command.sh +77 -0
  100. package/presets/claude/next/rules/README.md +42 -11
  101. package/presets/claude/next/rules/api-and-data/README.md +7 -1
  102. package/presets/claude/next/rules/api-and-data/api-services.md +57 -0
  103. package/presets/claude/next/rules/api-and-data/http-client.md +40 -0
  104. package/presets/claude/next/rules/api-and-data/store-rtk.md +65 -0
  105. package/presets/claude/next/rules/architecture/README.md +11 -2
  106. package/presets/claude/next/rules/architecture/architecture-boundaries-ui.md +15 -0
  107. package/presets/claude/next/rules/architecture/architecture-boundaries.md +75 -0
  108. package/presets/claude/next/rules/architecture/feature-delivery-workflow.md +79 -0
  109. package/presets/claude/next/rules/architecture/layer-barrel-exports.md +58 -0
  110. package/presets/claude/next/rules/architecture/public-imports.md +46 -0
  111. package/presets/claude/next/rules/architecture/reference-features.md +37 -0
  112. package/presets/claude/next/rules/stack/README.md +10 -1
  113. package/presets/claude/next/rules/stack/arrow-functions.md +45 -0
  114. package/presets/claude/next/rules/stack/navigation-router-ui.md +15 -0
  115. package/presets/claude/next/rules/stack/navigation-router.md +64 -0
  116. package/presets/claude/next/rules/stack/next-app-core.md +33 -0
  117. package/presets/claude/next/rules/stack/next-app-router.md +36 -0
  118. package/presets/claude/next/rules/stack/no-type-assertion.md +59 -0
  119. package/presets/claude/next/rules/stack/types-jsdoc.md +37 -0
  120. package/presets/claude/next/rules/testing/README.md +9 -1
  121. package/presets/claude/next/rules/testing/playwright-agents.md +74 -0
  122. package/presets/claude/next/rules/testing/tests-e2e-structure.md +52 -0
  123. package/presets/claude/next/rules/testing/tests-unit.md +66 -0
  124. package/presets/claude/next/rules/tooling-and-review/README.md +12 -1
  125. package/presets/claude/next/rules/tooling-and-review/agent-team-intake.md +15 -0
  126. package/presets/claude/next/rules/tooling-and-review/agent-team-orchestrator.md +141 -0
  127. package/presets/claude/next/rules/tooling-and-review/code-quality.md +42 -0
  128. package/presets/claude/next/rules/tooling-and-review/code-review-mr.md +30 -0
  129. package/presets/claude/next/rules/tooling-and-review/package-manager.md +11 -0
  130. package/presets/claude/next/rules/tooling-and-review/post-change-lint.md +44 -0
  131. package/presets/claude/next/rules/ui-and-accessibility/README.md +10 -1
  132. package/presets/claude/next/rules/ui-and-accessibility/css-property-order.md +14 -0
  133. package/presets/claude/next/rules/ui-and-accessibility/no-props-spread.md +57 -0
  134. package/presets/claude/next/rules/ui-and-accessibility/react-a11y-coding.md +37 -0
  135. package/presets/claude/next/rules/ui-and-accessibility/react-ui.md +91 -0
  136. package/presets/claude/next/skills/README.md +11 -1
  137. package/presets/claude/next/skills/ci-investigation/SKILL.md +36 -0
  138. package/presets/claude/next/skills/code-review/SKILL.md +26 -0
  139. package/presets/claude/next/skills/debug-investigation/SKILL.md +28 -0
  140. package/presets/claude/next/skills/feature-delivery/SKILL.md +15 -0
  141. package/presets/claude/next/skills/playwright-e2e/SKILL.md +31 -0
  142. package/presets/claude/next/skills/technical-retro/SKILL.md +40 -0
  143. package/presets/claude/next/skills/unit-testing/SKILL.md +32 -0
  144. package/presets/claude/next/team/README.md +105 -0
  145. package/presets/claude/next/team/fixtures/bugfix-standard.json +15 -0
  146. package/presets/claude/next/team/fixtures/feature-full.json +16 -0
  147. package/presets/claude/next/team/fixtures/feature-light.json +17 -0
  148. package/presets/claude/next/team/tasks/.gitkeep +1 -0
  149. package/presets/cursor/ios-swift/AGENTS.md +47 -0
  150. package/presets/cursor/ios-swift/BUGBOT.md +15 -0
  151. package/presets/cursor/ios-swift/README.md +26 -7
  152. package/presets/cursor/ios-swift/agents/README.md +55 -0
  153. package/presets/cursor/ios-swift/agents/accessibility-reviewer.md +67 -0
  154. package/presets/cursor/ios-swift/agents/api-contract-reviewer.md +72 -0
  155. package/presets/cursor/ios-swift/agents/build-verifier.md +64 -0
  156. package/presets/cursor/ios-swift/agents/ci-investigator.md +73 -0
  157. package/presets/cursor/ios-swift/agents/code-reviewer.md +75 -0
  158. package/presets/cursor/ios-swift/agents/debugger.md +72 -0
  159. package/presets/cursor/ios-swift/agents/feature-developer.md +35 -0
  160. package/presets/cursor/ios-swift/agents/migration-specialist.md +73 -0
  161. package/presets/cursor/ios-swift/agents/performance-auditor.md +72 -0
  162. package/presets/cursor/ios-swift/agents/qa-tester.md +65 -0
  163. package/presets/cursor/ios-swift/agents/security-reviewer.md +69 -0
  164. package/presets/cursor/ios-swift/agents/solution-architect.md +17 -0
  165. package/presets/cursor/ios-swift/agents/task-analyst.md +25 -0
  166. package/presets/cursor/ios-swift/agents/task-router.md +62 -0
  167. package/presets/cursor/ios-swift/agents/tech-writer.md +63 -0
  168. package/presets/cursor/ios-swift/agents/unit-test-generator.md +54 -0
  169. package/presets/cursor/ios-swift/agents/unit-test-healer.md +53 -0
  170. package/presets/cursor/ios-swift/agents/unit-test-planner.md +64 -0
  171. package/presets/cursor/ios-swift/agents/xcuitest-test-generator.md +47 -0
  172. package/presets/cursor/ios-swift/agents/xcuitest-test-healer.md +47 -0
  173. package/presets/cursor/ios-swift/agents/xcuitest-test-planner.md +67 -0
  174. package/presets/cursor/ios-swift/commands/README.md +49 -1
  175. package/presets/cursor/ios-swift/commands/feature-continue.md +19 -0
  176. package/presets/cursor/ios-swift/commands/feature-start.md +33 -0
  177. package/presets/cursor/ios-swift/commands/task-continue.md +49 -0
  178. package/presets/cursor/ios-swift/commands/task.md +50 -0
  179. package/presets/cursor/ios-swift/commands/technical-retro.md +81 -0
  180. package/presets/cursor/ios-swift/hooks/README.md +8 -0
  181. package/presets/cursor/ios-swift/hooks/chain-team-phases.sh +382 -0
  182. package/presets/cursor/ios-swift/hooks/guard-shell-command.sh +79 -0
  183. package/presets/cursor/ios-swift/hooks.json +17 -0
  184. package/presets/cursor/ios-swift/rules/README.md +45 -13
  185. package/presets/cursor/ios-swift/rules/agent-team-intake.mdc +16 -0
  186. package/presets/cursor/ios-swift/rules/agent-team-orchestrator.mdc +80 -0
  187. package/presets/cursor/ios-swift/rules/code-review-mr.mdc +1 -0
  188. package/presets/cursor/ios-swift/rules/feature-delivery-workflow.mdc +1 -1
  189. package/presets/cursor/ios-swift/rules/ios-app-core.mdc +2 -1
  190. package/presets/cursor/ios-swift/rules/module-public-api.mdc +26 -0
  191. package/presets/cursor/ios-swift/rules/navigation-coordinators.mdc +29 -0
  192. package/presets/cursor/ios-swift/rules/networking-services.mdc +2 -2
  193. package/presets/cursor/ios-swift/rules/persistence-data.mdc +31 -0
  194. package/presets/cursor/ios-swift/rules/reference-features.mdc +53 -0
  195. package/presets/cursor/ios-swift/rules/security-ios.mdc +35 -0
  196. package/presets/cursor/ios-swift/rules/technical-retro.mdc +12 -0
  197. package/presets/cursor/ios-swift/rules/tests-ui.mdc +1 -0
  198. package/presets/cursor/ios-swift/rules/xcode-tooling.mdc +20 -0
  199. package/presets/cursor/ios-swift/skills/README.md +13 -0
  200. package/presets/cursor/ios-swift/skills/ci-investigation/SKILL.md +39 -0
  201. package/presets/cursor/ios-swift/skills/code-review/SKILL.md +27 -0
  202. package/presets/cursor/ios-swift/skills/debug-investigation/SKILL.md +30 -0
  203. package/presets/cursor/ios-swift/skills/feature-delivery/SKILL.md +27 -0
  204. package/presets/cursor/ios-swift/skills/technical-retro/SKILL.md +10 -0
  205. package/presets/cursor/ios-swift/skills/unit-testing/SKILL.md +32 -0
  206. package/presets/cursor/ios-swift/skills/xcuitest-e2e/SKILL.md +33 -0
  207. package/presets/cursor/ios-swift/team/README.md +27 -0
  208. package/presets/cursor/ios-swift/team/fixtures/bugfix-standard.json +33 -0
  209. package/presets/cursor/ios-swift/team/fixtures/feature-full.json +48 -0
  210. package/presets/cursor/ios-swift/team/fixtures/feature-light.json +36 -0
  211. package/presets/cursor/next/AGENTS.md +36 -0
  212. package/presets/cursor/next/BUGBOT.md +14 -0
  213. package/presets/cursor/next/agents/README.md +165 -0
  214. package/presets/cursor/next/agents/accessibility-reviewer.md +67 -0
  215. package/presets/cursor/next/agents/api-contract-reviewer.md +71 -0
  216. package/presets/cursor/next/agents/build-verifier.md +66 -0
  217. package/presets/cursor/next/agents/ci-investigator.md +64 -0
  218. package/presets/cursor/next/agents/code-reviewer.md +64 -0
  219. package/presets/cursor/next/agents/debugger.md +64 -0
  220. package/presets/cursor/next/agents/feature-developer.md +28 -0
  221. package/presets/cursor/next/agents/migration-specialist.md +71 -0
  222. package/presets/cursor/next/agents/performance-auditor.md +70 -0
  223. package/presets/cursor/next/agents/playwright-test-generator.md +27 -0
  224. package/presets/cursor/next/agents/playwright-test-healer.md +27 -0
  225. package/presets/cursor/next/agents/playwright-test-planner.md +28 -0
  226. package/presets/cursor/next/agents/qa-tester.md +58 -0
  227. package/presets/cursor/next/agents/security-reviewer.md +66 -0
  228. package/presets/cursor/next/agents/solution-architect.md +71 -0
  229. package/presets/cursor/next/agents/task-analyst.md +112 -0
  230. package/presets/cursor/next/agents/task-router.md +95 -0
  231. package/presets/cursor/next/agents/tech-writer.md +62 -0
  232. package/presets/cursor/next/agents/unit-test-generator.md +39 -0
  233. package/presets/cursor/next/agents/unit-test-healer.md +40 -0
  234. package/presets/cursor/next/agents/unit-test-planner.md +64 -0
  235. package/presets/cursor/next/commands/README.md +49 -1
  236. package/presets/cursor/next/commands/feature-continue.md +19 -0
  237. package/presets/cursor/next/commands/feature-start.md +33 -0
  238. package/presets/cursor/next/commands/task-continue.md +49 -0
  239. package/presets/cursor/next/commands/task.md +50 -0
  240. package/presets/cursor/next/commands/technical-retro.md +81 -0
  241. package/presets/cursor/next/hooks/README.md +8 -0
  242. package/presets/cursor/next/hooks/chain-team-phases.sh +380 -0
  243. package/presets/cursor/next/hooks/guard-shell-command.sh +77 -0
  244. package/presets/cursor/next/hooks.json +17 -0
  245. package/presets/cursor/next/rules/README.md +67 -0
  246. package/presets/cursor/next/rules/agent-team-intake.mdc +14 -0
  247. package/presets/cursor/next/rules/agent-team-orchestrator.mdc +141 -0
  248. package/presets/cursor/next/rules/api-services.mdc +12 -10
  249. package/presets/cursor/next/rules/architecture-boundaries-ui.mdc +15 -0
  250. package/presets/cursor/next/rules/architecture-boundaries.mdc +31 -12
  251. package/presets/cursor/next/rules/arrow-functions.mdc +46 -0
  252. package/presets/cursor/next/rules/code-quality-and-refactoring.mdc +5 -4
  253. package/presets/cursor/next/rules/code-review-mr.mdc +21 -40
  254. package/presets/cursor/next/rules/css-property-order-stylelint.mdc +16 -0
  255. package/presets/cursor/next/rules/feature-delivery-workflow.mdc +76 -0
  256. package/presets/cursor/next/rules/http-client.mdc +42 -0
  257. package/presets/cursor/next/rules/layer-barrel-exports.mdc +59 -0
  258. package/presets/cursor/next/rules/navigation-router-stack.mdc +62 -0
  259. package/presets/cursor/next/rules/navigation-router-ui.mdc +16 -0
  260. package/presets/cursor/next/rules/next-app-core.mdc +18 -61
  261. package/presets/cursor/next/rules/next-app-router.mdc +36 -0
  262. package/presets/cursor/next/rules/no-props-spread.mdc +27 -4
  263. package/presets/cursor/next/rules/no-type-assertion-as-import-export.mdc +60 -0
  264. package/presets/cursor/next/rules/package-manager.mdc +16 -0
  265. package/presets/cursor/next/rules/playwright-agents.mdc +2 -1
  266. package/presets/cursor/next/rules/post-change-lint.mdc +40 -0
  267. package/presets/cursor/next/rules/public-imports.mdc +48 -0
  268. package/presets/cursor/next/rules/react-a11y-coding.mdc +37 -0
  269. package/presets/cursor/next/rules/react-ui.mdc +33 -3
  270. package/presets/cursor/next/rules/reference-features.mdc +39 -0
  271. package/presets/cursor/next/rules/store-rtk.mdc +13 -6
  272. package/presets/cursor/next/rules/technical-retro.mdc +12 -0
  273. package/presets/cursor/next/rules/tests-unit.mdc +30 -10
  274. package/presets/cursor/next/rules/types-jsdoc.mdc +42 -0
  275. package/presets/cursor/next/skills/README.md +15 -0
  276. package/presets/cursor/next/skills/ci-investigation/SKILL.md +36 -0
  277. package/presets/cursor/next/skills/code-review/SKILL.md +26 -0
  278. package/presets/cursor/next/skills/debug-investigation/SKILL.md +28 -0
  279. package/presets/cursor/next/skills/feature-delivery/SKILL.md +15 -0
  280. package/presets/cursor/next/skills/playwright-e2e/SKILL.md +31 -0
  281. package/presets/cursor/next/skills/technical-retro/SKILL.md +40 -0
  282. package/presets/cursor/next/skills/unit-testing/SKILL.md +32 -0
  283. package/presets/cursor/next/team/README.md +105 -0
  284. package/presets/cursor/next/team/fixtures/bugfix-standard.json +15 -0
  285. package/presets/cursor/next/team/fixtures/feature-full.json +16 -0
  286. package/presets/cursor/next/team/fixtures/feature-light.json +17 -0
  287. package/presets/cursor/next/team/tasks/.gitkeep +0 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,63 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ ### Breaking
6
+
7
+ - **Deprecated rule stubs removed** (Cursor + Claude `next`): `types-public-imports`, `api-public-imports`, `no-cross-component-styles-import` / `component-styles`. Use `public-imports` and `react-ui` instead.
8
+ - **`next` preset — post-change-lint no longer always-on:** Cursor `post-change-lint.mdc` and Claude twin are **requestable** (not session-start / `alwaysApply`). Load explicitly after code edits via skill `feature-delivery` or agent `build-verifier`. Session-start / alwaysApply is now **3** rules: `next-app-core`, `package-manager`, `code-quality-and-refactoring`. Workspace dogfood `.cursor/rules/post-change-lint.mdc` synced.
9
+
10
+ ### Added
11
+
12
+ - **Cursor + Claude `ios-swift` — full agent-team parity with `next`:** **21** agents (Playwright trio → `xcuitest-test-{planner,generator,healer}`), **7** skills (`xcuitest-e2e`), **5** slash commands, `hooks.json` + iOS-adapted `chain-team-phases.sh` (Cursor) / hook scripts + README (Claude), `team/fixtures/` ×3, `AGENTS.md` (Cursor) / thin `CLAUDE.md` (≤35 lines).
13
+ - **ios-swift rules:** agent-team intake/orchestrator, `xcode-tooling`, `reference-features`, domain rules (`navigation-coordinators`, `persistence-data`, `security-ios`, `module-public-api`), `technical-retro` alias; **21** rule topics (+ README). CLI init copies agents, hooks, skills, team, `AGENTS.md`.
14
+ - **ios-swift retro follow-ups:** `build-verifier` preset checks (chain ≠ next; ban Playwright/`lint:js` handoffs); enriched 16 priority agent prompts + 6 skills; dogfood checklist (5 scenarios) in `AGENTS.md` / `reference-features`; Cursor-only **`BUGBOT.md`** (iOS review priorities).
15
+
16
+ ### Changed
17
+
18
+ - **Token model (ios-swift + next):** both presets use **3** alwaysApply / session-start rules (~77 / ~59 body lines). Post-change verification is **requestable** — ios: `post-change-build`; next: `post-change-lint`. Orchestrator, intake, code-review, feature-delivery, tooling rules load on-demand (`paths:` / description).
19
+ - Claude `next`: `agent-team-orchestrator` and `code-review-mr` use `paths:` (on-demand) — session-start matches the 3-rule budget above.
20
+ - Cursor `next` agents: all pipeline agents set **`readonly: false`** so they can write `.cursor/team/**`. Production/app restrictions remain in prompt bodies (Cursor `readonly: true` blocks all file writes, including team artifacts).
21
+ - **ios-swift:** `networking-services` HTTP-only (persistence split out); soft AC-19 for thin aliases (`agent-team-intake`, `technical-retro`); `feature-developer` requires stack-specific hook handoff forks.
22
+
23
+ ### Notes
24
+
25
+ - **P2 optional (ios-swift):** Remaining polish: feature-delivery matrix enrichment, swift-conventions body cap. (`BUGBOT.md` shipped.)
26
+
27
+ ## 0.2.2
28
+
29
+ ### Breaking
30
+
31
+ - **`clean` is selective:** removes only CLI-managed paths (`rules`, `commands`, optional `agents`/`hooks`/`skills`/`team`, plus Cursor `hooks.json` / `BUGBOT.md` / `AGENTS.md`, Claude `CLAUDE.md`). Does **not** wipe the entire `.cursor/` or `.claude/` directory.
32
+
33
+ ### Added
34
+
35
+ - Cursor `next`: `architecture-boundaries-ui.mdc`, `navigation-router-ui.mdc` (slim UI-edit rules); Claude equivalents under `architecture/` and `stack/`.
36
+ - Cursor/Claude `next`: `AGENTS.md` on Cursor init; team `fixtures/` for pipeline profiles; pipeline profiles (`full` / `standard` / `light`) in `task-router`.
37
+ - Claude `next`: `hooks/chain-team-phases.sh` feature parity with Cursor (tool paths only differ).
38
+
39
+ ### Changed
40
+
41
+ - Narrower globs for full `architecture-boundaries` / `navigation-router(-stack)` vs UI slim rules; `layer-barrel-exports` → `index.ts`; styles colocation consolidated into `react-ui` (stubs remain).
42
+ - README documents `AGENTS.md` and selective `clean`.
43
+
44
+ ## 0.2.0
45
+
46
+ ### Breaking
47
+
48
+ - **Import rules merged:** `types-public-imports.mdc` and `api-public-imports.mdc` → **`public-imports.mdc`** (Claude: `architecture/public-imports.md`). Old filenames remain as deprecated stubs for one release cycle.
49
+ - **`feature-delivery-flow.mdc` removed** — content merged into `feature-delivery-workflow.mdc`.
50
+ - **`agent-team-intake`** no longer always-on (Cursor: `alwaysApply: false`; Claude: `paths:` on commands/team). Use orchestrator or `/task`.
51
+
52
+ ### Changed
53
+
54
+ - Slimmed always-on rules: `next-app-core`, `code-quality-and-refactoring`, `post-change-lint`, `package-manager` (~9 KB baseline vs ~21 KB).
55
+ - Narrowed globs: `css-property-order-stylelint`, `no-type-assertion-as-import-export`, `reference-features`, `public-imports`.
56
+ - `css-property-order` stub — property list delegated to Stylelint `--fix`.
57
+ - Slimmed `task-router` agent; pipeline JSON examples moved to `agents/README.md`.
58
+ - Agents reference skills as SSOT; scoped lint for `feature-developer` when next step is `build-verifier`.
59
+ - Orchestrator: explicit fast-path when to skip pipeline.
60
+
61
+ ## 0.1.42
62
+
63
+ Prior releases — see git history.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @bonesofspring/ai-rules
2
2
 
3
- Presets for Cursor and Claude Code: rules, commands, plus for Claude `CLAUDE.md` and `skills` / `agents` / `hooks` when the preset includes them. Install from npm into a project so you don’t have to copy files out of the repo by hand.
3
+ Presets for Cursor and Claude Code: rules, commands, plus optional `agents`, `hooks`, `skills`, and team artifacts when the preset includes them. For Claude: `CLAUDE.md`. Install from npm into a project so you don’t have to copy files out of the repo by hand.
4
4
 
5
5
  Node 18+.
6
6
 
@@ -13,9 +13,27 @@ npx @bonesofspring/ai-rules clean cursor
13
13
 
14
14
  Global: `npm i -g @bonesofspring/ai-rules`, then `ai-rules ...`.
15
15
 
16
- `init` merges into the current directory: dirs are created, matching files are **overwritten**. `--preset` and the subcommand can be in either order, e.g. `--preset=next init cursor`.
16
+ `init` merges into the **current working directory** (or `--cwd <dir>`): dirs are created, matching files are **overwritten**. `--preset` defaults to **`next`**. Supported forms:
17
17
 
18
- `clean cursor` / `clean claude` removes what this CLI installs: for Cursor, the entire `.cursor` directory; for Claude, `.claude/rules`, `.claude/commands`, `skills`, `agents`, `hooks`, and `CLAUDE.md` when present. Anything else under `.claude` is left alone.
18
+ ```bash
19
+ npx @bonesofspring/ai-rules init cursor --preset next
20
+ npx @bonesofspring/ai-rules init cursor next
21
+ npx @bonesofspring/ai-rules init cursor # preset next by default
22
+ npx @bonesofspring/ai-rules cursor init --preset next
23
+ ```
24
+
25
+ If `.cursor` does not appear, check the command output for errors and confirm you run init from the **target project root** (where the app lives), not from `node_modules`. Success ends with: `Done. .cursor installed at <absolute-path>`.
26
+
27
+ ### `clean` (breaking vs older wipe behavior)
28
+
29
+ `clean cursor` / `clean claude` removes **only CLI-managed paths** — not the entire `.cursor/` or `.claude/` tree:
30
+
31
+ - `rules/`, `commands/`
32
+ - optional dirs when present: `agents/`, `hooks/`, `skills/`, `team/`
33
+ - Cursor root files: `hooks.json`, `BUGBOT.md`, `AGENTS.md`
34
+ - Claude root file: `CLAUDE.md`
35
+
36
+ Any other files you added under `.cursor/` or `.claude/` (notes, local overrides, IDE state) are **left intact**. Older releases that deleted the whole tool directory are no longer the behavior.
19
37
 
20
38
  Where things go on `init`:
21
39
 
@@ -23,7 +41,11 @@ Where things go on `init`:
23
41
  |---|--------|--------|
24
42
  | rules | `.cursor/rules` | `.claude/rules` |
25
43
  | commands | `.cursor/commands` | `.claude/commands` |
26
- | other | | root `CLAUDE.md` → `.claude/CLAUDE.md`; folders `skills`, `agents`, `hooks` → under `.claude/` with the same names |
44
+ | agents | `.cursor/agents` | `.claude/agents` |
45
+ | hooks | `.cursor/hooks`, `.cursor/hooks.json` | `.claude/hooks` |
46
+ | skills | `.cursor/skills` | `.claude/skills` |
47
+ | team artifacts template | `.cursor/team` | `.claude/team` |
48
+ | other | `BUGBOT.md`, `AGENTS.md` → `.cursor/` | `CLAUDE.md` → `.claude/CLAUDE.md` |
27
49
 
28
50
  The package ships presets including **`next`** (Next.js stack) and **`ios-swift`** (iOS apps on Swift / SwiftUI). Other preset names: see `presets/` in the [repo](https://github.com/bonesofspring/ai-rules). Name is a single path segment, no `/` or `..`.
29
51
 
package/bin/cli.js CHANGED
@@ -5,51 +5,88 @@
5
5
  const fs = require('fs');
6
6
  const path = require('path');
7
7
 
8
- const packageRoot = path.join(__dirname, '..');
9
-
10
8
  /** Single path segment: letters, digits, dot, underscore, hyphen; no separators or "..". */
11
9
  const PRESET_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
10
+ const DEFAULT_PRESET = 'next';
11
+ const TOOLS = new Set(['cursor', 'claude']);
12
12
 
13
13
  const PRESETS = {
14
14
  cursor: {
15
15
  rulesDir: '.cursor/rules',
16
16
  commandsDir: '.cursor/commands',
17
17
  relBase: ['presets', 'cursor'],
18
+ optionalCursorDirs: ['agents', 'hooks', 'skills', 'team'],
19
+ hooksJsonSrc: 'hooks.json',
20
+ toolRootFiles: ['BUGBOT.md', 'AGENTS.md'],
18
21
  },
19
22
  claude: {
20
23
  rulesDir: '.claude/rules',
21
24
  commandsDir: '.claude/commands',
22
25
  relBase: ['presets', 'claude'],
23
- /** Optional dirs under preset root → under `.claude/` (recursive copy). */
24
- optionalClaudeDirs: ['skills', 'agents', 'hooks'],
25
- /** Copied from preset root to `.claude/CLAUDE.md` when present. */
26
+ optionalClaudeDirs: ['skills', 'agents', 'hooks', 'team'],
26
27
  claudeMdSrc: 'CLAUDE.md',
27
28
  },
28
29
  };
29
30
 
31
+ function getPackageRoot() {
32
+ try {
33
+ return path.dirname(require.resolve('@bonesofspring/ai-rules/package.json'));
34
+ } catch {
35
+ return path.join(__dirname, '..');
36
+ }
37
+ }
38
+
30
39
  function printHelp() {
31
40
  console.log(`@bonesofspring/ai-rules
32
41
 
33
42
  Usage:
34
- ai-rules init <cursor|claude> --preset <name> Copy preset rules and commands into the current directory
35
- ai-rules clean <cursor|claude> Remove preset target rules and commands directories
43
+ ai-rules init <cursor|claude> [--preset <name>]
44
+ ai-rules init <cursor|claude> <preset-name>
45
+ ai-rules clean <cursor|claude> [--cwd <dir>]
46
+
47
+ Options:
48
+ --preset <name> Preset name (default: ${DEFAULT_PRESET})
49
+ --cwd <dir> Target project directory (default: current working directory)
36
50
 
37
51
  Notes:
38
- init merges into existing target folders; same-named files are overwritten.
39
- clean cursor removes the entire .cursor directory (if present).
40
- Flags may appear before or after the subcommand (e.g. --preset next init cursor).
52
+ init merges into the target directory; same-named files are overwritten.
53
+ Cursor init copies rules, commands, agents, hooks, skills, team, hooks.json, BUGBOT.md, AGENTS.md.
54
+ Claude init copies rules, commands, skills, agents, hooks, team, and CLAUDE.md when present.
55
+ Command forms: "init cursor --preset next", "init cursor next", "--preset next init cursor", "cursor init --preset next".
41
56
 
42
57
  Examples:
43
58
  npx @bonesofspring/ai-rules init cursor --preset next
59
+ npx @bonesofspring/ai-rules init cursor next
60
+ npx @bonesofspring/ai-rules init cursor --preset ios-swift
61
+ npx @bonesofspring/ai-rules init claude
44
62
  npx @bonesofspring/ai-rules init claude --preset ios-swift
45
- npx @bonesofspring/ai-rules clean claude
63
+ npx @bonesofspring/ai-rules clean cursor
46
64
  `);
47
65
  }
48
66
 
49
67
  function parseArgs(argv) {
50
- const args = { _: [] };
68
+ const args = { _: [], cwd: undefined, preset: undefined, presetError: undefined };
51
69
  for (let i = 0; i < argv.length; i++) {
52
70
  const a = argv[i];
71
+ if (a === '--cwd') {
72
+ const value = argv[i + 1];
73
+ if (value === undefined || value.startsWith('-')) {
74
+ args.cwdError = 'Missing value for --cwd';
75
+ continue;
76
+ }
77
+ args.cwd = value;
78
+ i++;
79
+ continue;
80
+ }
81
+ if (a.startsWith('--cwd=')) {
82
+ const value = a.slice('--cwd='.length);
83
+ if (value === '') {
84
+ args.cwdError = 'Missing value after --cwd=';
85
+ continue;
86
+ }
87
+ args.cwd = value;
88
+ continue;
89
+ }
53
90
  if (a === '--preset') {
54
91
  const value = argv[i + 1];
55
92
  if (value === undefined || value.startsWith('-')) {
@@ -70,17 +107,53 @@ function parseArgs(argv) {
70
107
  args.preset = value;
71
108
  continue;
72
109
  }
110
+ if (a === '-h' || a === '--help') {
111
+ args.help = true;
112
+ continue;
113
+ }
73
114
  args._.push(a);
74
115
  }
75
116
  return args;
76
117
  }
77
118
 
119
+ /**
120
+ * Supports: init cursor, cursor init, init cursor next (positional preset).
121
+ */
122
+ function normalizeInitClean(parsed) {
123
+ const positional = [...parsed._];
124
+ let command;
125
+ let tool;
126
+ let presetFromPositional;
127
+
128
+ if (positional.length >= 2 && TOOLS.has(positional[0]) && positional[1] === 'init') {
129
+ command = 'init';
130
+ tool = positional[0];
131
+ presetFromPositional = positional[2];
132
+ } else if (positional.length >= 2 && positional[0] === 'init' && TOOLS.has(positional[1])) {
133
+ command = 'init';
134
+ tool = positional[1];
135
+ presetFromPositional = positional[2];
136
+ } else if (positional.length >= 2 && positional[0] === 'clean' && TOOLS.has(positional[1])) {
137
+ command = 'clean';
138
+ tool = positional[1];
139
+ } else if (positional.length >= 1) {
140
+ command = positional[0];
141
+ tool = positional[1];
142
+ if (command === 'init' && positional[2] && PRESET_NAME_RE.test(positional[2])) {
143
+ presetFromPositional = positional[2];
144
+ }
145
+ }
146
+
147
+ const preset = parsed.preset || presetFromPositional;
148
+ return { command, tool, preset };
149
+ }
150
+
78
151
  /**
79
152
  * @returns {string | null} Error message or null if valid.
80
153
  */
81
154
  function validatePresetName(preset) {
82
155
  if (preset === undefined || preset === '') {
83
- return 'Missing --preset <name>';
156
+ return 'Missing preset name (use --preset <name>, e.g. --preset next)';
84
157
  }
85
158
  if (!PRESET_NAME_RE.test(preset) || preset.includes('..')) {
86
159
  return (
@@ -91,9 +164,6 @@ function validatePresetName(preset) {
91
164
  return null;
92
165
  }
93
166
 
94
- /**
95
- * Ensures resolved preset dir stays under the tool presets root (defense in depth).
96
- */
97
167
  function assertPresetDirInsideRoot(presetsRoot, presetBase) {
98
168
  const root = path.resolve(presetsRoot);
99
169
  const resolved = path.resolve(presetBase);
@@ -117,10 +187,17 @@ function copyDir(src, dest) {
117
187
  copyDir(from, to);
118
188
  } else {
119
189
  fs.copyFileSync(from, to);
190
+ if (e.name.endsWith('.sh')) {
191
+ fs.chmodSync(to, 0o755);
192
+ }
120
193
  }
121
194
  }
122
195
  }
123
196
 
197
+ function getOptionalDirs(cfg) {
198
+ return cfg.optionalCursorDirs || cfg.optionalClaudeDirs || [];
199
+ }
200
+
124
201
  function removeDirIfExists(dir) {
125
202
  if (fs.existsSync(dir)) {
126
203
  fs.rmSync(dir, { recursive: true, force: true });
@@ -133,76 +210,157 @@ function removeFileIfExists(filePath) {
133
210
  }
134
211
  }
135
212
 
213
+ function listPresetNames(presetsRoot) {
214
+ if (!fs.existsSync(presetsRoot)) {
215
+ return [];
216
+ }
217
+ return fs
218
+ .readdirSync(presetsRoot, { withFileTypes: true })
219
+ .filter((e) => e.isDirectory())
220
+ .map((e) => e.name)
221
+ .filter((name) => PRESET_NAME_RE.test(name));
222
+ }
223
+
136
224
  function presetHasAnySource(base, cfg) {
137
225
  const rulesSrc = path.join(base, 'rules');
138
226
  const commandsSrc = path.join(base, 'commands');
139
227
  if (fs.existsSync(rulesSrc) || fs.existsSync(commandsSrc)) {
140
228
  return true;
141
229
  }
142
- if (cfg.optionalClaudeDirs) {
143
- for (const name of cfg.optionalClaudeDirs) {
144
- if (fs.existsSync(path.join(base, name))) {
145
- return true;
146
- }
230
+ for (const name of getOptionalDirs(cfg)) {
231
+ if (fs.existsSync(path.join(base, name))) {
232
+ return true;
147
233
  }
148
234
  }
149
235
  if (cfg.claudeMdSrc && fs.existsSync(path.join(base, cfg.claudeMdSrc))) {
150
236
  return true;
151
237
  }
238
+ if (cfg.hooksJsonSrc && fs.existsSync(path.join(base, cfg.hooksJsonSrc))) {
239
+ return true;
240
+ }
241
+ for (const name of cfg.toolRootFiles || []) {
242
+ if (fs.existsSync(path.join(base, name))) {
243
+ return true;
244
+ }
245
+ }
152
246
  return false;
153
247
  }
154
248
 
155
- function cmdInit(tool, preset) {
156
- const cfg = PRESETS[tool];
157
- if (!cfg) {
158
- console.error(`Unknown tool: ${tool}. Use cursor or claude.`);
249
+ function resolveTargetCwd(cwdOption) {
250
+ const cwd = cwdOption ? path.resolve(cwdOption) : process.cwd();
251
+ if (!fs.existsSync(cwd)) {
252
+ console.error(`Target directory does not exist: ${cwd}`);
253
+ process.exit(1);
254
+ }
255
+ if (!fs.statSync(cwd).isDirectory()) {
256
+ console.error(`Target path is not a directory: ${cwd}`);
159
257
  process.exit(1);
160
258
  }
161
- const nameErr = validatePresetName(preset);
259
+ return cwd;
260
+ }
261
+
262
+ function resolvePresetName(tool, preset, packageRoot) {
263
+ const cfg = PRESETS[tool];
264
+ const presetsRoot = path.join(packageRoot, ...cfg.relBase);
265
+ let name = preset || DEFAULT_PRESET;
266
+
267
+ const nameErr = validatePresetName(name);
162
268
  if (nameErr) {
163
269
  console.error(nameErr);
164
270
  process.exit(1);
165
271
  }
166
- const presetsRoot = path.join(packageRoot, ...cfg.relBase);
167
- const base = path.join(presetsRoot, preset);
272
+
273
+ let base = path.join(presetsRoot, name);
274
+ if (!presetHasAnySource(base, cfg)) {
275
+ const available = listPresetNames(presetsRoot);
276
+ if (!preset && available.includes(DEFAULT_PRESET)) {
277
+ name = DEFAULT_PRESET;
278
+ base = path.join(presetsRoot, name);
279
+ } else {
280
+ console.error(`Preset "${name}" for ${tool} not found.`);
281
+ console.error(`Looked in: ${base}`);
282
+ console.error(`Package root: ${packageRoot}`);
283
+ if (available.length > 0) {
284
+ console.error(`Available presets: ${available.join(', ')}`);
285
+ } else {
286
+ console.error(`No presets directory at: ${presetsRoot}`);
287
+ console.error(
288
+ 'The installed package may be incomplete. Reinstall @bonesofspring/ai-rules or run from the package source.',
289
+ );
290
+ }
291
+ process.exit(1);
292
+ }
293
+ }
294
+
168
295
  assertPresetDirInsideRoot(presetsRoot, base);
296
+ return { name, base, presetsRoot };
297
+ }
298
+
299
+ function cmdInit(tool, preset, cwdOption) {
300
+ const cfg = PRESETS[tool];
301
+ if (!cfg) {
302
+ console.error(`Unknown tool: ${tool}. Use cursor or claude.`);
303
+ process.exit(1);
304
+ }
305
+
306
+ const packageRoot = getPackageRoot();
307
+ const cwd = resolveTargetCwd(cwdOption);
308
+ const { name: presetName, base } = resolvePresetName(tool, preset, packageRoot);
169
309
 
170
310
  const rulesSrc = path.join(base, 'rules');
171
311
  const commandsSrc = path.join(base, 'commands');
172
- const cwd = process.cwd();
312
+ const toolRoot = tool === 'cursor' ? '.cursor' : '.claude';
313
+ const toolRootAbs = path.join(cwd, toolRoot);
173
314
 
174
- if (!presetHasAnySource(base, cfg)) {
175
- console.error(`Preset "${preset}" for ${tool} not found under ${base}`);
176
- process.exit(1);
177
- }
315
+ fs.mkdirSync(toolRootAbs, { recursive: true });
316
+
317
+ let copiedSteps = 0;
178
318
 
179
319
  try {
180
320
  if (tool === 'claude' && cfg.claudeMdSrc) {
181
321
  const mdFrom = path.join(base, cfg.claudeMdSrc);
182
322
  if (fs.existsSync(mdFrom)) {
183
- const claudeRoot = path.join(cwd, '.claude');
184
- fs.mkdirSync(claudeRoot, { recursive: true });
185
- fs.copyFileSync(mdFrom, path.join(claudeRoot, 'CLAUDE.md'));
186
- console.log('Copied CLAUDE.md → .claude/CLAUDE.md');
323
+ fs.copyFileSync(mdFrom, path.join(toolRootAbs, 'CLAUDE.md'));
324
+ console.log(`Copied CLAUDE.md ${path.join(toolRoot, 'CLAUDE.md')}`);
325
+ copiedSteps++;
187
326
  }
188
327
  }
189
328
 
190
329
  if (fs.existsSync(rulesSrc)) {
191
330
  copyDir(rulesSrc, path.join(cwd, cfg.rulesDir));
192
331
  console.log(`Copied rules → ${cfg.rulesDir}`);
332
+ copiedSteps++;
193
333
  }
194
334
  if (fs.existsSync(commandsSrc)) {
195
335
  copyDir(commandsSrc, path.join(cwd, cfg.commandsDir));
196
336
  console.log(`Copied commands → ${cfg.commandsDir}`);
337
+ copiedSteps++;
338
+ }
339
+
340
+ for (const name of getOptionalDirs(cfg)) {
341
+ const src = path.join(base, name);
342
+ if (fs.existsSync(src)) {
343
+ copyDir(src, path.join(toolRootAbs, name));
344
+ console.log(`Copied ${name}/ → ${toolRoot}/${name}/`);
345
+ copiedSteps++;
346
+ }
347
+ }
348
+
349
+ if (tool === 'cursor' && cfg.hooksJsonSrc) {
350
+ const hooksFrom = path.join(base, cfg.hooksJsonSrc);
351
+ if (fs.existsSync(hooksFrom)) {
352
+ fs.copyFileSync(hooksFrom, path.join(toolRootAbs, 'hooks.json'));
353
+ console.log(`Copied hooks.json → ${toolRoot}/hooks.json`);
354
+ copiedSteps++;
355
+ }
197
356
  }
198
357
 
199
- if (tool === 'claude' && cfg.optionalClaudeDirs) {
200
- for (const name of cfg.optionalClaudeDirs) {
201
- const src = path.join(base, name);
202
- if (fs.existsSync(src)) {
203
- copyDir(src, path.join(cwd, '.claude', name));
204
- console.log(`Copied ${name}/ → .claude/${name}/`);
205
- }
358
+ for (const name of cfg.toolRootFiles || []) {
359
+ const from = path.join(base, name);
360
+ if (fs.existsSync(from)) {
361
+ fs.copyFileSync(from, path.join(toolRootAbs, name));
362
+ console.log(`Copied ${name} → ${toolRoot}/${name}`);
363
+ copiedSteps++;
206
364
  }
207
365
  }
208
366
  } catch (err) {
@@ -210,66 +368,95 @@ function cmdInit(tool, preset) {
210
368
  console.error(`init failed: ${msg}`);
211
369
  process.exit(1);
212
370
  }
371
+
372
+ if (copiedSteps === 0) {
373
+ console.error(`init failed: preset "${presetName}" had no files to copy from ${base}`);
374
+ process.exit(1);
375
+ }
376
+
377
+ if (!fs.existsSync(toolRootAbs)) {
378
+ console.error(`init failed: ${toolRootAbs} was not created`);
379
+ process.exit(1);
380
+ }
381
+
382
+ console.log(`Done. ${toolRoot} installed at ${toolRootAbs} (preset: ${presetName})`);
213
383
  }
214
384
 
215
- function cmdClean(tool) {
385
+ function cmdClean(tool, cwdOption) {
216
386
  const cfg = PRESETS[tool];
217
387
  if (!cfg) {
218
388
  console.error(`Unknown tool: ${tool}. Use cursor or claude.`);
219
389
  process.exit(1);
220
390
  }
221
- const cwd = process.cwd();
222
- if (tool === 'cursor') {
223
- removeDirIfExists(path.join(cwd, '.cursor'));
224
- console.log('Removed .cursor (if present)');
225
- return;
226
- }
391
+ const cwd = resolveTargetCwd(cwdOption);
392
+ const toolRoot = tool === 'cursor' ? '.cursor' : '.claude';
393
+ const removedParts = [cfg.rulesDir, cfg.commandsDir];
394
+
227
395
  removeDirIfExists(path.join(cwd, cfg.rulesDir));
228
396
  removeDirIfExists(path.join(cwd, cfg.commandsDir));
229
- if (tool === 'claude' && cfg.optionalClaudeDirs) {
230
- for (const name of cfg.optionalClaudeDirs) {
231
- removeDirIfExists(path.join(cwd, '.claude', name));
232
- }
233
- removeFileIfExists(path.join(cwd, '.claude', 'CLAUDE.md'));
234
- }
235
- console.log(
236
- `Removed ${cfg.rulesDir} and ${cfg.commandsDir}` +
237
- (tool === 'claude' && cfg.optionalClaudeDirs
238
- ? `, optional .claude/{${cfg.optionalClaudeDirs.join(',')}}, and .claude/CLAUDE.md`
239
- : '') +
240
- ' (if present)',
241
- );
397
+
398
+ const optionalDirs = getOptionalDirs(cfg);
399
+ for (const name of optionalDirs) {
400
+ removeDirIfExists(path.join(cwd, toolRoot, name));
401
+ removedParts.push(`${toolRoot}/${name}`);
402
+ }
403
+
404
+ if (cfg.claudeMdSrc) {
405
+ removeFileIfExists(path.join(cwd, toolRoot, 'CLAUDE.md'));
406
+ removedParts.push(`${toolRoot}/CLAUDE.md`);
407
+ }
408
+
409
+ if (cfg.hooksJsonSrc) {
410
+ removeFileIfExists(path.join(cwd, toolRoot, 'hooks.json'));
411
+ removedParts.push(`${toolRoot}/hooks.json`);
412
+ }
413
+
414
+ for (const name of cfg.toolRootFiles || []) {
415
+ removeFileIfExists(path.join(cwd, toolRoot, name));
416
+ removedParts.push(`${toolRoot}/${name}`);
417
+ }
418
+
419
+ console.log(`Removed ${removedParts.join(', ')} (if present)`);
242
420
  }
243
421
 
244
422
  function main() {
245
423
  const argv = process.argv.slice(2);
246
- if (argv.length === 0 || argv.includes('-h') || argv.includes('--help')) {
424
+ if (argv.length === 0) {
247
425
  printHelp();
248
426
  process.exit(0);
249
427
  }
250
428
 
251
429
  const parsed = parseArgs(argv);
252
- const [command, tool] = parsed._;
430
+ if (parsed.help) {
431
+ printHelp();
432
+ process.exit(0);
433
+ }
253
434
 
254
435
  if (parsed.presetError) {
255
436
  console.error(parsed.presetError);
256
437
  process.exit(1);
257
438
  }
439
+ if (parsed.cwdError) {
440
+ console.error(parsed.cwdError);
441
+ process.exit(1);
442
+ }
443
+
444
+ const { command, tool, preset } = normalizeInitClean(parsed);
258
445
 
259
446
  if (command === 'init') {
260
- if (!tool) {
261
- console.error('Missing <cursor|claude> after init.');
447
+ if (!tool || !TOOLS.has(tool)) {
448
+ console.error('Missing or invalid tool. Use: init cursor|claude [--preset next]');
262
449
  process.exit(1);
263
450
  }
264
- cmdInit(tool, parsed.preset);
451
+ cmdInit(tool, preset, parsed.cwd);
265
452
  return;
266
453
  }
267
454
  if (command === 'clean') {
268
- if (!tool) {
269
- console.error('Missing <cursor|claude> after clean.');
455
+ if (!tool || !TOOLS.has(tool)) {
456
+ console.error('Missing or invalid tool. Use: clean cursor|claude');
270
457
  process.exit(1);
271
458
  }
272
- cmdClean(tool);
459
+ cmdClean(tool, parsed.cwd);
273
460
  return;
274
461
  }
275
462
 
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bonesofspring/ai-rules",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Presets of Cursor and Claude rules/commands for Revy Ross personal use",
5
5
  "license": "MIT",
6
6
  "author": "Revy Ross",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/bonesofspring/ai-rules.git"
9
+ "url": "git+https://github.com/bonesofspring/ai-rules.git"
10
10
  },
11
11
  "keywords": [
12
12
  "cursor",
@@ -20,6 +20,7 @@
20
20
  },
21
21
  "files": [
22
22
  "README.md",
23
+ "CHANGELOG.md",
23
24
  "bin",
24
25
  "presets"
25
26
  ],