safeword 0.2.4 → 0.2.5

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/dist/check-3NGQ4NR5.js +129 -0
  2. package/dist/check-3NGQ4NR5.js.map +1 -0
  3. package/dist/chunk-2XWIUEQK.js +190 -0
  4. package/dist/chunk-2XWIUEQK.js.map +1 -0
  5. package/dist/chunk-GZRQL3SX.js +146 -0
  6. package/dist/chunk-GZRQL3SX.js.map +1 -0
  7. package/dist/chunk-ORQHKDT2.js +10 -0
  8. package/dist/chunk-ORQHKDT2.js.map +1 -0
  9. package/dist/chunk-W66Z3C5H.js +21 -0
  10. package/dist/chunk-W66Z3C5H.js.map +1 -0
  11. package/dist/cli.d.ts +1 -0
  12. package/dist/cli.js +34 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/diff-Y6QTAW4O.js +166 -0
  15. package/dist/diff-Y6QTAW4O.js.map +1 -0
  16. package/dist/index.d.ts +11 -0
  17. package/dist/index.js +7 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/reset-3ACTIYYE.js +143 -0
  20. package/dist/reset-3ACTIYYE.js.map +1 -0
  21. package/dist/setup-RR4M334C.js +266 -0
  22. package/dist/setup-RR4M334C.js.map +1 -0
  23. package/dist/upgrade-6AR3DHUV.js +134 -0
  24. package/dist/upgrade-6AR3DHUV.js.map +1 -0
  25. package/package.json +44 -19
  26. package/{.safeword → templates}/hooks/agents-md-check.sh +0 -0
  27. package/{.safeword → templates}/hooks/post-tool.sh +0 -0
  28. package/{.safeword → templates}/hooks/pre-commit.sh +0 -0
  29. package/.claude/commands/arch-review.md +0 -32
  30. package/.claude/commands/lint.md +0 -6
  31. package/.claude/commands/quality-review.md +0 -13
  32. package/.claude/commands/setup-linting.md +0 -6
  33. package/.claude/hooks/auto-lint.sh +0 -6
  34. package/.claude/hooks/auto-quality-review.sh +0 -170
  35. package/.claude/hooks/check-linting-sync.sh +0 -17
  36. package/.claude/hooks/inject-timestamp.sh +0 -6
  37. package/.claude/hooks/question-protocol.sh +0 -12
  38. package/.claude/hooks/run-linters.sh +0 -8
  39. package/.claude/hooks/run-quality-review.sh +0 -76
  40. package/.claude/hooks/version-check.sh +0 -10
  41. package/.claude/mcp/README.md +0 -96
  42. package/.claude/mcp/arcade.sample.json +0 -9
  43. package/.claude/mcp/context7.sample.json +0 -7
  44. package/.claude/mcp/playwright.sample.json +0 -7
  45. package/.claude/settings.json +0 -62
  46. package/.claude/skills/quality-reviewer/SKILL.md +0 -190
  47. package/.claude/skills/safeword-quality-reviewer/SKILL.md +0 -13
  48. package/.env.arcade.example +0 -4
  49. package/.env.example +0 -11
  50. package/.gitmodules +0 -4
  51. package/.safeword/SAFEWORD.md +0 -33
  52. package/.safeword/eslint/eslint-base.mjs +0 -101
  53. package/.safeword/guides/architecture-guide.md +0 -404
  54. package/.safeword/guides/code-philosophy.md +0 -174
  55. package/.safeword/guides/context-files-guide.md +0 -405
  56. package/.safeword/guides/data-architecture-guide.md +0 -183
  57. package/.safeword/guides/design-doc-guide.md +0 -165
  58. package/.safeword/guides/learning-extraction.md +0 -515
  59. package/.safeword/guides/llm-instruction-design.md +0 -239
  60. package/.safeword/guides/llm-prompting.md +0 -95
  61. package/.safeword/guides/tdd-best-practices.md +0 -570
  62. package/.safeword/guides/test-definitions-guide.md +0 -243
  63. package/.safeword/guides/testing-methodology.md +0 -573
  64. package/.safeword/guides/user-story-guide.md +0 -237
  65. package/.safeword/guides/zombie-process-cleanup.md +0 -214
  66. package/.safeword/planning/002-user-story-quality-evaluation.md +0 -1840
  67. package/.safeword/planning/003-langsmith-eval-setup-prompt.md +0 -363
  68. package/.safeword/planning/004-llm-eval-test-cases.md +0 -3226
  69. package/.safeword/planning/005-architecture-enforcement-system.md +0 -169
  70. package/.safeword/planning/006-reactive-fix-prevention-research.md +0 -135
  71. package/.safeword/planning/011-cli-ux-vision.md +0 -330
  72. package/.safeword/planning/012-project-structure-cleanup.md +0 -154
  73. package/.safeword/planning/README.md +0 -39
  74. package/.safeword/planning/automation-plan-v2.md +0 -1225
  75. package/.safeword/planning/automation-plan-v3.md +0 -1291
  76. package/.safeword/planning/automation-plan.md +0 -3058
  77. package/.safeword/planning/design/005-cli-implementation.md +0 -343
  78. package/.safeword/planning/design/013-cli-self-contained-templates.md +0 -596
  79. package/.safeword/planning/design/013a-eslint-plugin-suite.md +0 -256
  80. package/.safeword/planning/design/013b-implementation-snippets.md +0 -385
  81. package/.safeword/planning/design/013c-config-isolation-strategy.md +0 -242
  82. package/.safeword/planning/design/code-philosophy-improvements.md +0 -60
  83. package/.safeword/planning/mcp-analysis.md +0 -545
  84. package/.safeword/planning/phase2-subagents-vs-skills-analysis.md +0 -451
  85. package/.safeword/planning/settings-improvements.md +0 -970
  86. package/.safeword/planning/test-definitions/005-cli-implementation.md +0 -1301
  87. package/.safeword/planning/test-definitions/cli-self-contained-templates.md +0 -205
  88. package/.safeword/planning/user-stories/001-guides-review-user-stories.md +0 -1381
  89. package/.safeword/planning/user-stories/003-reactive-fix-prevention.md +0 -132
  90. package/.safeword/planning/user-stories/004-technical-constraints.md +0 -86
  91. package/.safeword/planning/user-stories/005-cli-implementation.md +0 -311
  92. package/.safeword/planning/user-stories/cli-self-contained-templates.md +0 -172
  93. package/.safeword/planning/versioned-distribution.md +0 -740
  94. package/.safeword/prompts/arch-review.md +0 -43
  95. package/.safeword/prompts/quality-review.md +0 -11
  96. package/.safeword/scripts/arch-review.sh +0 -235
  97. package/.safeword/scripts/check-linting-sync.sh +0 -58
  98. package/.safeword/scripts/setup-linting.sh +0 -559
  99. package/.safeword/templates/architecture-template.md +0 -136
  100. package/.safeword/templates/ci/architecture-check.yml +0 -79
  101. package/.safeword/templates/design-doc-template.md +0 -127
  102. package/.safeword/templates/test-definitions-feature.md +0 -100
  103. package/.safeword/templates/ticket-template.md +0 -74
  104. package/.safeword/templates/user-stories-template.md +0 -82
  105. package/.safeword/tickets/001-guides-review-user-stories.md +0 -83
  106. package/.safeword/tickets/002-architecture-enforcement.md +0 -211
  107. package/.safeword/tickets/003-reactive-fix-prevention.md +0 -57
  108. package/.safeword/tickets/004-technical-constraints-in-user-stories.md +0 -39
  109. package/.safeword/tickets/005-cli-implementation.md +0 -248
  110. package/.safeword/tickets/006-flesh-out-skills.md +0 -43
  111. package/.safeword/tickets/007-flesh-out-questioning.md +0 -44
  112. package/.safeword/tickets/008-upgrade-questioning.md +0 -58
  113. package/.safeword/tickets/009-naming-conventions.md +0 -41
  114. package/.safeword/tickets/010-safeword-md-cleanup.md +0 -34
  115. package/.safeword/tickets/011-cursor-setup.md +0 -86
  116. package/.safeword/tickets/README.md +0 -73
  117. package/.safeword/version +0 -1
  118. package/AGENTS.md +0 -59
  119. package/CLAUDE.md +0 -12
  120. package/README.md +0 -347
  121. package/docs/001-cli-implementation-plan.md +0 -856
  122. package/docs/elite-dx-implementation-plan.md +0 -1034
  123. package/framework/README.md +0 -131
  124. package/framework/mcp/README.md +0 -96
  125. package/framework/mcp/arcade.sample.json +0 -8
  126. package/framework/mcp/context7.sample.json +0 -6
  127. package/framework/mcp/playwright.sample.json +0 -6
  128. package/framework/scripts/arch-review.sh +0 -235
  129. package/framework/scripts/check-linting-sync.sh +0 -58
  130. package/framework/scripts/load-env.sh +0 -49
  131. package/framework/scripts/setup-claude.sh +0 -223
  132. package/framework/scripts/setup-linting.sh +0 -559
  133. package/framework/scripts/setup-quality.sh +0 -477
  134. package/framework/scripts/setup-safeword.sh +0 -550
  135. package/framework/templates/ci/architecture-check.yml +0 -78
  136. package/learnings/ai-sdk-v5-breaking-changes.md +0 -178
  137. package/learnings/e2e-test-zombie-processes.md +0 -231
  138. package/learnings/milkdown-crepe-editor-property.md +0 -96
  139. package/learnings/prosemirror-fragment-traversal.md +0 -119
  140. package/packages/cli/AGENTS.md +0 -1
  141. package/packages/cli/ARCHITECTURE.md +0 -279
  142. package/packages/cli/package.json +0 -51
  143. package/packages/cli/src/cli.ts +0 -63
  144. package/packages/cli/src/commands/check.ts +0 -166
  145. package/packages/cli/src/commands/diff.ts +0 -209
  146. package/packages/cli/src/commands/reset.ts +0 -190
  147. package/packages/cli/src/commands/setup.ts +0 -325
  148. package/packages/cli/src/commands/upgrade.ts +0 -163
  149. package/packages/cli/src/index.ts +0 -3
  150. package/packages/cli/src/templates/config.ts +0 -58
  151. package/packages/cli/src/templates/content.ts +0 -18
  152. package/packages/cli/src/templates/index.ts +0 -12
  153. package/packages/cli/src/utils/agents-md.ts +0 -66
  154. package/packages/cli/src/utils/fs.ts +0 -179
  155. package/packages/cli/src/utils/git.ts +0 -124
  156. package/packages/cli/src/utils/hooks.ts +0 -29
  157. package/packages/cli/src/utils/output.ts +0 -60
  158. package/packages/cli/src/utils/project-detector.test.ts +0 -185
  159. package/packages/cli/src/utils/project-detector.ts +0 -44
  160. package/packages/cli/src/utils/version.ts +0 -28
  161. package/packages/cli/src/version.ts +0 -6
  162. package/packages/cli/templates/SAFEWORD.md +0 -776
  163. package/packages/cli/templates/doc-templates/architecture-template.md +0 -136
  164. package/packages/cli/templates/doc-templates/design-doc-template.md +0 -134
  165. package/packages/cli/templates/doc-templates/test-definitions-feature.md +0 -131
  166. package/packages/cli/templates/doc-templates/ticket-template.md +0 -82
  167. package/packages/cli/templates/doc-templates/user-stories-template.md +0 -92
  168. package/packages/cli/templates/guides/architecture-guide.md +0 -423
  169. package/packages/cli/templates/guides/code-philosophy.md +0 -195
  170. package/packages/cli/templates/guides/context-files-guide.md +0 -457
  171. package/packages/cli/templates/guides/data-architecture-guide.md +0 -200
  172. package/packages/cli/templates/guides/design-doc-guide.md +0 -171
  173. package/packages/cli/templates/guides/learning-extraction.md +0 -552
  174. package/packages/cli/templates/guides/llm-instruction-design.md +0 -248
  175. package/packages/cli/templates/guides/llm-prompting.md +0 -102
  176. package/packages/cli/templates/guides/tdd-best-practices.md +0 -615
  177. package/packages/cli/templates/guides/test-definitions-guide.md +0 -334
  178. package/packages/cli/templates/guides/testing-methodology.md +0 -618
  179. package/packages/cli/templates/guides/user-story-guide.md +0 -256
  180. package/packages/cli/templates/guides/zombie-process-cleanup.md +0 -219
  181. package/packages/cli/templates/hooks/agents-md-check.sh +0 -27
  182. package/packages/cli/templates/hooks/post-tool.sh +0 -4
  183. package/packages/cli/templates/hooks/pre-commit.sh +0 -10
  184. package/packages/cli/templates/prompts/arch-review.md +0 -43
  185. package/packages/cli/templates/prompts/quality-review.md +0 -10
  186. package/packages/cli/templates/skills/safeword-quality-reviewer/SKILL.md +0 -207
  187. package/packages/cli/tests/commands/check.test.ts +0 -129
  188. package/packages/cli/tests/commands/cli.test.ts +0 -89
  189. package/packages/cli/tests/commands/diff.test.ts +0 -115
  190. package/packages/cli/tests/commands/reset.test.ts +0 -310
  191. package/packages/cli/tests/commands/self-healing.test.ts +0 -170
  192. package/packages/cli/tests/commands/setup-blocking.test.ts +0 -71
  193. package/packages/cli/tests/commands/setup-core.test.ts +0 -135
  194. package/packages/cli/tests/commands/setup-git.test.ts +0 -139
  195. package/packages/cli/tests/commands/setup-hooks.test.ts +0 -334
  196. package/packages/cli/tests/commands/setup-linting.test.ts +0 -189
  197. package/packages/cli/tests/commands/setup-noninteractive.test.ts +0 -80
  198. package/packages/cli/tests/commands/setup-templates.test.ts +0 -181
  199. package/packages/cli/tests/commands/upgrade.test.ts +0 -215
  200. package/packages/cli/tests/helpers.ts +0 -243
  201. package/packages/cli/tests/npm-package.test.ts +0 -83
  202. package/packages/cli/tests/technical-constraints.test.ts +0 -96
  203. package/packages/cli/tsconfig.json +0 -25
  204. package/packages/cli/tsup.config.ts +0 -11
  205. package/packages/cli/vitest.config.ts +0 -23
  206. package/promptfoo.yaml +0 -3270
  207. /package/{framework → templates}/SAFEWORD.md +0 -0
  208. /package/{packages/cli/templates → templates}/commands/arch-review.md +0 -0
  209. /package/{packages/cli/templates → templates}/commands/lint.md +0 -0
  210. /package/{packages/cli/templates → templates}/commands/quality-review.md +0 -0
  211. /package/{framework/templates → templates/doc-templates}/architecture-template.md +0 -0
  212. /package/{framework/templates → templates/doc-templates}/design-doc-template.md +0 -0
  213. /package/{framework/templates → templates/doc-templates}/test-definitions-feature.md +0 -0
  214. /package/{framework/templates → templates/doc-templates}/ticket-template.md +0 -0
  215. /package/{framework/templates → templates/doc-templates}/user-stories-template.md +0 -0
  216. /package/{framework → templates}/guides/architecture-guide.md +0 -0
  217. /package/{framework → templates}/guides/code-philosophy.md +0 -0
  218. /package/{framework → templates}/guides/context-files-guide.md +0 -0
  219. /package/{framework → templates}/guides/data-architecture-guide.md +0 -0
  220. /package/{framework → templates}/guides/design-doc-guide.md +0 -0
  221. /package/{framework → templates}/guides/learning-extraction.md +0 -0
  222. /package/{framework → templates}/guides/llm-instruction-design.md +0 -0
  223. /package/{framework → templates}/guides/llm-prompting.md +0 -0
  224. /package/{framework → templates}/guides/tdd-best-practices.md +0 -0
  225. /package/{framework → templates}/guides/test-definitions-guide.md +0 -0
  226. /package/{framework → templates}/guides/testing-methodology.md +0 -0
  227. /package/{framework → templates}/guides/user-story-guide.md +0 -0
  228. /package/{framework → templates}/guides/zombie-process-cleanup.md +0 -0
  229. /package/{packages/cli/templates → templates}/hooks/inject-timestamp.sh +0 -0
  230. /package/{packages/cli/templates → templates}/lib/common.sh +0 -0
  231. /package/{packages/cli/templates → templates}/lib/jq-fallback.sh +0 -0
  232. /package/{packages/cli/templates → templates}/markdownlint.jsonc +0 -0
  233. /package/{framework → templates}/prompts/arch-review.md +0 -0
  234. /package/{framework → templates}/prompts/quality-review.md +0 -0
  235. /package/{framework/skills/quality-reviewer → templates/skills/safeword-quality-reviewer}/SKILL.md +0 -0
