cc-discipline 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +153 -0
  3. package/README.zh-CN.md +207 -0
  4. package/bin/cli.sh +96 -0
  5. package/global/CLAUDE.md +43 -0
  6. package/init.sh +486 -0
  7. package/lib/doctor.sh +145 -0
  8. package/lib/stack-remove.sh +68 -0
  9. package/lib/status.sh +95 -0
  10. package/package.json +34 -0
  11. package/templates/.claude/agents/investigator.md +44 -0
  12. package/templates/.claude/agents/reviewer.md +46 -0
  13. package/templates/.claude/hooks/action-counter.sh +28 -0
  14. package/templates/.claude/hooks/phase-gate.sh +10 -0
  15. package/templates/.claude/hooks/post-error-remind.sh +109 -0
  16. package/templates/.claude/hooks/pre-edit-guard.sh +79 -0
  17. package/templates/.claude/hooks/session-start.sh +43 -0
  18. package/templates/.claude/hooks/streak-breaker.sh +111 -0
  19. package/templates/.claude/rules/00-core-principles.md +12 -0
  20. package/templates/.claude/rules/01-debugging.md +22 -0
  21. package/templates/.claude/rules/02-before-edit.md +11 -0
  22. package/templates/.claude/rules/03-context-mgmt.md +19 -0
  23. package/templates/.claude/rules/04-no-mole-whacking.md +26 -0
  24. package/templates/.claude/rules/05-phase-discipline.md +13 -0
  25. package/templates/.claude/rules/06-multi-task.md +11 -0
  26. package/templates/.claude/rules/07-integrity.md +81 -0
  27. package/templates/.claude/rules/stacks/embedded.md +24 -0
  28. package/templates/.claude/rules/stacks/js-ts.md +21 -0
  29. package/templates/.claude/rules/stacks/mobile.md +16 -0
  30. package/templates/.claude/rules/stacks/python.md +20 -0
  31. package/templates/.claude/rules/stacks/rtl.md +24 -0
  32. package/templates/.claude/settings.json +75 -0
  33. package/templates/.claude/skills/commit/SKILL.md +40 -0
  34. package/templates/.claude/skills/evaluate/SKILL.md +57 -0
  35. package/templates/.claude/skills/self-check/SKILL.md +62 -0
  36. package/templates/CLAUDE.md +80 -0
  37. package/templates/docs/debug-log.md +48 -0
  38. package/templates/docs/progress.md +29 -0
  39. package/templates/memory/MEMORY.md +23 -0
