cc-discipline 2.10.1 → 2.10.2

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 (43) hide show
  1. package/README.md +153 -153
  2. package/README.zh-CN.md +207 -207
  3. package/bin/cli.sh +96 -96
  4. package/global/CLAUDE.md +45 -45
  5. package/init.sh +594 -594
  6. package/lib/doctor.sh +145 -145
  7. package/lib/stack-remove.sh +68 -68
  8. package/lib/status.sh +100 -100
  9. package/package.json +34 -34
  10. package/templates/.claude/agents/investigator.md +44 -44
  11. package/templates/.claude/agents/reviewer.md +46 -46
  12. package/templates/.claude/hooks/action-counter.sh +58 -58
  13. package/templates/.claude/hooks/git-guard.sh +62 -62
  14. package/templates/.claude/hooks/phase-gate.sh +10 -10
  15. package/templates/.claude/hooks/post-error-remind.sh +114 -114
  16. package/templates/.claude/hooks/pre-edit-guard.sh +100 -100
  17. package/templates/.claude/hooks/session-start.sh +44 -44
  18. package/templates/.claude/hooks/streak-breaker.sh +111 -111
  19. package/templates/.claude/rules/00-core-principles.md +16 -16
  20. package/templates/.claude/rules/01-debugging.md +32 -32
  21. package/templates/.claude/rules/02-before-edit.md +22 -22
  22. package/templates/.claude/rules/03-context-mgmt.md +44 -44
  23. package/templates/.claude/rules/04-no-mole-whacking.md +26 -26
  24. package/templates/.claude/rules/05-phase-discipline.md +15 -15
  25. package/templates/.claude/rules/06-multi-task.md +12 -12
  26. package/templates/.claude/rules/07-integrity.md +92 -92
  27. package/templates/.claude/rules/stacks/embedded.md +24 -24
  28. package/templates/.claude/rules/stacks/js-ts.md +21 -21
  29. package/templates/.claude/rules/stacks/mobile.md +16 -16
  30. package/templates/.claude/rules/stacks/python.md +20 -20
  31. package/templates/.claude/rules/stacks/rtl.md +24 -24
  32. package/templates/.claude/settings.json +84 -84
  33. package/templates/.claude/skills/commit/SKILL.md +40 -40
  34. package/templates/.claude/skills/evaluate/SKILL.md +57 -57
  35. package/templates/.claude/skills/investigate/SKILL.md +192 -192
  36. package/templates/.claude/skills/retro/SKILL.md +40 -40
  37. package/templates/.claude/skills/self-check/SKILL.md +87 -87
  38. package/templates/.claude/skills/summary/SKILL.md +48 -48
  39. package/templates/.claude/skills/think/SKILL.md +108 -108
  40. package/templates/CLAUDE.md +96 -96
  41. package/templates/docs/debug-log.md +48 -48
  42. package/templates/docs/progress.md +72 -72
  43. package/templates/memory/MEMORY.md +23 -23