@@ -1,279 +0,0 @@
1
- # Safeword CLI Architecture
2
-
3
- **Version:** 1.0
4
- **Last Updated:** 2025-11-27
5
- **Status:** Design
6
-
7
- ---
8
-
9
- ## Table of Contents
10
-
11
- - [Overview](#overview)
12
- - [Tech Stack](#tech-stack)
13
- - [Project Structure](#project-structure)
14
- - [Key Decisions](#key-decisions)
15
- - [Best Practices](#best-practices)
16
- - [Migration Strategy](#migration-strategy)
17
-
18
- ---
19
-
20
- ## Overview
21
-
22
- The Safeword CLI is a TypeScript Node.js application that replaces bash scripts for project setup, verification, and maintenance. It provides commands for setting up development environments with linting, Claude Code hooks, and configuration management.
23
-
24
- **Design Philosophy:**
25
-
26
- - **npx-first**: Always run via npx for latest version
27
- - **Stateless**: No global config, all state in project files
28
- - **Idempotent**: Safe to re-run commands (with appropriate guards)
29
- - **Non-interactive capable**: Full functionality via flags for CI/automation
30
-
31
- ---
32
-
33
- ## Tech Stack
34
-
35
- | Category | Choice | Rationale |
36
- | ----------- | ---------------------- | -------------------------------------------------- |
37
- | Language | TypeScript 5.x | Type safety, IDE support, matches target projects |
38
- | Runtime | Node.js 18+ | LTS, native fetch, stable fs/promises |
39
- | Arg parsing | Commander.js | Industry standard, TypeScript support, subcommands |
40
- | Build | tsup | Fast, zero-config, ESM + CJS output |
41
- | Testing | Vitest | Fast, TypeScript-native, compatible with Node |
42
- | Linting | ESLint 9 (flat config) | What we install for users, dogfood ourselves |
43
-
44
- ---
45
-
46
- ## Project Structure
47
-
48
- ```
49
- packages/cli/
50
- ├── src/
51
- │ ├── cli.ts # Entry point, arg parsing
52
- │ ├── commands/
53
- │ │ ├── setup.ts # Setup command
54
- │ │ ├── check.ts # Health check command
55
- │ │ ├── upgrade.ts # Upgrade command
56
- │ │ ├── diff.ts # Diff preview command
57
- │ │ └── reset.ts # Reset/uninstall command
58
- │ ├── utils/
59
- │ │ ├── file-manager.ts # File operations
60
- │ │ ├── hook-manager.ts # Claude + git hooks
61
- │ │ ├── prompter.ts # Interactive prompts
62
- │ │ ├── project-detector.ts # Project type detection
63
- │ │ ├── linting-setup.ts # ESLint/Prettier config
64
- │ │ └── output.ts # Colored output, spinners
65
- │ └── templates/ # Bundled templates (copied to .safeword/)
66
- ├── tests/
67
- │ ├── commands/ # Integration tests per command
68
- │ └── utils/ # Unit tests for utilities
69
- ├── ARCHITECTURE.md # This file
70
- ├── package.json
71
- └── tsconfig.json
72
- ```
73
-
74
- ---
75
-
76
- ## Key Decisions
77
-
78
- ### Decision 1: TypeScript over JavaScript
79
-
80
- **Status:** Active
81
- **Date:** 2025-11-27
82
-
83
- | Field | Value |
84
- | -------------- | ---------------------------------------------------------------------------------------------------------------------- |
85
- | What | Write CLI in TypeScript, compile to JavaScript for distribution |
86
- | Why | Type safety catches bugs early, better IDE support, self-documents interfaces. Target users are TypeScript developers. |
87
- | Trade-off | Build step required, but tsup makes this trivial |
88
- | Alternatives | Pure JS (rejected: lose type safety), Bun (rejected: not ubiquitous enough) |
89
- | Implementation | `packages/cli/src/**/*.ts` |
90
-
91
- ### Decision 2: ESM-only
92
-
93
- **Status:** Active
94
- **Date:** 2025-11-27
95
-
96
- | Field | Value |
97
- | -------------- | -------------------------------------------------------------------------- |
98
- | What | Package uses `"type": "module"`, tsup outputs ESM only |
99
- | Why | Node 18+ has full ESM support, CJS adds bloat for shrinking use case |
100
- | Trade-off | Won't work with very old tooling that requires CJS |
101
- | Alternatives | CJS-only (rejected: legacy), dual ESM+CJS (rejected: unnecessary bloat) |
102
- | Implementation | `tsup.config.ts`: `format: ['esm']` |
103
-
104
- ### Decision 3: Bundle templates in package
105
-
106
- **Status:** Active
107
- **Date:** 2025-11-27
108
-
109
- | Field | Value |
110
- | -------------- | ----------------------------------------------------------------------- |
111
- | What | Ship `.safeword/` templates as part of npm package, copy on setup |
112
- | Why | Works offline, version-locked to CLI, no network dependency for setup |
113
- | Trade-off | Larger package (~500KB), templates update requires CLI update |
114
- | Alternatives | Fetch from GitHub (rejected: network dependency, version mismatch risk) |
115
- | Implementation | `src/templates/` copied to dist, read at runtime |
116
-
117
- ### Decision 4: Commander.js for CLI framework
118
-
119
- **Status:** Active
120
- **Date:** 2025-11-27
121
-
122
- | Field | Value |
123
- | -------------- | --------------------------------------------------------------------------------------------------------- |
124
- | What | Use Commander.js for argument parsing, help generation, subcommands |
125
- | Why | Most popular (40k+ stars), excellent TypeScript support, minimal bundle impact |
126
- | Trade-off | External dependency, but arg parsing complexity justifies it |
127
- | Alternatives | yargs (rejected: heavier), meow (rejected: less TypeScript support), manual (rejected: reinventing wheel) |
128
- | Implementation | `src/cli.ts` |
129
-
130
- ### Decision 5: Vitest for testing
131
-
132
- **Status:** Active
133
- **Date:** 2025-11-27
134
-
135
- | Field | Value |
136
- | -------------- | ------------------------------------------------------------------------------- |
137
- | What | Use Vitest for unit and integration tests |
138
- | Why | Fast, TypeScript-native, watch mode, compatible with Node fs operations |
139
- | Trade-off | Another test runner to know (but API is Jest-compatible) |
140
- | Alternatives | Jest (rejected: slower, config heavy), Node test runner (rejected: less mature) |
141
- | Implementation | `tests/**/*.test.ts` |
142
-
143
- ### Decision 6: No runtime dependencies beyond Commander
144
-
145
- **Status:** Active
146
- **Date:** 2025-11-27
147
-
148
- | Field | Value |
149
- | -------------- | --------------------------------------------------------------------------------- |
150
- | What | Minimize runtime deps - only Commander.js, use Node built-ins for everything else |
151
- | Why | Faster install, fewer security audit concerns, smaller attack surface |
152
- | Trade-off | May need to implement utilities that libraries provide |
153
- | Alternatives | Use chalk, ora, inquirer, etc. (rejected: bloat for simple CLI) |
154
- | Implementation | Use Node readline for prompts, ANSI codes directly for colors |
155
-
156
- ---
157
-
158
- ## Best Practices
159
-
160
- ### Error Handling Pattern
161
-
162
- **What:** Use custom error classes with exit codes
163
- **Why:** Consistent error handling, testable exit behavior
164
- **Example:** See `src/utils/errors.ts`
165
-
166
- ```typescript
167
- // Define error types
168
- class SafewordError extends Error {
169
- constructor(
170
- message: string,
171
- public exitCode: number = 1,
172
- ) {
173
- super(message);
174
- }
175
- }
176
-
177
- class SetupError extends SafewordError {}
178
- class ConfigError extends SafewordError {}
179
-
180
- // Use in commands
181
- try {
182
- await setup(options);
183
- } catch (e) {
184
- if (e instanceof SafewordError) {
185
- console.error(e.message);
186
- process.exit(e.exitCode);
187
- }
188
- throw e; // Re-throw unexpected errors
189
- }
190
- ```
191
-
192
- ### File Operations Pattern
193
-
194
- **What:** Always use async fs operations, handle errors explicitly
195
- **Why:** Non-blocking, better error messages
196
- **Example:** See `src/utils/file-manager.ts`
197
-
198
- ```typescript
199
- import { readFile, writeFile, mkdir } from 'fs/promises';
200
-
201
- async function safeWrite(path: string, content: string): Promise<void> {
202
- await mkdir(dirname(path), { recursive: true });
203
- await writeFile(path, content, 'utf-8');
204
- }
205
- ```
206
-
207
- ### Output Pattern
208
-
209
- **What:** Use symbols for status, no emoji by default
210
- **Why:** Works in all terminals, professional appearance
211
- **Example:** See `src/utils/output.ts`
212
-
213
- ```typescript
214
- const symbols = {
215
- success: '✓',
216
- warning: '⚠',
217
- error: '✗',
218
- info: '→',
219
- };
220
-
221
- function success(msg: string) {
222
- console.log(`${symbols.success} ${msg}`);
223
- }
224
- ```
225
-
226
- ---
227
-
228
- ## Migration Strategy
229
-
230
- ### From Bash Scripts to CLI
231
-
232
- **Trigger:** User has existing bash-based safeword setup
233
- **Steps:**
234
-
235
- 1. User runs `npx safeword upgrade`
236
- 2. CLI detects `.safeword/` exists
237
- 3. CLI overwrites all files with bundled templates
238
- 4. CLI updates hooks in `.claude/settings.json`
239
- 5. CLI preserves user's AGENTS.md content (only updates link)
240
-
241
- **Rollback:** Run `npx safeword reset`, then re-run old bash scripts
242
-
243
- ### Future: v1 to v2
244
-
245
- **Trigger:** Breaking changes to template structure or hook format
246
- **Steps:**
247
-
248
- 1. v2 CLI detects v1 version in `.safeword/version`
249
- 2. Runs migration logic before normal upgrade
250
- 3. Updates version file to v2
251
-
252
- **Rollback:** Document breaking changes, provide migration guide
253
-
254
- ---
255
-
256
- ## Appendix
257
-
258
- ### References
259
-
260
- - [Design Doc](../../.safeword/planning/design/005-cli-implementation.md)
261
- - [User Stories](../../.safeword/planning/user-stories/005-cli-implementation.md)
262
- - [Test Definitions](../../.safeword/planning/test-definitions/005-cli-implementation.md)
263
- - [CLI UX Vision](../../.safeword/planning/011-cli-ux-vision.md)
264
-
265
- ### Package.json (key fields)
266
-
267
- ```json
268
- {
269
- "name": "safeword",
270
- "type": "module",
271
- "bin": {
272
- "safeword": "./dist/cli.js"
273
- },
274
- "engines": {
275
- "node": ">=18"
276
- },
277
- "files": ["dist", "templates"]
278
- }
279
- ```
@@ -1,51 +0,0 @@
1
- {
2
- "name": "safeword",
3
- "version": "0.2.3",
4
- "description": "CLI for setting up and managing safeword development environments",
5
- "type": "module",
6
- "bin": {
7
- "safeword": "./dist/cli.js"
8
- },
9
- "exports": {
10
- ".": {
11
- "import": "./dist/index.js",
12
- "types": "./dist/index.d.ts"
13
- }
14
- },
15
- "files": [
16
- "dist",
17
- "templates"
18
- ],
19
- "engines": {
20
- "node": ">=18"
21
- },
22
- "scripts": {
23
- "build": "tsup",
24
- "dev": "tsup --watch",
25
- "test": "vitest run",
26
- "test:watch": "vitest",
27
- "test:coverage": "vitest run --coverage",
28
- "typecheck": "tsc --noEmit",
29
- "lint": "eslint src tests",
30
- "clean": "rm -rf dist",
31
- "prepublishOnly": "npm audit --audit-level=high && npm run build && npm test"
32
- },
33
- "dependencies": {
34
- "commander": "^12.1.0"
35
- },
36
- "devDependencies": {
37
- "@types/node": "^20.10.0",
38
- "tsup": "^8.0.0",
39
- "typescript": "^5.3.0",
40
- "vitest": "^2.0.0"
41
- },
42
- "keywords": [
43
- "cli",
44
- "safeword",
45
- "developer-experience",
46
- "linting",
47
- "claude-code"
48
- ],
49
- "author": "",
50
- "license": "MIT"
51
- }
@@ -1,63 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { Command } from 'commander';
4
- import { VERSION } from './version.js';
5
-
6
- const program = new Command();
7
-
8
- program
9
- .name('safeword')
10
- .description('CLI for setting up and managing safeword development environments')
11
- .version(VERSION);
12
-
13
- program
14
- .command('setup')
15
- .description('Set up safeword in the current project')
16
- .option('-y, --yes', 'Accept all defaults (non-interactive mode)')
17
- .action(async options => {
18
- const { setup } = await import('./commands/setup.js');
19
- await setup(options);
20
- });
21
-
22
- program
23
- .command('check')
24
- .description('Check project health and versions')
25
- .option('--offline', 'Skip remote version check')
26
- .action(async options => {
27
- const { check } = await import('./commands/check.js');
28
- await check(options);
29
- });
30
-
31
- program
32
- .command('upgrade')
33
- .description('Upgrade safeword configuration to latest version')
34
- .action(async () => {
35
- const { upgrade } = await import('./commands/upgrade.js');
36
- await upgrade();
37
- });
38
-
39
- program
40
- .command('diff')
41
- .description('Preview changes that would be made by upgrade')
42
- .option('-v, --verbose', 'Show full diff output')
43
- .action(async options => {
44
- const { diff } = await import('./commands/diff.js');
45
- await diff(options);
46
- });
47
-
48
- program
49
- .command('reset')
50
- .description('Remove safeword configuration from project')
51
- .option('-y, --yes', 'Skip confirmation prompt')
52
- .action(async options => {
53
- const { reset } = await import('./commands/reset.js');
54
- await reset(options);
55
- });
56
-
57
- // Show help if no arguments provided
58
- if (process.argv.length === 2) {
59
- program.help();
60
- }
61
-
62
- // Parse arguments
63
- program.parse();
@@ -1,166 +0,0 @@
1
- /**
2
- * Check command - Verify project health and configuration
3
- */
4
-
5
- import { join } from 'node:path';
6
- import { VERSION } from '../version.js';
7
- import { exists, readFile, readFileSafe } from '../utils/fs.js';
8
- import { info, success, warn, header, keyValue } from '../utils/output.js';
9
- import { isNewerVersion } from '../utils/version.js';
10
-
11
- export interface CheckOptions {
12
- offline?: boolean;
13
- }
14
-
15
- interface HealthStatus {
16
- configured: boolean;
17
- projectVersion: string | null;
18
- cliVersion: string;
19
- updateAvailable: boolean;
20
- latestVersion: string | null;
21
- issues: string[];
22
- }
23
-
24
- /**
25
- * Check for latest version from npm (with timeout)
26
- */
27
- async function checkLatestVersion(timeout = 3000): Promise<string | null> {
28
- try {
29
- const controller = new AbortController();
30
- const timeoutId = setTimeout(() => controller.abort(), timeout);
31
-
32
- const response = await fetch('https://registry.npmjs.org/safeword/latest', {
33
- signal: controller.signal,
34
- });
35
-
36
- clearTimeout(timeoutId);
37
-
38
- if (!response.ok) return null;
39
-
40
- const data = (await response.json()) as { version?: string };
41
- return data.version ?? null;
42
- } catch {
43
- return null;
44
- }
45
- }
46
-
47
- /**
48
- * Check project configuration health
49
- */
50
- function checkHealth(cwd: string): HealthStatus {
51
- const safewordDir = join(cwd, '.safeword');
52
- const issues: string[] = [];
53
-
54
- // Check if configured
55
- if (!exists(safewordDir)) {
56
- return {
57
- configured: false,
58
- projectVersion: null,
59
- cliVersion: VERSION,
60
- updateAvailable: false,
61
- latestVersion: null,
62
- issues: [],
63
- };
64
- }
65
-
66
- // Read project version
67
- const versionPath = join(safewordDir, 'version');
68
- const projectVersion = readFileSafe(versionPath)?.trim() ?? null;
69
-
70
- // Check for required files
71
- const requiredFiles = ['SAFEWORD.md', 'version', 'hooks/agents-md-check.sh'];
72
-
73
- for (const file of requiredFiles) {
74
- if (!exists(join(safewordDir, file))) {
75
- issues.push(`Missing: .safeword/${file}`);
76
- }
77
- }
78
-
79
- // Check AGENTS.md link
80
- const agentsMdPath = join(cwd, 'AGENTS.md');
81
- if (exists(agentsMdPath)) {
82
- const content = readFile(agentsMdPath);
83
- if (!content.includes('@./.safeword/SAFEWORD.md')) {
84
- issues.push('AGENTS.md missing safeword link');
85
- }
86
- } else {
87
- issues.push('AGENTS.md file missing');
88
- }
89
-
90
- // Check .claude/settings.json
91
- const settingsPath = join(cwd, '.claude', 'settings.json');
92
- if (!exists(settingsPath)) {
93
- issues.push('Missing: .claude/settings.json');
94
- }
95
-
96
- return {
97
- configured: true,
98
- projectVersion,
99
- cliVersion: VERSION,
100
- updateAvailable: false,
101
- latestVersion: null,
102
- issues,
103
- };
104
- }
105
-
106
- export async function check(options: CheckOptions): Promise<void> {
107
- const cwd = process.cwd();
108
-
109
- header('Safeword Health Check');
110
-
111
- const health = checkHealth(cwd);
112
-
113
- // Not configured
114
- if (!health.configured) {
115
- info('Not configured. Run `safeword setup` to initialize.');
116
- return;
117
- }
118
-
119
- // Show versions
120
- keyValue('Safeword CLI', `v${health.cliVersion}`);
121
- keyValue('Project config', health.projectVersion ? `v${health.projectVersion}` : 'unknown');
122
-
123
- // Check for updates (unless offline)
124
- if (!options.offline) {
125
- info('\nChecking for updates...');
126
- const latestVersion = await checkLatestVersion();
127
-
128
- if (latestVersion) {
129
- health.latestVersion = latestVersion;
130
- health.updateAvailable = isNewerVersion(health.cliVersion, latestVersion);
131
-
132
- if (health.updateAvailable) {
133
- warn(`Update available: v${latestVersion}`);
134
- info('Run `npm install -g safeword` to upgrade');
135
- } else {
136
- success('CLI is up to date');
137
- }
138
- } else {
139
- warn("Couldn't check for updates (offline?)");
140
- }
141
- } else {
142
- info('\nSkipped update check (offline mode)');
143
- }
144
-
145
- // Check project version vs CLI version
146
- if (health.projectVersion && isNewerVersion(health.cliVersion, health.projectVersion)) {
147
- warn(`Project config (v${health.projectVersion}) is newer than CLI (v${health.cliVersion})`);
148
- info('Consider upgrading the CLI');
149
- } else if (health.projectVersion && isNewerVersion(health.projectVersion, health.cliVersion)) {
150
- info(`\nUpgrade available for project config`);
151
- info(
152
- `Run \`safeword upgrade\` to update from v${health.projectVersion} to v${health.cliVersion}`,
153
- );
154
- }
155
-
156
- // Show issues
157
- if (health.issues.length > 0) {
158
- header('Issues Found');
159
- for (const issue of health.issues) {
160
- warn(issue);
161
- }
162
- info('\nRun `safeword upgrade` to repair configuration');
163
- } else {
164
- success('\nConfiguration is healthy');
165
- }
166
- }