codebyplan 1.5.1 → 1.8.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 (205) hide show
  1. package/dist/cli.js +4462 -748
  2. package/package.json +5 -1
  3. package/templates/.gitkeep +0 -0
  4. package/templates/README.md +20 -0
  5. package/templates/agents/cbp-cc-executor.md +213 -0
  6. package/templates/agents/cbp-database-agent.md +229 -0
  7. package/templates/agents/cbp-improve-claude.md +245 -0
  8. package/templates/agents/cbp-improve-round.md +284 -0
  9. package/templates/agents/cbp-mechanical-edits.md +111 -0
  10. package/templates/agents/cbp-research.md +282 -0
  11. package/templates/agents/cbp-round-executor.md +604 -0
  12. package/templates/agents/cbp-security-agent.md +134 -0
  13. package/templates/agents/cbp-task-check.md +213 -0
  14. package/templates/agents/cbp-task-planner.md +582 -0
  15. package/templates/agents/cbp-test-e2e-agent.md +363 -0
  16. package/templates/agents/cbp-testing-qa-agent.md +400 -0
  17. package/templates/context/mcp-docs.md +139 -0
  18. package/templates/hooks/README.md +236 -0
  19. package/templates/hooks/cbp-auto-test-hooks.sh +44 -0
  20. package/templates/hooks/cbp-lint-format-on-edit.sh +159 -0
  21. package/templates/hooks/cbp-maestro-yaml-validate.sh +100 -0
  22. package/templates/hooks/cbp-mcp-migration-guard.sh +32 -0
  23. package/templates/hooks/cbp-mcp-round-sync.sh +79 -0
  24. package/templates/hooks/cbp-mcp-worktree-inject.sh +76 -0
  25. package/templates/hooks/cbp-notify.sh +68 -0
  26. package/templates/hooks/cbp-plugin-dispatch.sh +29 -0
  27. package/templates/hooks/cbp-pre-commit-quality-gate.sh +204 -0
  28. package/templates/hooks/cbp-statusline.sh +347 -0
  29. package/templates/hooks/cbp-subagent-statusline.sh +182 -0
  30. package/templates/hooks/cbp-test-coverage-gate.sh +144 -0
  31. package/templates/hooks/cbp-test-hooks.sh +320 -0
  32. package/templates/hooks/hooks.json +85 -0
  33. package/templates/hooks/validate-context-usage.sh +59 -0
  34. package/templates/hooks/validate-git-commit.sh +78 -0
  35. package/templates/hooks/validate-git-stash-deny.sh +32 -0
  36. package/templates/hooks/validate-structure-lengths.sh +57 -0
  37. package/templates/hooks/validate-structure-lib.sh +104 -0
  38. package/templates/hooks/validate-structure-patterns.sh +54 -0
  39. package/templates/hooks/validate-structure-scope.sh +33 -0
  40. package/templates/hooks/validate-structure-smoke.sh +95 -0
  41. package/templates/hooks/validate-structure-templates.sh +34 -0
  42. package/templates/hooks/validate-structure.sh +69 -0
  43. package/templates/rules/.gitkeep +0 -0
  44. package/templates/rules/README.md +47 -0
  45. package/templates/rules/context-file-loading.md +52 -0
  46. package/templates/rules/scope-vocabulary.md +64 -0
  47. package/templates/rules/todo-backend.md +109 -0
  48. package/templates/settings.project.base.json +55 -0
  49. package/templates/settings.user.base.json +25 -0
  50. package/templates/skills/cbp-build-cc-agent/SKILL.md +139 -0
  51. package/templates/skills/cbp-build-cc-agent/examples/read-only-reviewer.md +32 -0
  52. package/templates/skills/cbp-build-cc-agent/examples/with-hooks.md +41 -0
  53. package/templates/skills/cbp-build-cc-agent/examples/with-skills-preload.md +25 -0
  54. package/templates/skills/cbp-build-cc-agent/reference/cbp-quality.md +153 -0
  55. package/templates/skills/cbp-build-cc-agent/reference/frontmatter-fields.md +37 -0
  56. package/templates/skills/cbp-build-cc-agent/reference/permission-modes.md +18 -0
  57. package/templates/skills/cbp-build-cc-agent/scripts/validate-agent.sh +67 -0
  58. package/templates/skills/cbp-build-cc-agent/templates/agent.md +66 -0
  59. package/templates/skills/cbp-build-cc-claude-file/SKILL.md +178 -0
  60. package/templates/skills/cbp-build-cc-claude-file/examples/minimal-project.md +33 -0
  61. package/templates/skills/cbp-build-cc-claude-file/examples/monorepo-with-imports.md +39 -0
  62. package/templates/skills/cbp-build-cc-claude-file/reference/imports.md +72 -0
  63. package/templates/skills/cbp-build-cc-claude-file/reference/what-belongs.md +39 -0
  64. package/templates/skills/cbp-build-cc-claude-file/templates/project-claude-md.md +48 -0
  65. package/templates/skills/cbp-build-cc-claude-file/templates/user-claude-md.md +22 -0
  66. package/templates/skills/cbp-build-cc-memory/SKILL.md +201 -0
  67. package/templates/skills/cbp-build-cc-memory/examples/feedback-memory.md +11 -0
  68. package/templates/skills/cbp-build-cc-memory/examples/project-memory.md +11 -0
  69. package/templates/skills/cbp-build-cc-memory/examples/reference-memory.md +13 -0
  70. package/templates/skills/cbp-build-cc-memory/examples/user-memory.md +14 -0
  71. package/templates/skills/cbp-build-cc-memory/reference/memory-types.md +59 -0
  72. package/templates/skills/cbp-build-cc-memory/reference/when-to-save.md +62 -0
  73. package/templates/skills/cbp-build-cc-memory/templates/MEMORY-index.md +4 -0
  74. package/templates/skills/cbp-build-cc-memory/templates/memory-entry.md +15 -0
  75. package/templates/skills/cbp-build-cc-mode/SKILL.md +99 -0
  76. package/templates/skills/cbp-build-cc-rule/SKILL.md +176 -0
  77. package/templates/skills/cbp-build-cc-rule/examples/global-rule.md +19 -0
  78. package/templates/skills/cbp-build-cc-rule/examples/scoped-rule.md +41 -0
  79. package/templates/skills/cbp-build-cc-rule/reference/paths-patterns.md +48 -0
  80. package/templates/skills/cbp-build-cc-rule/templates/rule.md +32 -0
  81. package/templates/skills/cbp-build-cc-settings/SKILL.md +220 -0
  82. package/templates/skills/cbp-build-cc-settings/examples/hooks-config.json +64 -0
  83. package/templates/skills/cbp-build-cc-settings/examples/permissions-config.json +34 -0
  84. package/templates/skills/cbp-build-cc-settings/examples/sandbox-config.json +42 -0
  85. package/templates/skills/cbp-build-cc-settings/reference/cbp-conventions.md +104 -0
  86. package/templates/skills/cbp-build-cc-settings/reference/permission-rules.md +61 -0
  87. package/templates/skills/cbp-build-cc-settings/reference/scope-precedence.md +73 -0
  88. package/templates/skills/cbp-build-cc-settings/reference/settings-fields.md +166 -0
  89. package/templates/skills/cbp-build-cc-settings/templates/settings.json +23 -0
  90. package/templates/skills/cbp-build-cc-settings/templates/settings.local.json +10 -0
  91. package/templates/skills/cbp-build-cc-skill/SKILL.md +154 -0
  92. package/templates/skills/cbp-build-cc-skill/examples/dynamic-context.md +31 -0
  93. package/templates/skills/cbp-build-cc-skill/examples/fork-skill.md +22 -0
  94. package/templates/skills/cbp-build-cc-skill/examples/knowledge-skill.md +25 -0
  95. package/templates/skills/cbp-build-cc-skill/examples/task-skill.md +29 -0
  96. package/templates/skills/cbp-build-cc-skill/reference/cbp-quality.md +157 -0
  97. package/templates/skills/cbp-build-cc-skill/reference/frontmatter-fields.md +35 -0
  98. package/templates/skills/cbp-build-cc-skill/reference/string-substitutions.md +60 -0
  99. package/templates/skills/cbp-build-cc-skill/scripts/validate-skill.sh +90 -0
  100. package/templates/skills/cbp-build-cc-skill/templates/skill.md +51 -0
  101. package/templates/skills/cbp-checkpoint-check/SKILL.md +156 -0
  102. package/templates/skills/cbp-checkpoint-complete/SKILL.md +109 -0
  103. package/templates/skills/cbp-checkpoint-create/SKILL.md +287 -0
  104. package/templates/skills/cbp-checkpoint-end/SKILL.md +241 -0
  105. package/templates/skills/cbp-checkpoint-update/SKILL.md +115 -0
  106. package/templates/skills/cbp-frontend-a11y/SKILL.md +109 -0
  107. package/templates/skills/cbp-frontend-a11y/reference/aria-roles-states.md +130 -0
  108. package/templates/skills/cbp-frontend-a11y/reference/contrast-visual.md +122 -0
  109. package/templates/skills/cbp-frontend-a11y/reference/keyboard-patterns.md +154 -0
  110. package/templates/skills/cbp-frontend-a11y/reference/semantic-html.md +111 -0
  111. package/templates/skills/cbp-frontend-design/SKILL.md +145 -0
  112. package/templates/skills/cbp-frontend-design/reference/nextjs-scss.md +118 -0
  113. package/templates/skills/cbp-frontend-design/reference/rn-expo.md +101 -0
  114. package/templates/skills/cbp-frontend-design/reference/tauri-react.md +82 -0
  115. package/templates/skills/cbp-frontend-ui/SKILL.md +262 -0
  116. package/templates/skills/cbp-frontend-ui/reference/ui-label-maps.md +42 -0
  117. package/templates/skills/cbp-frontend-ui/reference/ui-layout-patterns.md +105 -0
  118. package/templates/skills/cbp-frontend-ui/reference/variant-defaults.md +149 -0
  119. package/templates/skills/cbp-frontend-ux/SKILL.md +181 -0
  120. package/templates/skills/cbp-git-branch-feat-create/SKILL.md +115 -0
  121. package/templates/skills/cbp-git-commit/SKILL.md +278 -0
  122. package/templates/skills/cbp-git-worktree-create/SKILL.md +226 -0
  123. package/templates/skills/cbp-git-worktree-remove/SKILL.md +145 -0
  124. package/templates/skills/cbp-merge-main/SKILL.md +228 -0
  125. package/templates/skills/cbp-round-check/SKILL.md +104 -0
  126. package/templates/skills/cbp-round-end/SKILL.md +183 -0
  127. package/templates/skills/cbp-round-end/reference/findings-presentation.md +44 -0
  128. package/templates/skills/cbp-round-end/reference/inline-fallback.md +35 -0
  129. package/templates/skills/cbp-round-execute/SKILL.md +211 -0
  130. package/templates/skills/cbp-round-execute/reference/inline-fallback.md +59 -0
  131. package/templates/skills/cbp-round-input/SKILL.md +165 -0
  132. package/templates/skills/cbp-round-start/SKILL.md +222 -0
  133. package/templates/skills/cbp-round-update/SKILL.md +163 -0
  134. package/templates/skills/cbp-session-end/SKILL.md +187 -0
  135. package/templates/skills/cbp-session-start/SKILL.md +155 -0
  136. package/templates/skills/cbp-ship/SKILL.md +332 -0
  137. package/templates/skills/cbp-ship/reference/changesets-overview.md +120 -0
  138. package/templates/skills/cbp-ship/reference/eas-cli-overview.md +60 -0
  139. package/templates/skills/cbp-ship/reference/gh-cli-overview.md +135 -0
  140. package/templates/skills/cbp-ship/reference/gh-cli-shipment-commands.md +283 -0
  141. package/templates/skills/cbp-ship/reference/npm-publish-monorepo.md +252 -0
  142. package/templates/skills/cbp-ship/reference/npm-publish-oidc-trusted.md +157 -0
  143. package/templates/skills/cbp-ship/reference/npm-publish-overview.md +171 -0
  144. package/templates/skills/cbp-ship/reference/preflight-checklist.md +88 -0
  145. package/templates/skills/cbp-ship/reference/railway-nestjs-deployment.md +169 -0
  146. package/templates/skills/cbp-ship/reference/railway-overview.md +120 -0
  147. package/templates/skills/cbp-ship/reference/railway-troubleshooting.md +168 -0
  148. package/templates/skills/cbp-ship/reference/release-please-overview.md +99 -0
  149. package/templates/skills/cbp-ship/reference/surface-expo-eas.md +155 -0
  150. package/templates/skills/cbp-ship/reference/surface-npm.md +180 -0
  151. package/templates/skills/cbp-ship/reference/surface-railway.md +152 -0
  152. package/templates/skills/cbp-ship/reference/surface-supabase.md +178 -0
  153. package/templates/skills/cbp-ship/reference/surface-tauri.md +138 -0
  154. package/templates/skills/cbp-ship/reference/surface-vercel.md +124 -0
  155. package/templates/skills/cbp-ship/reference/surface-vscode-ext.md +144 -0
  156. package/templates/skills/cbp-ship/reference/surfaces.md +60 -0
  157. package/templates/skills/cbp-ship/reference/testflight-automation.md +215 -0
  158. package/templates/skills/cbp-ship/reference/testflight-internal-vs-external.md +69 -0
  159. package/templates/skills/cbp-ship/reference/testflight-overview.md +98 -0
  160. package/templates/skills/cbp-ship/reference/versioning.md +116 -0
  161. package/templates/skills/cbp-ship/scripts/detect-surfaces.sh +217 -0
  162. package/templates/skills/cbp-ship/scripts/verify-expo-eas.sh +35 -0
  163. package/templates/skills/cbp-ship/scripts/verify-npm.sh +21 -0
  164. package/templates/skills/cbp-ship/scripts/verify-railway.sh +41 -0
  165. package/templates/skills/cbp-ship/scripts/verify-supabase.sh +19 -0
  166. package/templates/skills/cbp-ship/scripts/verify-tauri.sh +24 -0
  167. package/templates/skills/cbp-ship/scripts/verify-vercel.sh +32 -0
  168. package/templates/skills/cbp-ship/scripts/verify-vscode-ext.sh +25 -0
  169. package/templates/skills/cbp-ship/templates/eas.json +66 -0
  170. package/templates/skills/cbp-ship/templates/railway.toml +15 -0
  171. package/templates/skills/cbp-ship/templates/release-please-config.json +17 -0
  172. package/templates/skills/cbp-ship/templates/vercel.json +19 -0
  173. package/templates/skills/cbp-ship/templates/vscodeignore +21 -0
  174. package/templates/skills/cbp-ship/templates/workflow-changesets.yml +41 -0
  175. package/templates/skills/cbp-ship/templates/workflow-eas-submit.yml +53 -0
  176. package/templates/skills/cbp-ship/templates/workflow-npm-publish.yml +36 -0
  177. package/templates/skills/cbp-ship/templates/workflow-release-please.yml +21 -0
  178. package/templates/skills/cbp-ship/templates/workflow-tauri-release.yml +69 -0
  179. package/templates/skills/cbp-ship/templates/workflow-vsce-publish.yml +31 -0
  180. package/templates/skills/cbp-ship-configure/SKILL.md +296 -0
  181. package/templates/skills/cbp-ship-configure/reference/expo-mobile.md +204 -0
  182. package/templates/skills/cbp-ship-configure/reference/npm-package.md +165 -0
  183. package/templates/skills/cbp-ship-configure/reference/railway-backend.md +199 -0
  184. package/templates/skills/cbp-ship-configure/reference/supabase.md +200 -0
  185. package/templates/skills/cbp-ship-configure/reference/tauri-desktop.md +181 -0
  186. package/templates/skills/cbp-ship-configure/reference/vercel.md +117 -0
  187. package/templates/skills/cbp-ship-configure/reference/vscode-ext.md +155 -0
  188. package/templates/skills/cbp-ship-main/SKILL.md +65 -0
  189. package/templates/skills/cbp-supabase-branch-check/SKILL.md +337 -0
  190. package/templates/skills/cbp-supabase-branch-check/reference/dag-steps.md +29 -0
  191. package/templates/skills/cbp-supabase-migrate/SKILL.md +314 -0
  192. package/templates/skills/cbp-supabase-migrate/reference/advisor-triage.md +70 -0
  193. package/templates/skills/cbp-supabase-migrate/reference/cli-fallback.md +87 -0
  194. package/templates/skills/cbp-supabase-migrate/reference/preflight-dry-run.md +58 -0
  195. package/templates/skills/cbp-supabase-setup/SKILL.md +239 -0
  196. package/templates/skills/cbp-supabase-setup/reference/branching-setup.md +121 -0
  197. package/templates/skills/cbp-supabase-setup/reference/cli-fallback.md +109 -0
  198. package/templates/skills/cbp-task-check/SKILL.md +166 -0
  199. package/templates/skills/cbp-task-complete/SKILL.md +206 -0
  200. package/templates/skills/cbp-task-complete/reference/checkpoint-done-branching.md +48 -0
  201. package/templates/skills/cbp-task-complete/reference/next-step-heuristic.md +56 -0
  202. package/templates/skills/cbp-task-create/SKILL.md +167 -0
  203. package/templates/skills/cbp-task-start/SKILL.md +239 -0
  204. package/templates/skills/cbp-task-testing/SKILL.md +277 -0
  205. package/templates/skills/cbp-todo/SKILL.md +97 -0