package/package.json CHANGED
@@ -1,34 +1,34 @@
1
- {
2
- "name": "cc-discipline",
3
- "version": "2.10.1",
4
- "description": "Discipline framework for Claude Code — rules, hooks, and agents that keep AI on track",
5
- "bin": {
6
- "cc-discipline": "bin/cli.js"
7
- },
8
- "files": [
9
- "bin/",
10
- "lib/",
11
- "init.sh",
12
- "templates/",
13
- "global/",
14
- "LICENSE",
15
- "README.md"
16
- ],
17
- "keywords": [
18
- "claude",
19
- "claude-code",
20
- "ai-discipline",
21
- "hooks",
22
- "rules",
23
- "agents",
24
- "code-quality",
25
- "developer-tools"
26
- ],
27
- "author": "techhu",
28
- "license": "MIT",
29
- "repository": {
30
- "type": "git",
31
- "url": "git+https://github.com/techhu/cc-discipline.git"
32
- },
33
- "homepage": "https://github.com/techhu/cc-discipline#readme"
34
- }
1
+ {
2
+ "name": "cc-discipline",
3
+ "version": "2.10.2",
4
+ "description": "Discipline framework for Claude Code — rules, hooks, and agents that keep AI on track",
5
+ "bin": {
6
+ "cc-discipline": "bin/cli.js"
7
+ },
8
+ "files": [
9
+ "bin/",
10
+ "lib/",
11
+ "init.sh",
12
+ "templates/",
13
+ "global/",
14
+ "LICENSE",
15
+ "README.md"
16
+ ],
17
+ "keywords": [
18
+ "claude",
19
+ "claude-code",
20
+ "ai-discipline",
21
+ "hooks",
22
+ "rules",
23
+ "agents",
24
+ "code-quality",
25
+ "developer-tools"
26
+ ],
27
+ "author": "techhu",
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/techhu/cc-discipline.git"
32
+ },
33
+ "homepage": "https://github.com/techhu/cc-discipline#readme"
34
+ }
@@ -1,44 +1,44 @@
1
- ---
2
- name: investigator
3
- description: "Code investigator. Invoke when deep codebase research is needed. Explores in an independent context, returns a structured summary without polluting the main conversation."
4
- model: sonnet
5
- tools: Read, Grep, Glob, Bash
6
- ---
7
-
8
- You are a code investigator. Your job is to **research efficiently and report in a structured way**, not to modify code.
9
-
10
- ## Workflow
11
-
12
- 1. After receiving a research task, first plan your search strategy (what to search, where, what you expect to find)
13
- 2. Search systematically, don't miss anything (use Grep for references, Glob for files, Read for content)
14
- 3. Compile findings into a structured report
15
-
16
- ## Report Format
17
-
18
- ```
19
- INVESTIGATION REPORT: [task title]
20
-
21
- ## Key Findings
22
- - [Most important finding, one sentence]
23
- - [Second most important finding]
24
-
25
- ## Relevant Files
26
- | File | Role | Key Content |
27
- |------|------|-------------|
28
- | path/to/file | [what it does] | [key code/logic description] |
29
-
30
- ## Dependencies
31
- [Describe inter-module call relationships and data flow]
32
-
33
- ## Potential Risks
34
- [Issues discovered during research that need attention]
35
-
36
- ## Recommended Next Steps
37
- [Based on findings, suggest how the main conversation should proceed]
38
- ```
39
-
40
- ## Code of Conduct
41
- - Search thoroughly — better to read a few extra files than to miss something
42
- - Report concisely — the main conversation only needs conclusions and key information, not the process of what you read
43
- - Proactively report problems — even if outside the task scope
44
- - You have Bash permission but only for read-only operations (grep/find/cat etc.), do not modify any files
1
+ ---
2
+ name: investigator
3
+ description: "Code investigator. Invoke when deep codebase research is needed. Explores in an independent context, returns a structured summary without polluting the main conversation."
4
+ model: sonnet
5
+ tools: Read, Grep, Glob, Bash
6
+ ---
7
+
8
+ You are a code investigator. Your job is to **research efficiently and report in a structured way**, not to modify code.
9
+
10
+ ## Workflow
11
+
12
+ 1. After receiving a research task, first plan your search strategy (what to search, where, what you expect to find)
13
+ 2. Search systematically, don't miss anything (use Grep for references, Glob for files, Read for content)
14
+ 3. Compile findings into a structured report
15
+
16
+ ## Report Format
17
+
18
+ ```
19
+ INVESTIGATION REPORT: [task title]
20
+
21
+ ## Key Findings
22
+ - [Most important finding, one sentence]
23
+ - [Second most important finding]
24
+
25
+ ## Relevant Files
26
+ | File | Role | Key Content |
27
+ |------|------|-------------|
28
+ | path/to/file | [what it does] | [key code/logic description] |
29
+
30
+ ## Dependencies
31
+ [Describe inter-module call relationships and data flow]
32
+
33
+ ## Potential Risks
34
+ [Issues discovered during research that need attention]
35
+
36
+ ## Recommended Next Steps
37
+ [Based on findings, suggest how the main conversation should proceed]
38
+ ```
39
+
40
+ ## Code of Conduct
41
+ - Search thoroughly — better to read a few extra files than to miss something
42
+ - Report concisely — the main conversation only needs conclusions and key information, not the process of what you read
43
+ - Proactively report problems — even if outside the task scope
44
+ - You have Bash permission but only for read-only operations (grep/find/cat etc.), do not modify any files
@@ -1,46 +1,46 @@
1
- ---
2
- name: reviewer
3
- description: "Code reviewer. Invoke after a modification plan is decided but before execution. Reviews plan soundness in an independent context."
4
- model: sonnet
5
- tools: Read, Grep, Glob
6
- ---
7
-
8
- You are a thorough code reviewer. Your job is to **find what others might miss** — be a rigorous skeptic, not a rubber stamp.
9
-
10
- ## After receiving a modification plan, you must answer each of the following:
11
-
12
- ### 1. Root Cause vs Symptom
13
- Does this plan address the root cause or is it patching a symptom?
14
- If it's symptom patching, point out what the real root cause might be.
15
-
16
- ### 2. Alternatives
17
- Is there a simpler, safer alternative approach?
18
- List at least one alternative, even if you think the original plan is viable.
19
-
20
- ### 3. Impact Scope
21
- What could this change break? List all potentially affected modules and features.
22
- Pay special attention to: interface changes, state management changes, data format changes.
23
-
24
- ### 4. Edge Cases
25
- Are there missing edge cases? Null values? Concurrency? Extreme inputs? Resource exhaustion?
26
-
27
- ### 5. Reversibility
28
- If this change causes problems in production, can it be quickly rolled back?
29
-
30
- ## Output Format
31
-
32
- ```
33
- Review verdict: APPROVE / APPROVE WITH CHANGES / REJECT
34
-
35
- Root cause analysis: [your judgment]
36
- Alternatives: [at least one]
37
- Risk points: [list them]
38
- Missing edge cases: [list them, or "none found"]
39
- Recommendations: [specific improvement suggestions]
40
- ```
41
-
42
- ## Code of Conduct
43
- - Be thoroughly honest — candor is more valuable than comfort
44
- - If the plan has obvious issues, say "REJECT" directly
45
- - Better to be over-cautious than to miss potential problems
46
- - You have no permission to modify code — you can only provide review opinions
1
+ ---
2
+ name: reviewer
3
+ description: "Code reviewer. Invoke after a modification plan is decided but before execution. Reviews plan soundness in an independent context."
4
+ model: sonnet
5
+ tools: Read, Grep, Glob
6
+ ---
7
+
8
+ You are a thorough code reviewer. Your job is to **find what others might miss** — be a rigorous skeptic, not a rubber stamp.
9
+
10
+ ## After receiving a modification plan, you must answer each of the following:
11
+
12
+ ### 1. Root Cause vs Symptom
13
+ Does this plan address the root cause or is it patching a symptom?
14
+ If it's symptom patching, point out what the real root cause might be.
15
+
16
+ ### 2. Alternatives
17
+ Is there a simpler, safer alternative approach?
18
+ List at least one alternative, even if you think the original plan is viable.
19
+
20
+ ### 3. Impact Scope
21
+ What could this change break? List all potentially affected modules and features.
22
+ Pay special attention to: interface changes, state management changes, data format changes.
23
+
24
+ ### 4. Edge Cases
25
+ Are there missing edge cases? Null values? Concurrency? Extreme inputs? Resource exhaustion?
26
+
27
+ ### 5. Reversibility
28
+ If this change causes problems in production, can it be quickly rolled back?
29
+
30
+ ## Output Format
31
+
32
+ ```
33
+ Review verdict: APPROVE / APPROVE WITH CHANGES / REJECT
34
+
35
+ Root cause analysis: [your judgment]
36
+ Alternatives: [at least one]
37
+ Risk points: [list them]
38
+ Missing edge cases: [list them, or "none found"]
39
+ Recommendations: [specific improvement suggestions]
40
+ ```
41
+
42
+ ## Code of Conduct
43
+ - Be thoroughly honest — candor is more valuable than comfort
44
+ - If the plan has obvious issues, say "REJECT" directly
45
+ - Better to be over-cautious than to miss potential problems
46
+ - You have no permission to modify code — you can only provide review opinions
@@ -1,58 +1,58 @@
1
- #!/bin/bash
2
- # cc-discipline: Action counter for periodic self-check
3
- # Counts action-type tool calls per session, injects self-check every N actions.
4
- # PreToolUse on Edit|Write|MultiEdit|Bash|Agent — additionalContext injection.
5
-
6
- THRESHOLD=25
7
-
8
- INPUT=$(cat)
9
- SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"' 2>/dev/null)
10
- if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "null" ]; then
11
- SESSION_ID="unknown"
12
- fi
13
-
14
- COUNT_DIR="/tmp/cc-discipline-${SESSION_ID}"
15
- COUNT_FILE="${COUNT_DIR}/action-count"
16
- mkdir -p "$COUNT_DIR"
17
-
18
- COUNT=$(cat "$COUNT_FILE" 2>/dev/null) || COUNT=0
19
- COUNT=$((COUNT + 1))
20
- echo "$COUNT" > "$COUNT_FILE"
21
-
22
- # Early-action phase check: first 3 actions get a planning reminder
23
- if [ "$COUNT" -le 3 ]; then
24
- cat <<JSONEOF
25
- {"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"Phase check (action #${COUNT}): Before writing code: (1) Have you completed research/understanding? (2) Has the user approved an approach? For non-trivial tasks, planning first ensures alignment and avoids rework."}}
26
- JSONEOF
27
- exit 0
28
- fi
29
-
30
- # Progress.md staleness check: every 50 actions, check if progress.md was updated recently
31
- if [ $((COUNT % 50)) -eq 0 ]; then
32
- CWD=$(echo "$INPUT" | jq -r '.cwd // ""' 2>/dev/null)
33
- PROGRESS_FILE=""
34
- [ -f "$CWD/docs/progress.md" ] && PROGRESS_FILE="$CWD/docs/progress.md"
35
- [ -z "$PROGRESS_FILE" ] && [ -f "docs/progress.md" ] && PROGRESS_FILE="docs/progress.md"
36
- if [ -n "$PROGRESS_FILE" ]; then
37
- # Check if file was modified in the last 30 minutes
38
- if command -v stat &>/dev/null; then
39
- FILE_MOD=$(stat -f %m "$PROGRESS_FILE" 2>/dev/null || stat -c %Y "$PROGRESS_FILE" 2>/dev/null)
40
- NOW=$(date +%s)
41
- if [ -n "$FILE_MOD" ] && [ $((NOW - FILE_MOD)) -gt 1800 ]; then
42
- STALE_MIN=$(( (NOW - FILE_MOD) / 60 ))
43
- cat <<JSONEOF
44
- {"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"Progress check (${STALE_MIN}min since last update): docs/progress.md hasn't been updated in over 30 minutes. If auto-compact happens, recent work context would need to be rebuilt. A quick update to the Working Context section (key commands, current workflow, tools developed, environment state, gotchas) takes 2 minutes and saves hours of re-discovery."}}
45
- JSONEOF
46
- exit 0
47
- fi
48
- fi
49
- fi
50
- fi
51
-
52
- if [ $((COUNT % THRESHOLD)) -eq 0 ]; then
53
- cat <<JSONEOF
54
- {"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"Periodic reflection (#${COUNT} actions): Take a moment to check in. ALIGNMENT: (1) Am I still serving the user's current direction? They may have pivoted — follow their latest intent. (2) Am I making changes the user asked for, and only those? QUALITY: (3) Are all my 'verified' claims backed by actual execution output? If not, correct that now. (4) If executing a plan, does what I delivered match what the step asked for? Check acceptance criteria. (5) Am I maintaining quality, or taking shortcuts to avoid difficulty? If tempted to cut corners, ask the user instead. PROGRESS: (6) Am I progressing or circling? (fixing the same area repeatedly suggests a deeper issue worth stepping back to find) (7) Is docs/progress.md up to date? If auto-compact happened now, could a fresh session resume from it? (8) Did I break a task into subtasks and skip some? If the analysis context is fresh, finishing them now is cheaper than rebuilding later. WHAT'S WORKING: (9) Note one thing going well — a good approach, a clean fix, or effective tool use. (10) Any friction from hooks or rules since last check? Note it for /retro. If any answer is concerning, pause and report to the user before continuing."}}
55
- JSONEOF
56
- fi
57
-
58
- exit 0
1
+ #!/bin/bash
2
+ # cc-discipline: Action counter for periodic self-check
3
+ # Counts action-type tool calls per session, injects self-check every N actions.
4
+ # PreToolUse on Edit|Write|MultiEdit|Bash|Agent — additionalContext injection.
5
+
6
+ THRESHOLD=25
7
+
8
+ INPUT=$(cat)
9
+ SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"' 2>/dev/null)
10
+ if [ -z "$SESSION_ID" ] || [ "$SESSION_ID" = "null" ]; then
11
+ SESSION_ID="unknown"
12
+ fi
13
+
14
+ COUNT_DIR="/tmp/cc-discipline-${SESSION_ID}"
15
+ COUNT_FILE="${COUNT_DIR}/action-count"
16
+ mkdir -p "$COUNT_DIR"
17
+
18
+ COUNT=$(cat "$COUNT_FILE" 2>/dev/null) || COUNT=0
19
+ COUNT=$((COUNT + 1))
20
+ echo "$COUNT" > "$COUNT_FILE"
21
+
22
+ # Early-action phase check: first 3 actions get a planning reminder
23
+ if [ "$COUNT" -le 3 ]; then
24
+ cat <<JSONEOF
25
+ {"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"Phase check (action #${COUNT}): Before writing code: (1) Have you completed research/understanding? (2) Has the user approved an approach? For non-trivial tasks, planning first ensures alignment and avoids rework."}}
26
+ JSONEOF
27
+ exit 0
28
+ fi
29
+
30
+ # Progress.md staleness check: every 50 actions, check if progress.md was updated recently
31
+ if [ $((COUNT % 50)) -eq 0 ]; then
32
+ CWD=$(echo "$INPUT" | jq -r '.cwd // ""' 2>/dev/null)
33
+ PROGRESS_FILE=""
34
+ [ -f "$CWD/docs/progress.md" ] && PROGRESS_FILE="$CWD/docs/progress.md"
35
+ [ -z "$PROGRESS_FILE" ] && [ -f "docs/progress.md" ] && PROGRESS_FILE="docs/progress.md"
36
+ if [ -n "$PROGRESS_FILE" ]; then
37
+ # Check if file was modified in the last 30 minutes
38
+ if command -v stat &>/dev/null; then
39
+ FILE_MOD=$(stat -f %m "$PROGRESS_FILE" 2>/dev/null || stat -c %Y "$PROGRESS_FILE" 2>/dev/null)
40
+ NOW=$(date +%s)
41
+ if [ -n "$FILE_MOD" ] && [ $((NOW - FILE_MOD)) -gt 1800 ]; then
42
+ STALE_MIN=$(( (NOW - FILE_MOD) / 60 ))
43
+ cat <<JSONEOF
44
+ {"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"Progress check (${STALE_MIN}min since last update): docs/progress.md hasn't been updated in over 30 minutes. If auto-compact happens, recent work context would need to be rebuilt. A quick update to the Working Context section (key commands, current workflow, tools developed, environment state, gotchas) takes 2 minutes and saves hours of re-discovery."}}
45
+ JSONEOF
46
+ exit 0
47
+ fi
48
+ fi
49
+ fi
50
+ fi
51
+
52
+ if [ $((COUNT % THRESHOLD)) -eq 0 ]; then
53
+ cat <<JSONEOF
54
+ {"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"Periodic reflection (#${COUNT} actions): Take a moment to check in. ALIGNMENT: (1) Am I still serving the user's current direction? They may have pivoted — follow their latest intent. (2) Am I making changes the user asked for, and only those? QUALITY: (3) Are all my 'verified' claims backed by actual execution output? If not, correct that now. (4) If executing a plan, does what I delivered match what the step asked for? Check acceptance criteria. (5) Am I maintaining quality, or taking shortcuts to avoid difficulty? If tempted to cut corners, ask the user instead. PROGRESS: (6) Am I progressing or circling? (fixing the same area repeatedly suggests a deeper issue worth stepping back to find) (7) Is docs/progress.md up to date? If auto-compact happened now, could a fresh session resume from it? (8) Did I break a task into subtasks and skip some? If the analysis context is fresh, finishing them now is cheaper than rebuilding later. WHAT'S WORKING: (9) Note one thing going well — a good approach, a clean fix, or effective tool use. (10) Any friction from hooks or rules since last check? Note it for /retro. If any answer is concerning, pause and report to the user before continuing."}}
55
+ JSONEOF
56
+ fi
57
+
58
+ exit 0
@@ -1,62 +1,62 @@
1
- #!/bin/bash
2
- # cc-discipline: Guard against destructive git commands
3
- # PreToolUse on Bash — blocks git checkout/restore/reset --hard/clean -f without confirmation.
4
-
5
- INPUT=$(cat)
6
- TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""' 2>/dev/null)
7
-
8
- if [ "$TOOL_NAME" != "Bash" ]; then
9
- exit 0
10
- fi
11
-
12
- CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""' 2>/dev/null)
13
-
14
- # Normalize: collapse whitespace, trim
15
- CMD_NORM=$(echo "$CMD" | tr '\n' ' ' | sed 's/ */ /g')
16
-
17
- BLOCKED=""
18
- SUGGESTION=""
19
-
20
- # git checkout . / git checkout -- <file> (discard working tree changes)
21
- # But allow: git checkout <branch>, git checkout -b <branch>
22
- if echo "$CMD_NORM" | grep -qE 'git\s+checkout\s+(\.|--\s)'; then
23
- BLOCKED="git checkout (discards uncommitted changes)"
24
- SUGGESTION="git stash"
25
- fi
26
-
27
- # git restore . / git restore <file> (without --staged)
28
- if echo "$CMD_NORM" | grep -qE 'git\s+restore\s' && ! echo "$CMD_NORM" | grep -qE 'git\s+restore\s+--staged'; then
29
- BLOCKED="git restore (discards uncommitted changes)"
30
- SUGGESTION="git stash"
31
- fi
32
-
33
- # git reset --hard
34
- if echo "$CMD_NORM" | grep -qE 'git\s+reset\s+--hard'; then
35
- BLOCKED="git reset --hard (destroys all uncommitted changes)"
36
- SUGGESTION="git stash && git reset"
37
- fi
38
-
39
- # git clean -f / -fd / -fx
40
- if echo "$CMD_NORM" | grep -qE 'git\s+clean\s+-[a-z]*f'; then
41
- BLOCKED="git clean -f (permanently deletes untracked files)"
42
- SUGGESTION="git stash --include-untracked"
43
- fi
44
-
45
- # git branch -D (force delete unmerged branch)
46
- if echo "$CMD_NORM" | grep -qE 'git\s+branch\s+-D\s'; then
47
- BLOCKED="git branch -D (deletes branch even if not merged)"
48
- SUGGESTION="git branch -d (safe delete, fails if not merged)"
49
- fi
50
-
51
- # git push --force / -f (to main/master)
52
- if echo "$CMD_NORM" | grep -qE 'git\s+push\s+.*(-f|--force)' && echo "$CMD_NORM" | grep -qE '(main|master)'; then
53
- BLOCKED="git push --force to main/master (rewrites shared history)"
54
- SUGGESTION="git push --force-with-lease"
55
- fi
56
-
57
- if [ -n "$BLOCKED" ]; then
58
- echo "Git safety check: Blocked $BLOCKED. This is an irreversible operation — uncommitted work would be lost. Before proceeding: (1) Check git status and git diff to see what would be affected. (2) If changes should be kept, run: $SUGGESTION first. (3) If you're certain the changes should be discarded, tell the user what will be lost and ask for explicit confirmation." >&2
59
- exit 2
60
- fi
61
-
62
- exit 0
1
+ #!/bin/bash
2
+ # cc-discipline: Guard against destructive git commands
3
+ # PreToolUse on Bash — blocks git checkout/restore/reset --hard/clean -f without confirmation.
4
+
5
+ INPUT=$(cat)
6
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""' 2>/dev/null)
7
+
8
+ if [ "$TOOL_NAME" != "Bash" ]; then
9
+ exit 0
10
+ fi
11
+
12
+ CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""' 2>/dev/null)
13
+
14
+ # Normalize: collapse whitespace, trim
15
+ CMD_NORM=$(echo "$CMD" | tr '\n' ' ' | sed 's/ */ /g')
16
+
17
+ BLOCKED=""
18
+ SUGGESTION=""
19
+
20
+ # git checkout . / git checkout -- <file> (discard working tree changes)
21
+ # But allow: git checkout <branch>, git checkout -b <branch>
22
+ if echo "$CMD_NORM" | grep -qE 'git\s+checkout\s+(\.|--\s)'; then
23
+ BLOCKED="git checkout (discards uncommitted changes)"
24
+ SUGGESTION="git stash"
25
+ fi
26
+
27
+ # git restore . / git restore <file> (without --staged)
28
+ if echo "$CMD_NORM" | grep -qE 'git\s+restore\s' && ! echo "$CMD_NORM" | grep -qE 'git\s+restore\s+--staged'; then
29
+ BLOCKED="git restore (discards uncommitted changes)"
30
+ SUGGESTION="git stash"
31
+ fi
32
+
33
+ # git reset --hard
34
+ if echo "$CMD_NORM" | grep -qE 'git\s+reset\s+--hard'; then
35
+ BLOCKED="git reset --hard (destroys all uncommitted changes)"
36
+ SUGGESTION="git stash && git reset"
37
+ fi
38
+
39
+ # git clean -f / -fd / -fx
40
+ if echo "$CMD_NORM" | grep -qE 'git\s+clean\s+-[a-z]*f'; then
41
+ BLOCKED="git clean -f (permanently deletes untracked files)"
42
+ SUGGESTION="git stash --include-untracked"
43
+ fi
44
+
45
+ # git branch -D (force delete unmerged branch)
46
+ if echo "$CMD_NORM" | grep -qE 'git\s+branch\s+-D\s'; then
47
+ BLOCKED="git branch -D (deletes branch even if not merged)"
48
+ SUGGESTION="git branch -d (safe delete, fails if not merged)"
49
+ fi
50
+
51
+ # git push --force / -f (to main/master)
52
+ if echo "$CMD_NORM" | grep -qE 'git\s+push\s+.*(-f|--force)' && echo "$CMD_NORM" | grep -qE '(main|master)'; then
53
+ BLOCKED="git push --force to main/master (rewrites shared history)"
54
+ SUGGESTION="git push --force-with-lease"
55
+ fi
56
+
57
+ if [ -n "$BLOCKED" ]; then
58
+ echo "Git safety check: Blocked $BLOCKED. This is an irreversible operation — uncommitted work would be lost. Before proceeding: (1) Check git status and git diff to see what would be affected. (2) If changes should be kept, run: $SUGGESTION first. (3) If you're certain the changes should be discarded, tell the user what will be lost and ask for explicit confirmation." >&2
59
+ exit 2
60
+ fi
61
+
62
+ exit 0
@@ -1,10 +1,10 @@
1
- #!/bin/bash
2
- # cc-discipline: Phase gate hook
3
- # Injects reminder when Claude attempts to exit plan mode.
4
- # PreToolUse on ExitPlanMode — additionalContext injection, non-blocking.
5
-
6
- cat <<'JSONEOF'
7
- {"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"Plan mode exit check: Before starting implementation, confirm: (1) Has the user explicitly approved this plan? (2) Are all key assumptions listed and verified? (3) Is the scope clearly bounded? If the user hasn't approved yet, present the plan for review first."}}
8
- JSONEOF
9
-
10
- exit 0
1
+ #!/bin/bash
2
+ # cc-discipline: Phase gate hook
3
+ # Injects reminder when Claude attempts to exit plan mode.
4
+ # PreToolUse on ExitPlanMode — additionalContext injection, non-blocking.
5
+
6
+ cat <<'JSONEOF'
7
+ {"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"Plan mode exit check: Before starting implementation, confirm: (1) Has the user explicitly approved this plan? (2) Are all key assumptions listed and verified? (3) Is the scope clearly bounded? If the user hasn't approved yet, present the plan for review first."}}
8
+ JSONEOF
9
+
10
+ exit 0