safeword 0.2.3 → 0.2.4

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 (235) hide show
  1. package/.claude/commands/arch-review.md +32 -0
  2. package/.claude/commands/lint.md +6 -0
  3. package/.claude/commands/quality-review.md +13 -0
  4. package/.claude/commands/setup-linting.md +6 -0
  5. package/.claude/hooks/auto-lint.sh +6 -0
  6. package/.claude/hooks/auto-quality-review.sh +170 -0
  7. package/.claude/hooks/check-linting-sync.sh +17 -0
  8. package/.claude/hooks/inject-timestamp.sh +6 -0
  9. package/.claude/hooks/question-protocol.sh +12 -0
  10. package/.claude/hooks/run-linters.sh +8 -0
  11. package/.claude/hooks/run-quality-review.sh +76 -0
  12. package/.claude/hooks/version-check.sh +10 -0
  13. package/.claude/mcp/README.md +96 -0
  14. package/.claude/mcp/arcade.sample.json +9 -0
  15. package/.claude/mcp/context7.sample.json +7 -0
  16. package/.claude/mcp/playwright.sample.json +7 -0
  17. package/.claude/settings.json +62 -0
  18. package/.claude/skills/quality-reviewer/SKILL.md +190 -0
  19. package/.claude/skills/safeword-quality-reviewer/SKILL.md +13 -0
  20. package/.env.arcade.example +4 -0
  21. package/.env.example +11 -0
  22. package/.gitmodules +4 -0
  23. package/.safeword/SAFEWORD.md +33 -0
  24. package/.safeword/eslint/eslint-base.mjs +101 -0
  25. package/.safeword/guides/architecture-guide.md +404 -0
  26. package/.safeword/guides/code-philosophy.md +174 -0
  27. package/.safeword/guides/context-files-guide.md +405 -0
  28. package/.safeword/guides/data-architecture-guide.md +183 -0
  29. package/.safeword/guides/design-doc-guide.md +165 -0
  30. package/.safeword/guides/learning-extraction.md +515 -0
  31. package/.safeword/guides/llm-instruction-design.md +239 -0
  32. package/.safeword/guides/llm-prompting.md +95 -0
  33. package/.safeword/guides/tdd-best-practices.md +570 -0
  34. package/.safeword/guides/test-definitions-guide.md +243 -0
  35. package/.safeword/guides/testing-methodology.md +573 -0
  36. package/.safeword/guides/user-story-guide.md +237 -0
  37. package/.safeword/guides/zombie-process-cleanup.md +214 -0
  38. package/{templates → .safeword}/hooks/agents-md-check.sh +0 -0
  39. package/{templates → .safeword}/hooks/post-tool.sh +0 -0
  40. package/{templates → .safeword}/hooks/pre-commit.sh +0 -0
  41. package/.safeword/planning/002-user-story-quality-evaluation.md +1840 -0
  42. package/.safeword/planning/003-langsmith-eval-setup-prompt.md +363 -0
  43. package/.safeword/planning/004-llm-eval-test-cases.md +3226 -0
  44. package/.safeword/planning/005-architecture-enforcement-system.md +169 -0
  45. package/.safeword/planning/006-reactive-fix-prevention-research.md +135 -0
  46. package/.safeword/planning/011-cli-ux-vision.md +330 -0
  47. package/.safeword/planning/012-project-structure-cleanup.md +154 -0
  48. package/.safeword/planning/README.md +39 -0
  49. package/.safeword/planning/automation-plan-v2.md +1225 -0
  50. package/.safeword/planning/automation-plan-v3.md +1291 -0
  51. package/.safeword/planning/automation-plan.md +3058 -0
  52. package/.safeword/planning/design/005-cli-implementation.md +343 -0
  53. package/.safeword/planning/design/013-cli-self-contained-templates.md +596 -0
  54. package/.safeword/planning/design/013a-eslint-plugin-suite.md +256 -0
  55. package/.safeword/planning/design/013b-implementation-snippets.md +385 -0
  56. package/.safeword/planning/design/013c-config-isolation-strategy.md +242 -0
  57. package/.safeword/planning/design/code-philosophy-improvements.md +60 -0
  58. package/.safeword/planning/mcp-analysis.md +545 -0
  59. package/.safeword/planning/phase2-subagents-vs-skills-analysis.md +451 -0
  60. package/.safeword/planning/settings-improvements.md +970 -0
  61. package/.safeword/planning/test-definitions/005-cli-implementation.md +1301 -0
  62. package/.safeword/planning/test-definitions/cli-self-contained-templates.md +205 -0
  63. package/.safeword/planning/user-stories/001-guides-review-user-stories.md +1381 -0
  64. package/.safeword/planning/user-stories/003-reactive-fix-prevention.md +132 -0
  65. package/.safeword/planning/user-stories/004-technical-constraints.md +86 -0
  66. package/.safeword/planning/user-stories/005-cli-implementation.md +311 -0
  67. package/.safeword/planning/user-stories/cli-self-contained-templates.md +172 -0
  68. package/.safeword/planning/versioned-distribution.md +740 -0
  69. package/.safeword/prompts/arch-review.md +43 -0
  70. package/.safeword/prompts/quality-review.md +11 -0
  71. package/.safeword/scripts/arch-review.sh +235 -0
  72. package/.safeword/scripts/check-linting-sync.sh +58 -0
  73. package/.safeword/scripts/setup-linting.sh +559 -0
  74. package/.safeword/templates/architecture-template.md +136 -0
  75. package/.safeword/templates/ci/architecture-check.yml +79 -0
  76. package/.safeword/templates/design-doc-template.md +127 -0
  77. package/.safeword/templates/test-definitions-feature.md +100 -0
  78. package/.safeword/templates/ticket-template.md +74 -0
  79. package/.safeword/templates/user-stories-template.md +82 -0
  80. package/.safeword/tickets/001-guides-review-user-stories.md +83 -0
  81. package/.safeword/tickets/002-architecture-enforcement.md +211 -0
  82. package/.safeword/tickets/003-reactive-fix-prevention.md +57 -0
  83. package/.safeword/tickets/004-technical-constraints-in-user-stories.md +39 -0
  84. package/.safeword/tickets/005-cli-implementation.md +248 -0
  85. package/.safeword/tickets/006-flesh-out-skills.md +43 -0
  86. package/.safeword/tickets/007-flesh-out-questioning.md +44 -0
  87. package/.safeword/tickets/008-upgrade-questioning.md +58 -0
  88. package/.safeword/tickets/009-naming-conventions.md +41 -0
  89. package/.safeword/tickets/010-safeword-md-cleanup.md +34 -0
  90. package/.safeword/tickets/011-cursor-setup.md +86 -0
  91. package/.safeword/tickets/README.md +73 -0
  92. package/.safeword/version +1 -0
  93. package/AGENTS.md +59 -0
  94. package/CLAUDE.md +12 -0
  95. package/README.md +347 -0
  96. package/docs/001-cli-implementation-plan.md +856 -0
  97. package/docs/elite-dx-implementation-plan.md +1034 -0
  98. package/framework/README.md +131 -0
  99. package/framework/mcp/README.md +96 -0
  100. package/framework/mcp/arcade.sample.json +8 -0
  101. package/framework/mcp/context7.sample.json +6 -0
  102. package/framework/mcp/playwright.sample.json +6 -0
  103. package/framework/scripts/arch-review.sh +235 -0
  104. package/framework/scripts/check-linting-sync.sh +58 -0
  105. package/framework/scripts/load-env.sh +49 -0
  106. package/framework/scripts/setup-claude.sh +223 -0
  107. package/framework/scripts/setup-linting.sh +559 -0
  108. package/framework/scripts/setup-quality.sh +477 -0
  109. package/framework/scripts/setup-safeword.sh +550 -0
  110. package/framework/templates/ci/architecture-check.yml +78 -0
  111. package/learnings/ai-sdk-v5-breaking-changes.md +178 -0
  112. package/learnings/e2e-test-zombie-processes.md +231 -0
  113. package/learnings/milkdown-crepe-editor-property.md +96 -0
  114. package/learnings/prosemirror-fragment-traversal.md +119 -0
  115. package/package.json +19 -43
  116. package/packages/cli/AGENTS.md +1 -0
  117. package/packages/cli/ARCHITECTURE.md +279 -0
  118. package/packages/cli/package.json +51 -0
  119. package/packages/cli/src/cli.ts +63 -0
  120. package/packages/cli/src/commands/check.ts +166 -0
  121. package/packages/cli/src/commands/diff.ts +209 -0
  122. package/packages/cli/src/commands/reset.ts +190 -0
  123. package/packages/cli/src/commands/setup.ts +325 -0
  124. package/packages/cli/src/commands/upgrade.ts +163 -0
  125. package/packages/cli/src/index.ts +3 -0
  126. package/packages/cli/src/templates/config.ts +58 -0
  127. package/packages/cli/src/templates/content.ts +18 -0
  128. package/packages/cli/src/templates/index.ts +12 -0
  129. package/packages/cli/src/utils/agents-md.ts +66 -0
  130. package/packages/cli/src/utils/fs.ts +179 -0
  131. package/packages/cli/src/utils/git.ts +124 -0
  132. package/packages/cli/src/utils/hooks.ts +29 -0
  133. package/packages/cli/src/utils/output.ts +60 -0
  134. package/packages/cli/src/utils/project-detector.test.ts +185 -0
  135. package/packages/cli/src/utils/project-detector.ts +44 -0
  136. package/packages/cli/src/utils/version.ts +28 -0
  137. package/packages/cli/src/version.ts +6 -0
  138. package/packages/cli/templates/SAFEWORD.md +776 -0
  139. package/packages/cli/templates/doc-templates/architecture-template.md +136 -0
  140. package/packages/cli/templates/doc-templates/design-doc-template.md +134 -0
  141. package/packages/cli/templates/doc-templates/test-definitions-feature.md +131 -0
  142. package/packages/cli/templates/doc-templates/ticket-template.md +82 -0
  143. package/packages/cli/templates/doc-templates/user-stories-template.md +92 -0
  144. package/packages/cli/templates/guides/architecture-guide.md +423 -0
  145. package/packages/cli/templates/guides/code-philosophy.md +195 -0
  146. package/packages/cli/templates/guides/context-files-guide.md +457 -0
  147. package/packages/cli/templates/guides/data-architecture-guide.md +200 -0
  148. package/packages/cli/templates/guides/design-doc-guide.md +171 -0
  149. package/packages/cli/templates/guides/learning-extraction.md +552 -0
  150. package/packages/cli/templates/guides/llm-instruction-design.md +248 -0
  151. package/packages/cli/templates/guides/llm-prompting.md +102 -0
  152. package/packages/cli/templates/guides/tdd-best-practices.md +615 -0
  153. package/packages/cli/templates/guides/test-definitions-guide.md +334 -0
  154. package/packages/cli/templates/guides/testing-methodology.md +618 -0
  155. package/packages/cli/templates/guides/user-story-guide.md +256 -0
  156. package/packages/cli/templates/guides/zombie-process-cleanup.md +219 -0
  157. package/packages/cli/templates/hooks/agents-md-check.sh +27 -0
  158. package/packages/cli/templates/hooks/post-tool.sh +4 -0
  159. package/packages/cli/templates/hooks/pre-commit.sh +10 -0
  160. package/packages/cli/templates/prompts/arch-review.md +43 -0
  161. package/packages/cli/templates/prompts/quality-review.md +10 -0
  162. package/packages/cli/templates/skills/safeword-quality-reviewer/SKILL.md +207 -0
  163. package/packages/cli/tests/commands/check.test.ts +129 -0
  164. package/packages/cli/tests/commands/cli.test.ts +89 -0
  165. package/packages/cli/tests/commands/diff.test.ts +115 -0
  166. package/packages/cli/tests/commands/reset.test.ts +310 -0
  167. package/packages/cli/tests/commands/self-healing.test.ts +170 -0
  168. package/packages/cli/tests/commands/setup-blocking.test.ts +71 -0
  169. package/packages/cli/tests/commands/setup-core.test.ts +135 -0
  170. package/packages/cli/tests/commands/setup-git.test.ts +139 -0
  171. package/packages/cli/tests/commands/setup-hooks.test.ts +334 -0
  172. package/packages/cli/tests/commands/setup-linting.test.ts +189 -0
  173. package/packages/cli/tests/commands/setup-noninteractive.test.ts +80 -0
  174. package/packages/cli/tests/commands/setup-templates.test.ts +181 -0
  175. package/packages/cli/tests/commands/upgrade.test.ts +215 -0
  176. package/packages/cli/tests/helpers.ts +243 -0
  177. package/packages/cli/tests/npm-package.test.ts +83 -0
  178. package/packages/cli/tests/technical-constraints.test.ts +96 -0
  179. package/packages/cli/tsconfig.json +25 -0
  180. package/packages/cli/tsup.config.ts +11 -0
  181. package/packages/cli/vitest.config.ts +23 -0
  182. package/promptfoo.yaml +3270 -0
  183. package/dist/check-3NGQ4NR5.js +0 -129
  184. package/dist/check-3NGQ4NR5.js.map +0 -1
  185. package/dist/chunk-2XWIUEQK.js +0 -190
  186. package/dist/chunk-2XWIUEQK.js.map +0 -1
  187. package/dist/chunk-GZRQL3SX.js +0 -146
  188. package/dist/chunk-GZRQL3SX.js.map +0 -1
  189. package/dist/chunk-ORQHKDT2.js +0 -10
  190. package/dist/chunk-ORQHKDT2.js.map +0 -1
  191. package/dist/chunk-W66Z3C5H.js +0 -21
  192. package/dist/chunk-W66Z3C5H.js.map +0 -1
  193. package/dist/cli.d.ts +0 -1
  194. package/dist/cli.js +0 -34
  195. package/dist/cli.js.map +0 -1
  196. package/dist/diff-Y6QTAW4O.js +0 -166
  197. package/dist/diff-Y6QTAW4O.js.map +0 -1
  198. package/dist/index.d.ts +0 -11
  199. package/dist/index.js +0 -7
  200. package/dist/index.js.map +0 -1
  201. package/dist/reset-3ACTIYYE.js +0 -143
  202. package/dist/reset-3ACTIYYE.js.map +0 -1
  203. package/dist/setup-RR4M334C.js +0 -266
  204. package/dist/setup-RR4M334C.js.map +0 -1
  205. package/dist/upgrade-6AR3DHUV.js +0 -134
  206. package/dist/upgrade-6AR3DHUV.js.map +0 -1
  207. /package/{templates → framework}/SAFEWORD.md +0 -0
  208. /package/{templates → framework}/guides/architecture-guide.md +0 -0
  209. /package/{templates → framework}/guides/code-philosophy.md +0 -0
  210. /package/{templates → framework}/guides/context-files-guide.md +0 -0
  211. /package/{templates → framework}/guides/data-architecture-guide.md +0 -0
  212. /package/{templates → framework}/guides/design-doc-guide.md +0 -0
  213. /package/{templates → framework}/guides/learning-extraction.md +0 -0
  214. /package/{templates → framework}/guides/llm-instruction-design.md +0 -0
  215. /package/{templates → framework}/guides/llm-prompting.md +0 -0
  216. /package/{templates → framework}/guides/tdd-best-practices.md +0 -0
  217. /package/{templates → framework}/guides/test-definitions-guide.md +0 -0
  218. /package/{templates → framework}/guides/testing-methodology.md +0 -0
  219. /package/{templates → framework}/guides/user-story-guide.md +0 -0
  220. /package/{templates → framework}/guides/zombie-process-cleanup.md +0 -0
  221. /package/{templates → framework}/prompts/arch-review.md +0 -0
  222. /package/{templates → framework}/prompts/quality-review.md +0 -0
  223. /package/{templates/skills/safeword-quality-reviewer → framework/skills/quality-reviewer}/SKILL.md +0 -0
  224. /package/{templates/doc-templates → framework/templates}/architecture-template.md +0 -0
  225. /package/{templates/doc-templates → framework/templates}/design-doc-template.md +0 -0
  226. /package/{templates/doc-templates → framework/templates}/test-definitions-feature.md +0 -0
  227. /package/{templates/doc-templates → framework/templates}/ticket-template.md +0 -0
  228. /package/{templates/doc-templates → framework/templates}/user-stories-template.md +0 -0
  229. /package/{templates → packages/cli/templates}/commands/arch-review.md +0 -0
  230. /package/{templates → packages/cli/templates}/commands/lint.md +0 -0
  231. /package/{templates → packages/cli/templates}/commands/quality-review.md +0 -0
  232. /package/{templates → packages/cli/templates}/hooks/inject-timestamp.sh +0 -0
  233. /package/{templates → packages/cli/templates}/lib/common.sh +0 -0
  234. /package/{templates → packages/cli/templates}/lib/jq-fallback.sh +0 -0
  235. /package/{templates → packages/cli/templates}/markdownlint.jsonc +0 -0