@@ -0,0 +1,76 @@
1
+ #!/bin/bash
2
+ # @scope: org-shared
3
+ # Hook: PreToolUse mcp__codebyplan__(update_task|complete_task|complete_round|update_checkpoint)
4
+ # Purpose: Auto-inject caller_worktree_id into MCP mutation calls when not already
5
+ # present. Uses the PreToolUse hookSpecificOutput.updatedInput contract
6
+ # (Claude Code v2.1 — see hooks.md "PreToolUse decision control"):
7
+ # - Output JSON with hookSpecificOutput.permissionDecision="allow" and
8
+ # hookSpecificOutput.updatedInput containing the full modified tool_input.
9
+ # This hook NEVER exits non-zero — it is a no-op on all failure paths.
10
+ #
11
+ # Fallback chain:
12
+ # 1. caller_worktree_id already present in tool_input → passthrough (no-op)
13
+ # 2. Primary: npx codebyplan resolve-worktree → UUID found → inject
14
+ # 3. Secondary: npx codebyplan resolve-worktree --fallback-from-branch → UUID found → inject
15
+ # 4. Both empty → passthrough (server pre-guard skips when absent)
16
+ #
17
+ # NEVER exit non-zero — backwards-compat passthrough when resolver is broken.
18
+
19
+ INPUT=$(cat)
20
+
21
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
22
+
23
+ # Only intercept matching MCP mutation tools
24
+ case "$TOOL_NAME" in
25
+ mcp__codebyplan__update_task|\
26
+ mcp__codebyplan__complete_task|\
27
+ mcp__codebyplan__complete_round|\
28
+ mcp__codebyplan__update_checkpoint) ;;
29
+ *) exit 0 ;;
30
+ esac
31
+
32
+ # If caller_worktree_id is already present, pass through unchanged
33
+ EXISTING=$(echo "$INPUT" | jq -r '.tool_input.caller_worktree_id // empty' 2>/dev/null)
34
+ if [ -n "$EXISTING" ]; then
35
+ exit 0
36
+ fi
37
+
38
+ # Try primary resolver
39
+ UUID=$(npx --yes codebyplan resolve-worktree 2>/dev/null)
40
+
41
+ # Try fallback if primary returned empty
42
+ if [ -z "$UUID" ]; then
43
+ UUID=$(npx --yes codebyplan resolve-worktree --fallback-from-branch 2>/dev/null)
44
+ fi
45
+
46
+ # If no UUID resolved, passthrough unchanged
47
+ if [ -z "$UUID" ]; then
48
+ exit 0
49
+ fi
50
+
51
+ # Extract tool_input and guard against null before merging
52
+ TOOL_INPUT=$(echo "$INPUT" | jq -c '.tool_input' 2>/dev/null)
53
+ if [ -z "$TOOL_INPUT" ] || [ "$TOOL_INPUT" = "null" ]; then
54
+ # No tool_input to mutate — output original input unchanged
55
+ echo "$INPUT"
56
+ exit 0
57
+ fi
58
+
59
+ MERGED_TOOL_INPUT=$(echo "$TOOL_INPUT" | jq -c --arg uuid "$UUID" '. + {caller_worktree_id: $uuid}' 2>/dev/null)
60
+ if [ -z "$MERGED_TOOL_INPUT" ] || [ "$MERGED_TOOL_INPUT" = "null" ]; then
61
+ echo "$INPUT"
62
+ exit 0
63
+ fi
64
+
65
+ # Output PreToolUse hookSpecificOutput with updatedInput
66
+ jq -n \
67
+ --argjson updated "$MERGED_TOOL_INPUT" \
68
+ '{
69
+ hookSpecificOutput: {
70
+ hookEventName: "PreToolUse",
71
+ permissionDecision: "allow",
72
+ updatedInput: $updated
73
+ }
74
+ }'
75
+
76
+ exit 0
@@ -0,0 +1,68 @@
1
+ #!/bin/bash
2
+ # @hook: Notification
3
+ # Hook: Notification for all matchers
4
+ # Purpose: Send desktop notifications with project context. Cross-platform graceful-degrade —
5
+ # silent no-op when terminal-notifier is missing (Linux/Windows/macOS without Homebrew);
6
+ # VS Code click-to-focus action only on macOS hosts with `code` on PATH.
7
+ # Exit 0 = always (notification hooks must never block Claude)
8
+ #
9
+ # Known: notification_type is not sent in JSON input (anthropics/claude-code#11964)
10
+ # Input fields: session_id, cwd, hook_event_name, message
11
+
12
+ set +e
13
+
14
+ # Graceful skip on hosts without terminal-notifier (Linux, Windows, macOS w/o Homebrew)
15
+ command -v terminal-notifier >/dev/null 2>&1 || exit 0
16
+
17
+ # Read JSON input from stdin
18
+ INPUT=$(cat)
19
+
20
+ # Parse notification fields
21
+ eval "$(echo "$INPUT" | jq -r '
22
+ @sh "MESSAGE=\(.message // "")",
23
+ @sh "CWD=\(.cwd // "")"
24
+ ' 2>/dev/null)"
25
+
26
+ # Detect project name
27
+ if [ -n "$CLAUDE_PROJECT_DIR" ]; then
28
+ PROJECT_DIR="$CLAUDE_PROJECT_DIR"
29
+ elif [ -n "$CWD" ]; then
30
+ PROJECT_DIR="$CWD"
31
+ else
32
+ PROJECT_DIR="unknown"
33
+ fi
34
+ PROJECT_NAME=$(basename "$PROJECT_DIR")
35
+
36
+ TITLE="[$PROJECT_NAME] Claude Code"
37
+ BODY="${MESSAGE:-Claude Code notification}"
38
+
39
+ # VS Code focus click action — only on macOS with `code` available
40
+ CLICK_ACTION=""
41
+ if [[ "$OSTYPE" == darwin* ]] && command -v code >/dev/null 2>&1; then
42
+ # Quote path for re-parse by terminal-notifier -execute (POSIX sh)
43
+ SAFE_DIR=$(printf '%q' "$PROJECT_DIR")
44
+ CLICK_ACTION="code -r $SAFE_DIR && sleep 0.3 && osascript -e 'tell application \"System Events\" to keystroke \"\`\" using control down'"
45
+ fi
46
+
47
+ # Send notification via terminal-notifier in background (non-blocking).
48
+ # Omit -execute argument entirely when CLICK_ACTION is empty (avoid passing empty string).
49
+ if [ -n "$CLICK_ACTION" ]; then
50
+ terminal-notifier \
51
+ -title "$TITLE" \
52
+ -message "$BODY" \
53
+ -sound "Glass" \
54
+ -group "claude-${PROJECT_NAME}" \
55
+ -execute "$CLICK_ACTION" \
56
+ -sender "com.microsoft.VSCode" \
57
+ > /dev/null 2>&1 &
58
+ else
59
+ terminal-notifier \
60
+ -title "$TITLE" \
61
+ -message "$BODY" \
62
+ -sound "Glass" \
63
+ -group "claude-${PROJECT_NAME}" \
64
+ -sender "com.microsoft.VSCode" \
65
+ > /dev/null 2>&1 &
66
+ fi
67
+
68
+ exit 0
@@ -0,0 +1,29 @@
1
+ #!/bin/bash
2
+ # @scope: org-shared
3
+ # Hook: universal plugin-script dispatcher
4
+ # Purpose: Resolve a plugin-shipped hook/statusLine script path with auto-detect fallback.
5
+ # Workaround: ${CLAUDE_PLUGIN_ROOT} is set in the plugin's own hook context but may not
6
+ # resolve in the consuming repo's settings.json statusLine/hooks command context (Claude
7
+ # Code v1.0 limitation). This shim prefers the env var when set; otherwise auto-detects
8
+ # the latest installed plugin version under ~/.claude/plugins/cache/codebyplan-tools/codebyplan/*.
9
+ # Called from settings.json: `bash .claude/hooks/plugin-dispatch.sh <hook-name>.sh [args...]`
10
+
11
+ HOOK_NAME="$1"
12
+ shift
13
+
14
+ if [ -z "$HOOK_NAME" ]; then
15
+ echo "plugin-dispatch.sh: missing hook script name as \$1" >&2
16
+ exit 0 # graceful no-op (don't block Claude Code)
17
+ fi
18
+
19
+ PLUGIN_BASE="$HOME/.claude/plugins/cache/codebyplan-tools/codebyplan"
20
+
21
+ TARGET=""
22
+ if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ] && [ -f "${CLAUDE_PLUGIN_ROOT}/hooks/$HOOK_NAME" ]; then
23
+ TARGET="${CLAUDE_PLUGIN_ROOT}/hooks/$HOOK_NAME"
24
+ else
25
+ TARGET="$(ls -d "$PLUGIN_BASE"/*/hooks/"$HOOK_NAME" 2>/dev/null | sort -V | tail -1)"
26
+ fi
27
+
28
+ [ -n "$TARGET" ] && [ -f "$TARGET" ] && exec bash "$TARGET" "$@"
29
+ exit 0
@@ -0,0 +1,204 @@
1
+ #!/bin/bash
2
+ # @hook: PreToolUse Bash
3
+ # Hook: PreToolUse for Bash (git commit commands)
4
+ # Purpose: Block git commits that violate greenfield-lint-zero-warnings,
5
+ # ship skip-only test files, or have TS compile errors in the
6
+ # staged files' owning packages.
7
+ #
8
+ # Gates:
9
+ # 3. Greenfield ESLint configs (newly-added eslint.config.{mjs,js,cjs,ts})
10
+ # must produce zero warnings/errors when run against their package.
11
+ # 4. Newly-added *.{test,spec}.{ts,tsx,js,jsx} files must contain at least
12
+ # one live (non-.skip / non-.todo) test declaration.
13
+ # 5. (Opt-in via CBP_PRECOMMIT_TYPECHECK=1) Staged TS files typecheck in
14
+ # their owning package.
15
+ #
16
+ # Exit 0 = allow, Exit 2 = block (stderr sent to Claude)
17
+
18
+ set -e
19
+
20
+ echo "[HOOK START] pre-commit-quality-gate"
21
+
22
+ # Read JSON input from stdin
23
+ INPUT=$(cat)
24
+
25
+ # Extract command from tool input
26
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
27
+
28
+ if [ -z "$COMMAND" ]; then
29
+ echo "[HOOK END] pre-commit-quality-gate (no command)"
30
+ exit 0
31
+ fi
32
+
33
+ # Only check git commit commands
34
+ if ! echo "$COMMAND" | grep -qE 'git\s+commit'; then
35
+ echo "[HOOK END] pre-commit-quality-gate (not git commit)"
36
+ exit 0
37
+ fi
38
+
39
+ REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
40
+ if [ -z "$REPO_ROOT" ]; then
41
+ echo "[HOOK END] pre-commit-quality-gate (not a git repo)"
42
+ exit 0
43
+ fi
44
+
45
+ STAGED_ADDED=$(git diff --cached --name-only --diff-filter=A 2>/dev/null || true)
46
+ STAGED_ALL=$(git diff --cached --name-only --diff-filter=AM 2>/dev/null || true)
47
+
48
+ BLOCKED=0
49
+ REASONS=""
50
+
51
+ # ── Helper: walk up from a file to its owning package.json dir ───────────
52
+ find_pkg_dir() {
53
+ local start_dir="$1"
54
+ local dir="$start_dir"
55
+ while [ "$dir" != "$REPO_ROOT" ] && [ "$dir" != "/" ] && [ -n "$dir" ]; do
56
+ if [ -f "$dir/package.json" ]; then
57
+ echo "$dir"
58
+ return 0
59
+ fi
60
+ dir="$(dirname "$dir")"
61
+ done
62
+ if [ -f "$REPO_ROOT/package.json" ]; then
63
+ echo "$REPO_ROOT"
64
+ return 0
65
+ fi
66
+ echo ""
67
+ }
68
+
69
+ # ── Gate 3: Greenfield ESLint configs ship with zero warnings ────────────
70
+ GREENFIELD_CONFIGS=$(echo "$STAGED_ADDED" | grep -E 'eslint\.config\.(mjs|js|cjs|ts)$' || true)
71
+
72
+ if [ -n "$GREENFIELD_CONFIGS" ]; then
73
+ while IFS= read -r CFG; do
74
+ [ -z "$CFG" ] && continue
75
+ PKG_DIR=$(find_pkg_dir "$REPO_ROOT/$(dirname "$CFG")")
76
+ [ -z "$PKG_DIR" ] && continue
77
+
78
+ ESLINT_BIN=""
79
+ if [ -x "$PKG_DIR/node_modules/.bin/eslint" ]; then
80
+ ESLINT_BIN="$PKG_DIR/node_modules/.bin/eslint"
81
+ elif [ -x "$REPO_ROOT/node_modules/.bin/eslint" ]; then
82
+ ESLINT_BIN="$REPO_ROOT/node_modules/.bin/eslint"
83
+ fi
84
+
85
+ if [ -z "$ESLINT_BIN" ]; then
86
+ continue # eslint binary missing, can't enforce — silent skip
87
+ fi
88
+
89
+ LINT_OUTPUT=$(cd "$PKG_DIR" && "$ESLINT_BIN" --no-error-on-unmatched-pattern . 2>&1) || LINT_FAILED=1
90
+
91
+ if [ -n "${LINT_FAILED:-}" ] || echo "$LINT_OUTPUT" | grep -qE '(warning|error)'; then
92
+ BLOCKED=1
93
+ REASONS="${REASONS}
94
+ GATE 3 (greenfield-lint-zero-warnings) FAILED for ${CFG}:
95
+ Package: ${PKG_DIR#$REPO_ROOT/}
96
+ Reproduce: (cd ${PKG_DIR#$REPO_ROOT/} && ./node_modules/.bin/eslint .)
97
+ New eslint configs must ship with zero warnings.
98
+ "
99
+ fi
100
+ unset LINT_FAILED
101
+ done <<< "$GREENFIELD_CONFIGS"
102
+ fi
103
+
104
+ # ── Gate 4: Skip-only test files ─────────────────────────────────────────
105
+ TEST_FILES=$(echo "$STAGED_ADDED" | grep -E '\.(test|spec)\.(ts|tsx|js|jsx)$' || true)
106
+
107
+ if [ -n "$TEST_FILES" ]; then
108
+ while IFS= read -r TF; do
109
+ [ -z "$TF" ] && continue
110
+ [ ! -f "$REPO_ROOT/$TF" ] && continue
111
+
112
+ # Count live test declarations (not .skip, not .todo)
113
+ # Patterns: describe(, it(, test( — must NOT be preceded by .skip or .todo
114
+ # Note: `grep -c` already prints 0 on no match (with exit 1); do NOT add
115
+ # `|| echo 0` — that concatenates a second 0 and breaks the -le comparison.
116
+ LIVE=$(grep -cE '(^|[^.])\b(describe|it|test)\s*\(' "$REPO_ROOT/$TF" 2>/dev/null) || LIVE=0
117
+ SKIP=$(grep -cE '\b(describe|it|test)\.(skip|todo)\s*\(' "$REPO_ROOT/$TF" 2>/dev/null) || SKIP=0
118
+
119
+ # If the file has only skip/todo declarations and no live tests, block
120
+ if [ "$LIVE" -le "$SKIP" ] && [ "$SKIP" -gt 0 ]; then
121
+ BLOCKED=1
122
+ REASONS="${REASONS}
123
+ GATE 4 (skip-only-test-file) FAILED for ${TF}:
124
+ File contains ${SKIP} skip/todo declarations and no live tests.
125
+ A new test file that only contains .skip() or .todo() exercises nothing
126
+ but satisfies test-coverage-gate.sh — remove .skip()/.todo() or remove the file.
127
+ "
128
+ fi
129
+ done <<< "$TEST_FILES"
130
+ fi
131
+
132
+ # ── Gate 5: TS-compile best-effort (opt-in via CBP_PRECOMMIT_TYPECHECK=1) ─
133
+ # Typecheck can take 30–60s on large packages; opt-in keeps the common-case
134
+ # commit path fast. Enable in CI or before shipping via: export CBP_PRECOMMIT_TYPECHECK=1
135
+ if [ "${CBP_PRECOMMIT_TYPECHECK:-0}" = "1" ]; then
136
+ TS_FILES=$(echo "$STAGED_ALL" | grep -E '\.(ts|tsx)$' \
137
+ | grep -vE '(^|/)(node_modules|dist|build|\.next|\.turbo|coverage)/' || true)
138
+
139
+ if [ -n "$TS_FILES" ]; then
140
+ # Group by owning package — uses newline-separated list + sort -u for bash 3.2 (macOS) compatibility
141
+ PKG_LIST=""
142
+ while IFS= read -r F; do
143
+ [ -z "$F" ] && continue
144
+ PKG_DIR=$(find_pkg_dir "$REPO_ROOT/$(dirname "$F")")
145
+ [ -z "$PKG_DIR" ] && continue
146
+ PKG_LIST="${PKG_LIST}${PKG_DIR}
147
+ "
148
+ done <<< "$TS_FILES"
149
+
150
+ UNIQUE_PKGS=$(printf "%s" "$PKG_LIST" | sort -u | grep -v '^$' || true)
151
+
152
+ while IFS= read -r PKG_DIR; do
153
+ [ -z "$PKG_DIR" ] && continue
154
+ TSC_BIN=""
155
+ if [ -x "$PKG_DIR/node_modules/.bin/tsc" ]; then
156
+ TSC_BIN="$PKG_DIR/node_modules/.bin/tsc"
157
+ elif [ -x "$REPO_ROOT/node_modules/.bin/tsc" ]; then
158
+ TSC_BIN="$REPO_ROOT/node_modules/.bin/tsc"
159
+ fi
160
+ [ -z "$TSC_BIN" ] && continue
161
+ [ -f "$PKG_DIR/tsconfig.json" ] || continue
162
+
163
+ TSC_OUTPUT=$(cd "$PKG_DIR" && "$TSC_BIN" --noEmit -p "$PKG_DIR/tsconfig.json" 2>&1) || TSC_FAILED=1
164
+
165
+ if [ -n "${TSC_FAILED:-}" ]; then
166
+ BLOCKED=1
167
+ TSC_TRUNC=$(echo "$TSC_OUTPUT" | head -30)
168
+ REASONS="${REASONS}
169
+ GATE 5 (ts-compile) FAILED for package ${PKG_DIR#$REPO_ROOT/}:
170
+ Reproduce: (cd ${PKG_DIR#$REPO_ROOT/} && ./node_modules/.bin/tsc --noEmit)
171
+ First errors:
172
+ ${TSC_TRUNC}
173
+ "
174
+ fi
175
+ unset TSC_FAILED
176
+ done <<< "$UNIQUE_PKGS"
177
+ fi
178
+ fi
179
+
180
+ # ── Gate 6: .claude/ / templates/ sibling identity ───────────────────────
181
+ SIBLING_CHECK_SCRIPT="$REPO_ROOT/scripts/check-sibling-identity.mjs"
182
+ if [ -f "$SIBLING_CHECK_SCRIPT" ]; then
183
+ SIBLING_OUTPUT=$(cd "$REPO_ROOT" && node "$SIBLING_CHECK_SCRIPT" 2>&1) || SIBLING_FAILED=1
184
+ if [ -n "${SIBLING_FAILED:-}" ]; then
185
+ BLOCKED=1
186
+ REASONS="${REASONS}
187
+ GATE 6 (sibling-identity) FAILED:
188
+ ${SIBLING_OUTPUT}
189
+ "
190
+ fi
191
+ unset SIBLING_FAILED
192
+ fi
193
+
194
+ # ── Report ───────────────────────────────────────────────────────────────
195
+ if [ "$BLOCKED" -eq 1 ]; then
196
+ echo "" >&2
197
+ echo "PRE-COMMIT QUALITY GATE: Cannot commit — one or more gates failed:" >&2
198
+ echo -e "$REASONS" >&2
199
+ echo "[HOOK END] pre-commit-quality-gate (BLOCKED)" >&2
200
+ exit 2
201
+ fi
202
+
203
+ echo "[HOOK END] pre-commit-quality-gate (all gates passed)"
204
+ exit 0