package/init.sh ADDED
@@ -0,0 +1,486 @@
1
+ #!/bin/bash
2
+ # cc-discipline init script
3
+ # Usage: cd your-project && bash /path/to/init.sh
4
+ # cd your-project && bash /path/to/init.sh --auto # non-interactive, defaults
5
+ # cd your-project && bash /path/to/init.sh --stack "3 4" --name myapp --global
6
+ # Or: curl -sL https://raw.githubusercontent.com/YOU/cc-discipline/main/init.sh | bash
7
+
8
+ set -e
9
+
10
+ # ─── Version ───
11
+ VERSION="2.0.0"
12
+
13
+ # ─── Parse CLI arguments ───
14
+ ARG_STACK=""
15
+ ARG_NAME=""
16
+ ARG_GLOBAL=""
17
+ ARG_AUTO=false
18
+
19
+ while [[ $# -gt 0 ]]; do
20
+ case $1 in
21
+ --auto)
22
+ ARG_AUTO=true
23
+ shift
24
+ ;;
25
+ --stack)
26
+ ARG_STACK="$2"
27
+ shift 2
28
+ ;;
29
+ --name)
30
+ ARG_NAME="$2"
31
+ shift 2
32
+ ;;
33
+ --global)
34
+ ARG_GLOBAL="y"
35
+ shift
36
+ ;;
37
+ --no-global)
38
+ ARG_GLOBAL="n"
39
+ shift
40
+ ;;
41
+ -h|--help)
42
+ echo "Usage: bash init.sh [options]"
43
+ echo ""
44
+ echo "Options:"
45
+ echo " --auto Non-interactive with defaults (stack=7, name=dirname, no global)"
46
+ echo " --stack <choices> Stack selection: 1-7, space-separated (e.g., --stack \"3 4\")"
47
+ echo " --name <name> Project name (default: directory name)"
48
+ echo " --global Install global rules to ~/.claude/CLAUDE.md"
49
+ echo " --no-global Skip global rules install"
50
+ echo " -h, --help Show this help"
51
+ echo ""
52
+ echo "Stacks: 1=RTL 2=Embedded 3=Python 4=JS/TS 5=Mobile 6=Fullstack 7=General"
53
+ exit 0
54
+ ;;
55
+ *)
56
+ echo "Unknown option: $1 (use --help for usage)"
57
+ exit 1
58
+ ;;
59
+ esac
60
+ done
61
+
62
+ # --auto sets defaults for anything not explicitly provided
63
+ if [ "$ARG_AUTO" = true ]; then
64
+ [ -z "$ARG_STACK" ] && ARG_STACK="7"
65
+ [ -z "$ARG_GLOBAL" ] && ARG_GLOBAL="n"
66
+ fi
67
+
68
+ # ─── Colors ───
69
+ RED='\033[0;31m'
70
+ GREEN='\033[0;32m'
71
+ YELLOW='\033[1;33m'
72
+ BLUE='\033[0;34m'
73
+ CYAN='\033[0;36m'
74
+ NC='\033[0m'
75
+
76
+ # Support both direct execution and npm (via CC_DISCIPLINE_PKG_DIR)
77
+ if [ -n "$CC_DISCIPLINE_PKG_DIR" ]; then
78
+ SCRIPT_DIR="$CC_DISCIPLINE_PKG_DIR"
79
+ else
80
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
81
+ fi
82
+ PROJECT_DIR="$(pwd)"
83
+
84
+ echo -e "${CYAN}╔══════════════════════════════════════════════╗${NC}"
85
+ echo -e "${CYAN}║ Claude Code Discipline Framework — Setup ║${NC}"
86
+ echo -e "${CYAN}╚══════════════════════════════════════════════╝${NC}"
87
+ echo ""
88
+ echo -e "Project directory: ${GREEN}${PROJECT_DIR}${NC}"
89
+
90
+ # ─── Detect install mode ───
91
+ INSTALL_MODE="fresh"
92
+ INSTALLED_VERSION=""
93
+
94
+ if [ -f ".claude/.cc-discipline-version" ]; then
95
+ INSTALL_MODE="upgrade"
96
+ INSTALLED_VERSION=$(cat ".claude/.cc-discipline-version")
97
+ elif [ -f ".claude/hooks/streak-breaker.sh" ] || [ -f ".claude/hooks/pre-edit-guard.sh" ] || [ -f ".claude/hooks/session-start.sh" ] || [ -f ".claude/hooks/phase-gate.sh" ]; then
98
+ INSTALL_MODE="upgrade"
99
+ INSTALLED_VERSION="<2.0.0"
100
+ elif [ -d ".claude" ] || [ -f "CLAUDE.md" ]; then
101
+ INSTALL_MODE="append"
102
+ fi
103
+
104
+ case "$INSTALL_MODE" in
105
+ fresh)
106
+ echo -e "Mode: ${GREEN}Fresh install${NC}"
107
+ ;;
108
+ upgrade)
109
+ echo -e "Mode: ${YELLOW}Upgrade cc-discipline (${INSTALLED_VERSION} → ${VERSION})${NC}"
110
+ ;;
111
+ append)
112
+ echo -e "Mode: ${YELLOW}Adding discipline to existing project${NC}"
113
+ echo -e "${YELLOW}Your existing files will be preserved. cc-discipline files will be added alongside them.${NC}"
114
+ ;;
115
+ esac
116
+ echo ""
117
+
118
+ # ─── Backup (upgrade/append) ───
119
+ BACKUP_DIR=""
120
+ if [ "$INSTALL_MODE" != "fresh" ]; then
121
+ BACKUP_DIR=".claude/.backup-$(date +%Y%m%d-%H%M%S)"
122
+ mkdir -p "$BACKUP_DIR"
123
+ [ -f "CLAUDE.md" ] && cp "CLAUDE.md" "$BACKUP_DIR/"
124
+ [ -f ".claude/settings.json" ] && cp ".claude/settings.json" "$BACKUP_DIR/"
125
+ [ -d ".claude/hooks" ] && cp -r ".claude/hooks" "$BACKUP_DIR/"
126
+ [ -d ".claude/rules" ] && cp -r ".claude/rules" "$BACKUP_DIR/"
127
+ [ -d ".claude/agents" ] && cp -r ".claude/agents" "$BACKUP_DIR/"
128
+ [ -d ".claude/skills" ] && cp -r ".claude/skills" "$BACKUP_DIR/"
129
+ echo -e "${GREEN}Backup saved to ${BACKUP_DIR}/${NC}"
130
+ echo ""
131
+ fi
132
+
133
+ # ─── Detect installed stacks (for upgrade/append) ───
134
+ detect_installed_stacks() {
135
+ INSTALLED_STACKS=""
136
+ [ -f ".claude/rules/stacks/rtl.md" ] && INSTALLED_STACKS="${INSTALLED_STACKS}1 "
137
+ [ -f ".claude/rules/stacks/embedded.md" ] && INSTALLED_STACKS="${INSTALLED_STACKS}2 "
138
+ [ -f ".claude/rules/stacks/python.md" ] && INSTALLED_STACKS="${INSTALLED_STACKS}3 "
139
+ [ -f ".claude/rules/stacks/js-ts.md" ] && INSTALLED_STACKS="${INSTALLED_STACKS}4 "
140
+ [ -f ".claude/rules/stacks/mobile.md" ] && INSTALLED_STACKS="${INSTALLED_STACKS}5 "
141
+ return 0
142
+ }
143
+
144
+ # ─── Select project type ───
145
+ if [ -n "$ARG_STACK" ]; then
146
+ STACK_CHOICES="$ARG_STACK"
147
+ echo -e "Stack: ${GREEN}${STACK_CHOICES}${NC} (from CLI)"
148
+ elif [ "$INSTALL_MODE" = "fresh" ]; then
149
+ echo -e "${BLUE}What is your project type? (select multiple with spaces)${NC}"
150
+ echo " 1) RTL / IC Design (Verilog, VHDL, SystemVerilog)"
151
+ echo " 2) Embedded (C/C++, bare-metal, RTOS)"
152
+ echo " 3) Python (backend / scripting / ML)"
153
+ echo " 4) JavaScript / TypeScript (Node, Web)"
154
+ echo " 5) Mobile (Swift, Kotlin, React Native, Flutter)"
155
+ echo " 6) Full-stack Web (frontend + backend)"
156
+ echo " 7) Other / General"
157
+ echo ""
158
+ read -p "Choose (e.g.: 1 2 or 3 4 6): " STACK_CHOICES
159
+ else
160
+ detect_installed_stacks
161
+ echo -e "${BLUE}Stack rules (* = already installed):${NC}"
162
+ for i in 1 2 3 4 5; do
163
+ MARKER=""
164
+ echo "$INSTALLED_STACKS" | grep -q "$i" && MARKER=" ${GREEN}*${NC}"
165
+ case $i in
166
+ 1) echo -e " 1) RTL / IC Design${MARKER}" ;;
167
+ 2) echo -e " 2) Embedded${MARKER}" ;;
168
+ 3) echo -e " 3) Python${MARKER}" ;;
169
+ 4) echo -e " 4) JavaScript / TypeScript${MARKER}" ;;
170
+ 5) echo -e " 5) Mobile${MARKER}" ;;
171
+ esac
172
+ done
173
+ echo " 6) Full-stack Web (JS/TS + Python)"
174
+ echo " 7) Other / General"
175
+ echo ""
176
+ read -p "Add stacks (e.g.: 2 4), or press Enter to keep current: " STACK_CHOICES
177
+ fi
178
+
179
+ # Parse choices into array
180
+ IFS=' ' read -ra STACKS <<< "$STACK_CHOICES"
181
+
182
+ # ─── Project name ───
183
+ if [ -n "$ARG_NAME" ]; then
184
+ PROJECT_NAME="$ARG_NAME"
185
+ echo -e "Project name: ${GREEN}${PROJECT_NAME}${NC} (from CLI)"
186
+ elif [ "$INSTALL_MODE" = "fresh" ]; then
187
+ DEFAULT_NAME=$(basename "$PROJECT_DIR")
188
+ if [ "$ARG_AUTO" = true ]; then
189
+ PROJECT_NAME="$DEFAULT_NAME"
190
+ echo -e "Project name: ${GREEN}${PROJECT_NAME}${NC} (auto)"
191
+ else
192
+ read -p "Project name [$DEFAULT_NAME]: " PROJECT_NAME
193
+ PROJECT_NAME=${PROJECT_NAME:-$DEFAULT_NAME}
194
+ fi
195
+ else
196
+ # Try to extract from existing CLAUDE.md: "# MyProject — CLAUDE.md"
197
+ PROJECT_NAME=""
198
+ if [ -f "CLAUDE.md" ]; then
199
+ PROJECT_NAME=$(head -1 CLAUDE.md | sed 's/^# //;s/ — CLAUDE.md$//' 2>/dev/null)
200
+ fi
201
+ if [ -z "$PROJECT_NAME" ] || [ "$PROJECT_NAME" = "[PROJECT_NAME]" ]; then
202
+ DEFAULT_NAME=$(basename "$PROJECT_DIR")
203
+ if [ "$ARG_AUTO" = true ]; then
204
+ PROJECT_NAME="$DEFAULT_NAME"
205
+ echo -e "Project name: ${GREEN}${PROJECT_NAME}${NC} (auto)"
206
+ else
207
+ read -p "Project name [$DEFAULT_NAME]: " PROJECT_NAME
208
+ PROJECT_NAME=${PROJECT_NAME:-$DEFAULT_NAME}
209
+ fi
210
+ else
211
+ echo -e "Project name: ${GREEN}${PROJECT_NAME}${NC} (from CLAUDE.md)"
212
+ fi
213
+ fi
214
+
215
+ # ─── Create directory structure ───
216
+ echo ""
217
+ echo -e "${GREEN}Creating directory structure...${NC}"
218
+ mkdir -p .claude/rules/stacks
219
+ mkdir -p .claude/hooks
220
+ mkdir -p .claude/agents
221
+ mkdir -p .claude/skills
222
+ mkdir -p docs
223
+
224
+ # ─── Copy core rules (always applied, always overwrite — these are framework files) ───
225
+ echo -e "${GREEN}Installing core rules...${NC}"
226
+ cp "$SCRIPT_DIR/templates/.claude/rules/00-core-principles.md" .claude/rules/
227
+ cp "$SCRIPT_DIR/templates/.claude/rules/01-debugging.md" .claude/rules/
228
+ cp "$SCRIPT_DIR/templates/.claude/rules/02-before-edit.md" .claude/rules/
229
+ cp "$SCRIPT_DIR/templates/.claude/rules/03-context-mgmt.md" .claude/rules/
230
+ cp "$SCRIPT_DIR/templates/.claude/rules/04-no-mole-whacking.md" .claude/rules/
231
+ cp "$SCRIPT_DIR/templates/.claude/rules/05-phase-discipline.md" .claude/rules/
232
+ cp "$SCRIPT_DIR/templates/.claude/rules/06-multi-task.md" .claude/rules/
233
+ cp "$SCRIPT_DIR/templates/.claude/rules/07-integrity.md" .claude/rules/
234
+
235
+ # ─── Copy stack-specific rules based on selection ───
236
+ if [ ${#STACKS[@]} -gt 0 ] && [ -n "${STACKS[0]}" ]; then
237
+ echo -e "${GREEN}Installing stack rules...${NC}"
238
+ for choice in "${STACKS[@]}"; do
239
+ case $choice in
240
+ 1)
241
+ cp "$SCRIPT_DIR/templates/.claude/rules/stacks/rtl.md" .claude/rules/stacks/
242
+ echo " ✓ RTL / IC Design rules"
243
+ ;;
244
+ 2)
245
+ cp "$SCRIPT_DIR/templates/.claude/rules/stacks/embedded.md" .claude/rules/stacks/
246
+ echo " ✓ Embedded development rules"
247
+ ;;
248
+ 3)
249
+ cp "$SCRIPT_DIR/templates/.claude/rules/stacks/python.md" .claude/rules/stacks/
250
+ echo " ✓ Python rules"
251
+ ;;
252
+ 4)
253
+ cp "$SCRIPT_DIR/templates/.claude/rules/stacks/js-ts.md" .claude/rules/stacks/
254
+ echo " ✓ JavaScript / TypeScript rules"
255
+ ;;
256
+ 5)
257
+ cp "$SCRIPT_DIR/templates/.claude/rules/stacks/mobile.md" .claude/rules/stacks/
258
+ echo " ✓ Mobile development rules"
259
+ ;;
260
+ 6)
261
+ cp "$SCRIPT_DIR/templates/.claude/rules/stacks/js-ts.md" .claude/rules/stacks/
262
+ cp "$SCRIPT_DIR/templates/.claude/rules/stacks/python.md" .claude/rules/stacks/
263
+ echo " ✓ Full-stack rules (JS/TS + Python)"
264
+ ;;
265
+ 7)
266
+ echo " ✓ General rules (no additional stack rules)"
267
+ ;;
268
+ esac
269
+ done
270
+ fi
271
+
272
+ # ─── Install hooks ───
273
+ echo -e "${GREEN}Installing hooks...${NC}"
274
+ cp "$SCRIPT_DIR/templates/.claude/hooks/pre-edit-guard.sh" .claude/hooks/
275
+ cp "$SCRIPT_DIR/templates/.claude/hooks/post-error-remind.sh" .claude/hooks/
276
+ cp "$SCRIPT_DIR/templates/.claude/hooks/streak-breaker.sh" .claude/hooks/
277
+ cp "$SCRIPT_DIR/templates/.claude/hooks/session-start.sh" .claude/hooks/
278
+ cp "$SCRIPT_DIR/templates/.claude/hooks/phase-gate.sh" .claude/hooks/
279
+ cp "$SCRIPT_DIR/templates/.claude/hooks/action-counter.sh" .claude/hooks/
280
+ chmod +x .claude/hooks/*.sh
281
+
282
+ # ─── Check jq availability ───
283
+ HAS_JQ=false
284
+ if command -v jq &>/dev/null; then
285
+ HAS_JQ=true
286
+ else
287
+ echo ""
288
+ echo -e "${YELLOW}Warning: jq not found — Hooks will use grep/sed fallback, but jq is recommended${NC}"
289
+ echo " macOS: brew install jq"
290
+ echo " Ubuntu: sudo apt install jq"
291
+ echo " Arch: sudo pacman -S jq"
292
+ echo ""
293
+ fi
294
+
295
+ # ─── Install/merge settings.json ───
296
+ SETTINGS_TEMPLATE="$SCRIPT_DIR/templates/.claude/settings.json"
297
+
298
+ if [ ! -f ".claude/settings.json" ]; then
299
+ # No existing settings.json — just copy template
300
+ cp "$SETTINGS_TEMPLATE" .claude/settings.json
301
+ echo -e "${GREEN} ✓ settings.json created${NC}"
302
+ elif [ "$INSTALL_MODE" = "fresh" ]; then
303
+ # Fresh mode shouldn't reach here, but just in case
304
+ cp "$SETTINGS_TEMPLATE" .claude/settings.json
305
+ else
306
+ # Merge: preserve user hooks, add/update cc-discipline hooks
307
+ if [ "$HAS_JQ" = true ]; then
308
+ TEMP_SETTINGS=$(mktemp)
309
+ MERGE_OK=false
310
+
311
+ if jq -s '
312
+ .[0] as $e | .[1] as $t |
313
+ def is_cc: .hooks | any(.command | test("pre-edit-guard|streak-breaker|post-error-remind|session-start|phase-gate|action-counter"));
314
+ def merge($ev): (($e.hooks[$ev] // []) | map(select(is_cc | not))) + ($t.hooks[$ev] // []);
315
+ $e * {
316
+ hooks: (($e.hooks // {}) + {
317
+ SessionStart: merge("SessionStart"),
318
+ PreToolUse: merge("PreToolUse"),
319
+ PostToolUse: merge("PostToolUse"),
320
+ PostToolUseFailure: merge("PostToolUseFailure")
321
+ } | with_entries(select(.value | length > 0)))
322
+ }
323
+ ' .claude/settings.json "$SETTINGS_TEMPLATE" > "$TEMP_SETTINGS" 2>/dev/null; then
324
+ # Verify the output is valid JSON
325
+ if jq empty "$TEMP_SETTINGS" 2>/dev/null; then
326
+ mv "$TEMP_SETTINGS" .claude/settings.json
327
+ MERGE_OK=true
328
+ echo -e "${GREEN} ✓ settings.json merged (your existing hooks preserved)${NC}"
329
+ fi
330
+ fi
331
+
332
+ if [ "$MERGE_OK" = false ]; then
333
+ rm -f "$TEMP_SETTINGS"
334
+ echo -e "${YELLOW} Warning: settings.json merge failed. Your file was NOT modified.${NC}"
335
+ echo -e "${YELLOW} Backed up to: ${BACKUP_DIR}/settings.json${NC}"
336
+ cp "$SETTINGS_TEMPLATE" .claude/.cc-discipline-settings-template.json
337
+ echo -e "${YELLOW} See .claude/.cc-discipline-settings-template.json for hooks to add manually.${NC}"
338
+ fi
339
+ else
340
+ # No jq — don't touch existing settings.json
341
+ echo -e "${YELLOW} settings.json: cannot merge without jq. Your file was NOT modified.${NC}"
342
+ echo -e "${YELLOW} Backed up to: ${BACKUP_DIR}/settings.json${NC}"
343
+ cp "$SETTINGS_TEMPLATE" .claude/.cc-discipline-settings-template.json
344
+ echo -e "${YELLOW} See .claude/.cc-discipline-settings-template.json for hooks to add manually.${NC}"
345
+ fi
346
+ fi
347
+
348
+ # ─── Install subagents ───
349
+ echo -e "${GREEN}Installing subagents...${NC}"
350
+ cp "$SCRIPT_DIR/templates/.claude/agents/reviewer.md" .claude/agents/
351
+ cp "$SCRIPT_DIR/templates/.claude/agents/investigator.md" .claude/agents/
352
+
353
+ # ─── Install skills ───
354
+ echo -e "${GREEN}Installing skills...${NC}"
355
+ cp -r "$SCRIPT_DIR/templates/.claude/skills/commit" .claude/skills/
356
+ cp -r "$SCRIPT_DIR/templates/.claude/skills/self-check" .claude/skills/
357
+ cp -r "$SCRIPT_DIR/templates/.claude/skills/evaluate" .claude/skills/
358
+ echo " ✓ /commit — smart commit (test → update memory → commit)"
359
+ echo " ✓ /self-check — periodic discipline check (use with /loop 10m /self-check)"
360
+ echo " ✓ /evaluate — evaluate external review/advice against codebase context"
361
+
362
+ # ─── Handle CLAUDE.md ───
363
+ if [ ! -f "CLAUDE.md" ]; then
364
+ # No CLAUDE.md exists — generate from template
365
+ echo -e "${GREEN}Generating CLAUDE.md...${NC}"
366
+ sed "s/\[PROJECT_NAME\]/$PROJECT_NAME/g" "$SCRIPT_DIR/templates/CLAUDE.md" > CLAUDE.md
367
+ else
368
+ if [ "$INSTALL_MODE" = "fresh" ]; then
369
+ # Should not happen (fresh mode means no existing files), but handle gracefully
370
+ sed "s/\[PROJECT_NAME\]/$PROJECT_NAME/g" "$SCRIPT_DIR/templates/CLAUDE.md" > CLAUDE.md
371
+ else
372
+ # Existing CLAUDE.md — NEVER overwrite
373
+ echo -e "${YELLOW} CLAUDE.md already exists — NOT modified (your content is safe)${NC}"
374
+ sed "s/\[PROJECT_NAME\]/$PROJECT_NAME/g" "$SCRIPT_DIR/templates/CLAUDE.md" \
375
+ > .claude/.cc-discipline-claude-md-template
376
+ echo " Discipline template saved to .claude/.cc-discipline-claude-md-template"
377
+ echo " You can reference it to add discipline sections to your CLAUDE.md."
378
+ fi
379
+ fi
380
+
381
+ # ─── Copy docs templates (only if not exist) ───
382
+ if [ ! -f "docs/progress.md" ]; then
383
+ cp "$SCRIPT_DIR/templates/docs/progress.md" docs/
384
+ fi
385
+ if [ ! -f "docs/debug-log.md" ]; then
386
+ cp "$SCRIPT_DIR/templates/docs/debug-log.md" docs/
387
+ fi
388
+
389
+ # ─── Install auto memory ───
390
+ echo -e "${GREEN}Installing auto memory...${NC}"
391
+ MEMORY_PROJECT_KEY=$(echo "$PROJECT_DIR" | sed 's|/|-|g')
392
+ MEMORY_DIR="$HOME/.claude/projects/${MEMORY_PROJECT_KEY}/memory"
393
+ mkdir -p "$MEMORY_DIR"
394
+ if [ ! -f "$MEMORY_DIR/MEMORY.md" ]; then
395
+ cp "$SCRIPT_DIR/templates/memory/MEMORY.md" "$MEMORY_DIR/MEMORY.md"
396
+ echo " ✓ Memory installed to $MEMORY_DIR/MEMORY.md"
397
+ else
398
+ echo -e " ${YELLOW}MEMORY.md already exists, skipping (no overwrite)${NC}"
399
+ fi
400
+
401
+ # ─── Install global rules (optional) ───
402
+ if [ -n "$ARG_GLOBAL" ]; then
403
+ REPLY="$ARG_GLOBAL"
404
+ else
405
+ echo ""
406
+ echo -e "${BLUE}Install global rules to ~/.claude/CLAUDE.md?${NC}"
407
+ echo " (Global rules apply to all projects, only needs to be installed once)"
408
+ read -p "Install global rules? (y/N) " -n 1 -r
409
+ echo
410
+ fi
411
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
412
+ mkdir -p ~/.claude
413
+ if [ -f ~/.claude/CLAUDE.md ]; then
414
+ echo -e "${YELLOW} Existing ~/.claude/CLAUDE.md found, backing up to ~/.claude/CLAUDE.md.bak${NC}"
415
+ cp ~/.claude/CLAUDE.md ~/.claude/CLAUDE.md.bak
416
+ fi
417
+ cp "$SCRIPT_DIR/global/CLAUDE.md" ~/.claude/CLAUDE.md
418
+ echo -e "${GREEN} ✓ Global rules installed${NC}"
419
+ fi
420
+
421
+ # ─── Write version marker ───
422
+ echo "$VERSION" > .claude/.cc-discipline-version
423
+
424
+ # ─── Summary ───
425
+ echo ""
426
+ echo -e "${CYAN}╔══════════════════════════════════════════════╗${NC}"
427
+ echo -e "${CYAN}║ Setup complete! ║${NC}"
428
+ echo -e "${CYAN}╚══════════════════════════════════════════════╝${NC}"
429
+ echo ""
430
+
431
+ if [ "$INSTALL_MODE" = "fresh" ]; then
432
+ echo -e "Created files:"
433
+ echo -e " ${GREEN}CLAUDE.md${NC} ← Project rules (fill in [TODO] sections)"
434
+ echo -e " ${GREEN}.claude/rules/${NC} ← Auto-injected rules"
435
+ echo -e " ${GREEN}.claude/hooks/${NC} ← 6 discipline hooks (edit guard, streak breaker, phase gate, action counter, error remind, session start)"
436
+ echo -e " ${GREEN}.claude/agents/${NC} ← Reviewer & investigator subagents"
437
+ echo -e " ${GREEN}.claude/skills/commit/${NC} ← /commit smart commit"
438
+ echo -e " ${GREEN}.claude/skills/self-check/${NC} ← /self-check periodic discipline check"
439
+ echo -e " ${GREEN}.claude/skills/evaluate/${NC} ← /evaluate assess external review advice"
440
+ echo -e " ${GREEN}.claude/settings.json${NC} ← Hooks configuration"
441
+ echo -e " ${GREEN}docs/progress.md${NC} ← Progress log (maintained by Claude)"
442
+ echo -e " ${GREEN}docs/debug-log.md${NC} ← Debug log (maintained by Claude)"
443
+ echo -e " ${GREEN}~/.claude/projects/.../memory/${NC} ← Auto memory (cross-session)"
444
+ echo ""
445
+ echo -e "${YELLOW}Next steps:${NC}"
446
+ echo " 1. Edit CLAUDE.md and fill in the [TODO] sections with project info"
447
+ echo " 2. Review rules in .claude/rules/stacks/ and adjust as needed"
448
+ echo " 3. For complex tasks, use: /loop 10m /self-check"
449
+ echo " 4. Start working with Claude Code!"
450
+ else
451
+ echo -e "What was done:"
452
+ echo -e " ${GREEN}.claude/rules/${NC} ← Discipline rules installed/updated"
453
+ echo -e " ${GREEN}.claude/hooks/${NC} ← Hook scripts installed/updated"
454
+ echo -e " ${GREEN}.claude/agents/${NC} ← Subagents installed/updated"
455
+ echo -e " ${GREEN}.claude/skills/commit/${NC} ← /commit skill installed/updated"
456
+ echo -e " ${GREEN}.claude/skills/self-check/${NC} ← /self-check discipline check installed"
457
+ echo -e " ${GREEN}.claude/skills/evaluate/${NC} ← /evaluate external review assessment"
458
+ if [ ! -f "$BACKUP_DIR/settings.json" ] || [ -f ".claude/.cc-discipline-settings-template.json" ]; then
459
+ echo -e " ${YELLOW}.claude/settings.json${NC} ← See notes above"
460
+ else
461
+ echo -e " ${GREEN}.claude/settings.json${NC} ← Hooks merged"
462
+ fi
463
+ echo ""
464
+ echo -e "What was ${GREEN}NOT${NC} touched:"
465
+ echo -e " CLAUDE.md ← Your project info is safe"
466
+ echo -e " docs/progress.md ← Your progress records are safe"
467
+ echo -e " docs/debug-log.md ← Your debug logs are safe"
468
+ echo -e " Your custom rules/agents ← Untouched (we only add our files)"
469
+ echo ""
470
+ echo -e "${YELLOW}Backup:${NC} ${BACKUP_DIR}/"
471
+ echo " Consider adding .claude/.backup-* to .gitignore"
472
+ echo ""
473
+ if [ -f ".claude/.cc-discipline-claude-md-template" ]; then
474
+ echo -e "${YELLOW}Next steps:${NC}"
475
+ echo " 1. Review .claude/.cc-discipline-claude-md-template"
476
+ echo " Consider adding the docs/ structure and discipline sections to your CLAUDE.md"
477
+ echo " 2. Review rules in .claude/rules/stacks/ and adjust as needed"
478
+ echo " 3. Start working with Claude Code!"
479
+ else
480
+ echo -e "${YELLOW}Next steps:${NC}"
481
+ echo " 1. Review rules in .claude/rules/stacks/ and adjust as needed"
482
+ echo " 2. Start working with Claude Code!"
483
+ fi
484
+ fi
485
+ echo ""
486
+ echo -e "${YELLOW}Tip:${NC} Commit .claude/ and CLAUDE.md to git to share discipline across the team"
package/lib/doctor.sh ADDED
@@ -0,0 +1,145 @@
1
+ #!/bin/bash
2
+ # cc-discipline doctor — diagnose installation issues
3
+ set -e
4
+
5
+ GREEN='\033[0;32m'
6
+ YELLOW='\033[1;33m'
7
+ RED='\033[0;31m'
8
+ NC='\033[0m'
9
+
10
+ ISSUES=0
11
+ WARNINGS=0
12
+
13
+ ok() { echo -e " ${GREEN}✓${NC} $1"; }
14
+ warn() { echo -e " ${YELLOW}!${NC} $1"; WARNINGS=$((WARNINGS + 1)); }
15
+ fail() { echo -e " ${RED}✗${NC} $1"; ISSUES=$((ISSUES + 1)); }
16
+
17
+ echo "cc-discipline doctor"
18
+ echo "──────────────────────"
19
+ echo ""
20
+
21
+ # 1. Version file
22
+ echo "Installation:"
23
+ if [ -f ".claude/.cc-discipline-version" ]; then
24
+ ok "Version file: $(cat .claude/.cc-discipline-version)"
25
+ else
26
+ fail "Not installed (no .claude/.cc-discipline-version)"
27
+ echo ""
28
+ echo "Run 'npx cc-discipline init' to install."
29
+ exit 1
30
+ fi
31
+
32
+ # 2. Core rules
33
+ echo ""
34
+ echo "Core rules:"
35
+ for i in 00 01 02 03 04 05 06 07; do
36
+ FILE=$(ls .claude/rules/${i}-*.md 2>/dev/null | head -1)
37
+ if [ -n "$FILE" ]; then
38
+ ok "$(basename "$FILE")"
39
+ else
40
+ fail "Missing rule ${i}-*.md"
41
+ fi
42
+ done
43
+
44
+ # 3. Hooks
45
+ echo ""
46
+ echo "Hooks:"
47
+ for hook in pre-edit-guard streak-breaker post-error-remind session-start phase-gate action-counter; do
48
+ if [ -f ".claude/hooks/${hook}.sh" ]; then
49
+ if [ -x ".claude/hooks/${hook}.sh" ]; then
50
+ ok "${hook}.sh"
51
+ else
52
+ warn "${hook}.sh exists but not executable"
53
+ fi
54
+ else
55
+ fail "Missing ${hook}.sh"
56
+ fi
57
+ done
58
+
59
+ # 4. settings.json hook registration
60
+ echo ""
61
+ echo "Hook registration:"
62
+ if [ -f ".claude/settings.json" ]; then
63
+ if command -v jq &>/dev/null; then
64
+ CONTENT=$(cat .claude/settings.json)
65
+ for hook in pre-edit-guard streak-breaker post-error-remind session-start phase-gate action-counter; do
66
+ if echo "$CONTENT" | grep -q "$hook"; then
67
+ ok "${hook} registered"
68
+ else
69
+ fail "${hook} NOT registered in settings.json"
70
+ fi
71
+ done
72
+ else
73
+ warn "jq not installed — cannot verify hook registration details"
74
+ if grep -q "pre-edit-guard" .claude/settings.json 2>/dev/null; then
75
+ ok "settings.json contains hook references"
76
+ else
77
+ fail "settings.json doesn't reference any hooks"
78
+ fi
79
+ fi
80
+ else
81
+ fail "settings.json missing"
82
+ fi
83
+
84
+ # 5. Agents
85
+ echo ""
86
+ echo "Agents:"
87
+ for agent in reviewer investigator; do
88
+ if [ -f ".claude/agents/${agent}.md" ]; then
89
+ ok "${agent}.md"
90
+ else
91
+ warn "Missing ${agent}.md (optional)"
92
+ fi
93
+ done
94
+
95
+ # 6. Skills
96
+ echo ""
97
+ echo "Skills:"
98
+ for skill in commit self-check evaluate; do
99
+ if [ -d ".claude/skills/${skill}" ]; then
100
+ ok "/${skill}"
101
+ else
102
+ warn "Missing /${skill} skill (optional)"
103
+ fi
104
+ done
105
+
106
+ # 7. jq
107
+ echo ""
108
+ echo "Dependencies:"
109
+ if command -v jq &>/dev/null; then
110
+ ok "jq installed ($(jq --version 2>&1))"
111
+ else
112
+ warn "jq not installed — hooks use grep/sed fallback, recommend: brew install jq"
113
+ fi
114
+
115
+ # 8. CLAUDE.md
116
+ echo ""
117
+ echo "Project files:"
118
+ if [ -f "CLAUDE.md" ]; then
119
+ if grep -q "\[TODO\]" CLAUDE.md 2>/dev/null; then
120
+ warn "CLAUDE.md has unfilled [TODO] sections"
121
+ else
122
+ ok "CLAUDE.md"
123
+ fi
124
+ else
125
+ warn "No CLAUDE.md found"
126
+ fi
127
+
128
+ if [ -f "docs/progress.md" ]; then
129
+ ok "docs/progress.md"
130
+ else
131
+ warn "No docs/progress.md"
132
+ fi
133
+
134
+ # Summary
135
+ echo ""
136
+ echo "──────────────────────"
137
+ if [ "$ISSUES" -eq 0 ] && [ "$WARNINGS" -eq 0 ]; then
138
+ echo -e "${GREEN}All checks passed!${NC}"
139
+ elif [ "$ISSUES" -eq 0 ]; then
140
+ echo -e "${YELLOW}${WARNINGS} warning(s), no critical issues${NC}"
141
+ else
142
+ echo -e "${RED}${ISSUES} issue(s), ${WARNINGS} warning(s)${NC}"
143
+ echo "Run 'npx cc-discipline upgrade' to fix missing files."
144
+ fi
145
+ echo ""