@@ -0,0 +1,343 @@
1
+ # Design: Safeword CLI
2
+
3
+ **Guide**: `@./.safeword/guides/design-doc-guide.md` - Principles, structure guidelines, and avoiding bloat
4
+ **Template**: `@./.safeword/templates/design-doc-template.md`
5
+
6
+ **Related**: User Stories: `.safeword/planning/user-stories/005-cli-implementation.md` | Test Definitions: `.safeword/planning/test-definitions/005-cli-implementation.md`
7
+
8
+ **TDD Note**: This design implements tests from Test Definitions. Reference specific test scenarios (e.g., "Test 3.1: Registers hooks in settings.json").
9
+
10
+ ## Architecture
11
+
12
+ The CLI is a TypeScript Node.js application structured around command handlers. Each command (setup, check, upgrade, diff, reset) is an independent module that shares utilities for file operations, prompting, and output formatting.
13
+
14
+ The core principle is **idempotent operations with explicit state**: the CLI reads project state from `.safeword/version` and `.claude/settings.json`, performs operations, and writes state back. No global state or caching between runs.
15
+
16
+ **Diagram**:
17
+ ```
18
+ ┌─────────────────────────────────────────────────────────┐
19
+ │ CLI Entry │
20
+ │ (parse args, route to command) │
21
+ └─────────────────────────────────────────────────────────┘
22
+
23
+ ┌─────────────────┼─────────────────┐
24
+ ▼ ▼ ▼
25
+ ┌─────────┐ ┌──────────┐ ┌─────────┐
26
+ │ setup │ │ check │ │ reset │
27
+ │ upgrade │ │ diff │ │ │
28
+ └────┬────┘ └────┬─────┘ └────┬────┘
29
+ │ │ │
30
+ └────────────────┼─────────────────┘
31
+
32
+ ┌─────────────────────┐
33
+ │ Utilities │
34
+ │ ─────────────────── │
35
+ │ • FileManager │
36
+ │ • HookManager │
37
+ │ • Prompter │
38
+ │ • ProjectDetector │
39
+ │ • OutputFormatter │
40
+ └─────────────────────┘
41
+ ```
42
+
43
+ ## Components
44
+
45
+ ### Component 1: CLI Entry (`src/cli.ts`)
46
+
47
+ **What**: Parses arguments, routes to command handlers, handles global flags
48
+ **Where**: `packages/cli/src/cli.ts`
49
+ **Interface**:
50
+ ```typescript
51
+ // Entry point
52
+ async function main(args: string[]): Promise<void>;
53
+
54
+ // Parsed options available to all commands
55
+ interface GlobalOptions {
56
+ version: boolean;
57
+ help: boolean;
58
+ yes: boolean; // --yes flag
59
+ verbose: boolean; // --verbose flag
60
+ offline: boolean; // --offline flag
61
+ }
62
+ ```
63
+
64
+ **Dependencies**: Commander.js (arg parsing), all command modules
65
+ **Tests**: Test 1.1-1.3 (version, help, bare command)
66
+
67
+ ### Component 2: Setup Command (`src/commands/setup.ts`)
68
+
69
+ **What**: Orchestrates full project setup - files, hooks, skills, linting, AGENTS.md
70
+ **Where**: `packages/cli/src/commands/setup.ts`
71
+ **Interface**:
72
+ ```typescript
73
+ interface SetupOptions {
74
+ yes: boolean; // Skip prompts
75
+ }
76
+
77
+ async function setup(options: SetupOptions): Promise<void>;
78
+
79
+ // Throws SetupError on failure (exit 1)
80
+ // Returns normally on success (exit 0)
81
+ ```
82
+
83
+ **Dependencies**: FileManager, HookManager, Prompter, ProjectDetector, LintingSetup
84
+ **Tests**: Test 2.1-2.5, 3.1-3.5, 4.4-4.8, 5.1-5.2, 6.1-6.3, 7.1-7.5
85
+
86
+ ### Component 2b: Other Commands (check, upgrade, diff, reset)
87
+
88
+ | Command | File | What | Dependencies | Tests |
89
+ |---------|------|------|--------------|-------|
90
+ | check | `commands/check.ts` | Show versions, verify structure, check for updates | FileManager, npm registry fetch | 8.1-8.7 |
91
+ | upgrade | `commands/upgrade.ts` | Overwrite .safeword/, update hooks/skills | FileManager, HookManager | 9.1-9.7 |
92
+ | diff | `commands/diff.ts` | Compare project vs bundled templates | FileManager | 10.1-10.5 |
93
+ | reset | `commands/reset.ts` | Remove .safeword/, hooks, skills, AGENTS.md link | FileManager, HookManager, Prompter | 11.1-11.10 |
94
+
95
+ All commands share the same pattern: parse options → check project state → perform operation → output result.
96
+
97
+ ### Component 3: FileManager (`src/utils/file-manager.ts`)
98
+
99
+ **What**: Handles all file system operations - copy, write, read, delete with atomic operations
100
+ **Where**: `packages/cli/src/utils/file-manager.ts`
101
+ **Interface**:
102
+ ```typescript
103
+ interface FileManager {
104
+ // Template operations
105
+ copyTemplates(dest: string): Promise<string[]>;
106
+
107
+ // Version file
108
+ readVersion(projectRoot: string): Promise<string | null>;
109
+ writeVersion(projectRoot: string, version: string): Promise<void>;
110
+
111
+ // AGENTS.md operations
112
+ prependAgentsLink(projectRoot: string): Promise<void>;
113
+ removeAgentsLink(projectRoot: string): Promise<void>;
114
+ hasAgentsLink(projectRoot: string): Promise<boolean>;
115
+
116
+ // Diff operations
117
+ diffTemplates(projectRoot: string): Promise<DiffResult>;
118
+ }
119
+
120
+ interface DiffResult {
121
+ added: string[];
122
+ modified: string[];
123
+ unchanged: string[];
124
+ removed: string[];
125
+ }
126
+ ```
127
+
128
+ **Dependencies**: Node fs/promises, path
129
+ **Tests**: Test 2.1-2.4, 9.1, 10.1-10.4, 11.4, 11.8
130
+
131
+ ### Component 4: HookManager (`src/utils/hook-manager.ts`)
132
+
133
+ **What**: Manages Claude Code hooks in settings.json and git hooks in .git/hooks/
134
+ **Where**: `packages/cli/src/utils/hook-manager.ts`
135
+ **Interface**:
136
+ ```typescript
137
+ interface HookManager {
138
+ // Claude hooks
139
+ registerClaudeHooks(projectRoot: string): Promise<void>;
140
+ removeClaudeHooks(projectRoot: string): Promise<void>;
141
+ getClaudeHooks(projectRoot: string): Promise<ClaudeSettings>;
142
+
143
+ // Git hooks
144
+ installGitHooks(projectRoot: string): Promise<void>;
145
+ removeGitHooks(projectRoot: string): Promise<void>;
146
+
147
+ // Skills
148
+ copySkills(projectRoot: string): Promise<void>;
149
+ removeSkills(projectRoot: string): Promise<void>;
150
+ }
151
+
152
+ // Marker constants for git hooks
153
+ const GIT_HOOK_START = '# SAFEWORD_ARCH_CHECK_START';
154
+ const GIT_HOOK_END = '# SAFEWORD_ARCH_CHECK_END';
155
+ ```
156
+
157
+ **Dependencies**: FileManager (for file ops)
158
+ **Tests**: Test 3.1-3.5, 7.4-7.5, 11.5-11.7
159
+
160
+ ### Component 5: Prompter (`src/utils/prompter.ts`)
161
+
162
+ **What**: Handles interactive prompts with TTY detection and --yes override
163
+ **Where**: `packages/cli/src/utils/prompter.ts`
164
+ **Interface**:
165
+ ```typescript
166
+ interface Prompter {
167
+ // Check if running interactively
168
+ isInteractive(): boolean;
169
+
170
+ // Prompt with automatic default in non-interactive mode
171
+ confirm(message: string, defaultValue: boolean): Promise<boolean>;
172
+ }
173
+
174
+ // Factory to inject --yes flag
175
+ function createPrompter(options: { yes: boolean }): Prompter;
176
+ ```
177
+
178
+ **Dependencies**: Node readline, process.stdin.isTTY
179
+ **Tests**: Test 6.1-6.3, 7.1-7.3, 11.1-11.3
180
+
181
+ ### Component 6: ProjectDetector (`src/utils/project-detector.ts`)
182
+
183
+ **What**: Detects project type from package.json for linting configuration
184
+ **Where**: `packages/cli/src/utils/project-detector.ts`
185
+ **Interface**:
186
+ ```typescript
187
+ interface ProjectType {
188
+ typescript: boolean;
189
+ react: boolean;
190
+ nextjs: boolean;
191
+ astro: boolean;
192
+ node: boolean;
193
+ }
194
+
195
+ function detectProjectType(packageJson: PackageJson): ProjectType;
196
+ ```
197
+
198
+ **Dependencies**: None (pure function)
199
+ **Tests**: Test 4.1-4.3
200
+
201
+ ### Component 7: LintingSetup (`src/utils/linting-setup.ts`)
202
+
203
+ **What**: Installs and configures ESLint + Prettier based on detected project type
204
+ **Where**: `packages/cli/src/utils/linting-setup.ts`
205
+ **Interface**:
206
+ ```typescript
207
+ interface LintingSetup {
208
+ // Full setup - install deps, create configs, add scripts
209
+ configure(projectRoot: string, projectType: ProjectType): Promise<void>;
210
+
211
+ // Individual operations
212
+ installDependencies(projectRoot: string, projectType: ProjectType): Promise<void>;
213
+ createEslintConfig(projectRoot: string, projectType: ProjectType): Promise<void>;
214
+ createPrettierConfig(projectRoot: string): Promise<void>;
215
+ addPackageScripts(projectRoot: string): Promise<void>;
216
+ }
217
+
218
+ // Throws LintingError on failure (exit 1 - core failure)
219
+ ```
220
+
221
+ **Dependencies**: ProjectDetector, child_process (for npm/pnpm install), FileManager
222
+ **Tests**: Test 4.4-4.8
223
+
224
+ ## Data Model
225
+
226
+ ```typescript
227
+ // Project state (read from .safeword/version)
228
+ interface ProjectState {
229
+ configured: boolean;
230
+ version: string | null; // null if unconfigured
231
+ }
232
+
233
+ // Claude settings structure
234
+ interface ClaudeSettings {
235
+ hooks?: {
236
+ SessionStart?: HookConfig[];
237
+ PostToolUse?: HookConfig[];
238
+ Stop?: HookConfig[];
239
+ // ... other hook types
240
+ };
241
+ }
242
+
243
+ interface HookConfig {
244
+ matcher?: string;
245
+ hooks: Array<{
246
+ type: 'command';
247
+ command: string;
248
+ timeout?: number;
249
+ }>;
250
+ }
251
+ ```
252
+
253
+ ## Component Interaction
254
+
255
+ **Setup Flow:**
256
+ ```
257
+ CLI Entry → Setup Command
258
+ → FileManager.copyTemplates()
259
+ → HookManager.registerClaudeHooks()
260
+ → HookManager.copySkills()
261
+ → LintingSetup.configure()
262
+ → Prompter.confirm() [if no git]
263
+ → HookManager.installGitHooks() [if git]
264
+ → FileManager.prependAgentsLink()
265
+ → FileManager.writeVersion()
266
+ ```
267
+
268
+ **Reset Flow:**
269
+ ```
270
+ CLI Entry → Reset Command
271
+ → Prompter.confirm()
272
+ → FileManager.remove('.safeword/')
273
+ → HookManager.removeClaudeHooks()
274
+ → HookManager.removeSkills()
275
+ → HookManager.removeGitHooks()
276
+ → FileManager.removeAgentsLink()
277
+ ```
278
+
279
+ ## User Flow
280
+
281
+ 1. User runs `npx safeword setup` in project directory
282
+ 2. CLI checks for existing `.safeword/` → errors if found
283
+ 3. CLI detects project type from package.json
284
+ 4. CLI copies templates to `.safeword/`
285
+ 5. CLI registers hooks in `.claude/settings.json`
286
+ 6. CLI installs ESLint + Prettier, creates configs
287
+ 7. CLI checks for `.git/` → prompts if missing (skips with --yes)
288
+ 8. CLI prepends link to `AGENTS.md`
289
+ 9. CLI prints success summary with file counts
290
+
291
+ ## Key Decisions
292
+
293
+ ### Decision 1: Commander.js for argument parsing
294
+
295
+ **What**: Use Commander.js instead of manual argv parsing or alternatives (yargs, meow)
296
+ **Why**: Most popular (40k+ GitHub stars), excellent TypeScript support, subcommand pattern matches our design, minimal bundle size impact
297
+ **Trade-off**: External dependency vs zero-dep (but arg parsing is complex enough to warrant it)
298
+
299
+ ### Decision 2: Marker-based git hooks
300
+
301
+ **What**: Use comment markers (`SAFEWORD_ARCH_CHECK_START/END`) for git hook content
302
+ **Why**: Allows coexistence with other tools (husky, lint-staged) that also modify pre-commit hooks
303
+ **Trade-off**: Slightly more complex removal logic, but essential for ecosystem compatibility
304
+
305
+ ### Decision 3: Bundled templates
306
+
307
+ **What**: Ship templates as part of npm package, copy on setup (not fetch from GitHub)
308
+ **Why**: Works offline, faster setup, version-locked to CLI, no network dependency
309
+ **Trade-off**: Larger package size (~500KB), but acceptable for CLI tool
310
+
311
+ ### Decision 4: No config file
312
+
313
+ **What**: No `.safewordrc` or similar - all behavior via flags
314
+ **Why**: Simpler mental model, npx-first means config rarely persists anyway, flags are explicit
315
+ **Trade-off**: Can't persist preferences, but `--yes` covers the main use case (CI)
316
+
317
+ ## Implementation Notes
318
+
319
+ **Constraints**:
320
+ - Node 18+ required (use engines field in package.json)
321
+ - Must work with npm, pnpm, yarn, bun for linting deps install
322
+ - Max 500ms startup time (lazy-load heavy modules)
323
+
324
+ **Error Handling**:
325
+ - Core failures (can't write files, linting fails) → exit 1 with clear message
326
+ - Warnings (no git, offline) → exit 0 with warning in output
327
+ - Use custom error classes: `SetupError`, `ConfigError`, `NetworkError`
328
+
329
+ **Gotchas**:
330
+ - Always check for existing `.safeword/` before any writes in setup
331
+ - AGENTS.md link must be exact string match for removal
332
+ - Git hooks must preserve existing content outside markers
333
+ - settings.json might not exist yet - create if missing
334
+
335
+ **Open Questions**:
336
+ - [ ] Which npm registry endpoint for version check? (registry.npmjs.org/safeword/latest)
337
+ - [ ] Should we support Bun's package manager for linting install?
338
+
339
+ ## References
340
+
341
+ - [CLI UX Vision](../../.agents/planning/011-cli-ux-vision.md)
342
+ - [Ticket #005](../../.agents/tickets/005-cli-implementation.md)
343
+ - [Commander.js docs](https://github.com/tj/commander.js)