codebyplan 1.5.1 → 1.9.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.
- package/dist/cli.js +4462 -748
- package/package.json +5 -1
- package/templates/.gitkeep +0 -0
- package/templates/README.md +20 -0
- package/templates/agents/cbp-cc-executor.md +213 -0
- package/templates/agents/cbp-database-agent.md +229 -0
- package/templates/agents/cbp-improve-claude.md +245 -0
- package/templates/agents/cbp-improve-round.md +284 -0
- package/templates/agents/cbp-mechanical-edits.md +111 -0
- package/templates/agents/cbp-research.md +282 -0
- package/templates/agents/cbp-round-executor.md +604 -0
- package/templates/agents/cbp-security-agent.md +134 -0
- package/templates/agents/cbp-task-check.md +213 -0
- package/templates/agents/cbp-task-planner.md +582 -0
- package/templates/agents/cbp-test-e2e-agent.md +363 -0
- package/templates/agents/cbp-testing-qa-agent.md +400 -0
- package/templates/context/mcp-docs.md +139 -0
- package/templates/hooks/README.md +236 -0
- package/templates/hooks/cbp-auto-test-hooks.sh +44 -0
- package/templates/hooks/cbp-lint-format-on-edit.sh +159 -0
- package/templates/hooks/cbp-maestro-yaml-validate.sh +100 -0
- package/templates/hooks/cbp-mcp-migration-guard.sh +32 -0
- package/templates/hooks/cbp-mcp-round-sync.sh +79 -0
- package/templates/hooks/cbp-mcp-worktree-inject.sh +76 -0
- package/templates/hooks/cbp-notify.sh +68 -0
- package/templates/hooks/cbp-plugin-dispatch.sh +29 -0
- package/templates/hooks/cbp-pre-commit-quality-gate.sh +204 -0
- package/templates/hooks/cbp-statusline.sh +347 -0
- package/templates/hooks/cbp-subagent-statusline.sh +182 -0
- package/templates/hooks/cbp-test-coverage-gate.sh +144 -0
- package/templates/hooks/cbp-test-hooks.sh +320 -0
- package/templates/hooks/hooks.json +85 -0
- package/templates/hooks/validate-context-usage.sh +59 -0
- package/templates/hooks/validate-git-commit.sh +78 -0
- package/templates/hooks/validate-git-stash-deny.sh +32 -0
- package/templates/hooks/validate-structure-lengths.sh +57 -0
- package/templates/hooks/validate-structure-lib.sh +104 -0
- package/templates/hooks/validate-structure-patterns.sh +54 -0
- package/templates/hooks/validate-structure-scope.sh +33 -0
- package/templates/hooks/validate-structure-smoke.sh +95 -0
- package/templates/hooks/validate-structure-templates.sh +34 -0
- package/templates/hooks/validate-structure.sh +69 -0
- package/templates/rules/.gitkeep +0 -0
- package/templates/rules/README.md +47 -0
- package/templates/rules/context-file-loading.md +52 -0
- package/templates/rules/scope-vocabulary.md +64 -0
- package/templates/rules/todo-backend.md +109 -0
- package/templates/settings.project.base.json +55 -0
- package/templates/settings.user.base.json +25 -0
- package/templates/skills/cbp-build-cc-agent/SKILL.md +139 -0
- package/templates/skills/cbp-build-cc-agent/examples/read-only-reviewer.md +32 -0
- package/templates/skills/cbp-build-cc-agent/examples/with-hooks.md +41 -0
- package/templates/skills/cbp-build-cc-agent/examples/with-skills-preload.md +25 -0
- package/templates/skills/cbp-build-cc-agent/reference/cbp-quality.md +153 -0
- package/templates/skills/cbp-build-cc-agent/reference/frontmatter-fields.md +37 -0
- package/templates/skills/cbp-build-cc-agent/reference/permission-modes.md +18 -0
- package/templates/skills/cbp-build-cc-agent/scripts/validate-agent.sh +67 -0
- package/templates/skills/cbp-build-cc-agent/templates/agent.md +66 -0
- package/templates/skills/cbp-build-cc-claude-file/SKILL.md +178 -0
- package/templates/skills/cbp-build-cc-claude-file/examples/minimal-project.md +33 -0
- package/templates/skills/cbp-build-cc-claude-file/examples/monorepo-with-imports.md +39 -0
- package/templates/skills/cbp-build-cc-claude-file/reference/imports.md +72 -0
- package/templates/skills/cbp-build-cc-claude-file/reference/what-belongs.md +39 -0
- package/templates/skills/cbp-build-cc-claude-file/templates/project-claude-md.md +48 -0
- package/templates/skills/cbp-build-cc-claude-file/templates/user-claude-md.md +22 -0
- package/templates/skills/cbp-build-cc-memory/SKILL.md +201 -0
- package/templates/skills/cbp-build-cc-memory/examples/feedback-memory.md +11 -0
- package/templates/skills/cbp-build-cc-memory/examples/project-memory.md +11 -0
- package/templates/skills/cbp-build-cc-memory/examples/reference-memory.md +13 -0
- package/templates/skills/cbp-build-cc-memory/examples/user-memory.md +14 -0
- package/templates/skills/cbp-build-cc-memory/reference/memory-types.md +59 -0
- package/templates/skills/cbp-build-cc-memory/reference/when-to-save.md +62 -0
- package/templates/skills/cbp-build-cc-memory/templates/MEMORY-index.md +4 -0
- package/templates/skills/cbp-build-cc-memory/templates/memory-entry.md +15 -0
- package/templates/skills/cbp-build-cc-mode/SKILL.md +99 -0
- package/templates/skills/cbp-build-cc-rule/SKILL.md +176 -0
- package/templates/skills/cbp-build-cc-rule/examples/global-rule.md +19 -0
- package/templates/skills/cbp-build-cc-rule/examples/scoped-rule.md +41 -0
- package/templates/skills/cbp-build-cc-rule/reference/paths-patterns.md +48 -0
- package/templates/skills/cbp-build-cc-rule/templates/rule.md +32 -0
- package/templates/skills/cbp-build-cc-settings/SKILL.md +220 -0
- package/templates/skills/cbp-build-cc-settings/examples/hooks-config.json +64 -0
- package/templates/skills/cbp-build-cc-settings/examples/permissions-config.json +34 -0
- package/templates/skills/cbp-build-cc-settings/examples/sandbox-config.json +42 -0
- package/templates/skills/cbp-build-cc-settings/reference/cbp-conventions.md +104 -0
- package/templates/skills/cbp-build-cc-settings/reference/permission-rules.md +61 -0
- package/templates/skills/cbp-build-cc-settings/reference/scope-precedence.md +73 -0
- package/templates/skills/cbp-build-cc-settings/reference/settings-fields.md +166 -0
- package/templates/skills/cbp-build-cc-settings/templates/settings.json +23 -0
- package/templates/skills/cbp-build-cc-settings/templates/settings.local.json +10 -0
- package/templates/skills/cbp-build-cc-skill/SKILL.md +154 -0
- package/templates/skills/cbp-build-cc-skill/examples/dynamic-context.md +31 -0
- package/templates/skills/cbp-build-cc-skill/examples/fork-skill.md +22 -0
- package/templates/skills/cbp-build-cc-skill/examples/knowledge-skill.md +25 -0
- package/templates/skills/cbp-build-cc-skill/examples/task-skill.md +29 -0
- package/templates/skills/cbp-build-cc-skill/reference/cbp-quality.md +157 -0
- package/templates/skills/cbp-build-cc-skill/reference/frontmatter-fields.md +35 -0
- package/templates/skills/cbp-build-cc-skill/reference/string-substitutions.md +60 -0
- package/templates/skills/cbp-build-cc-skill/scripts/validate-skill.sh +90 -0
- package/templates/skills/cbp-build-cc-skill/templates/skill.md +51 -0
- package/templates/skills/cbp-checkpoint-check/SKILL.md +156 -0
- package/templates/skills/cbp-checkpoint-complete/SKILL.md +109 -0
- package/templates/skills/cbp-checkpoint-create/SKILL.md +116 -0
- package/templates/skills/cbp-checkpoint-end/SKILL.md +241 -0
- package/templates/skills/cbp-checkpoint-plan/SKILL.md +137 -0
- package/templates/skills/cbp-checkpoint-plan/reference/alternative-comparison-template.md +54 -0
- package/templates/skills/cbp-checkpoint-plan/reference/dep-decision-rubric.md +50 -0
- package/templates/skills/cbp-checkpoint-plan/reference/e2e-discovery-probe.md +57 -0
- package/templates/skills/cbp-checkpoint-plan/reference/gap-analysis-playbook.md +47 -0
- package/templates/skills/cbp-checkpoint-start/SKILL.md +84 -0
- package/templates/skills/cbp-checkpoint-update/SKILL.md +115 -0
- package/templates/skills/cbp-frontend-a11y/SKILL.md +109 -0
- package/templates/skills/cbp-frontend-a11y/reference/aria-roles-states.md +130 -0
- package/templates/skills/cbp-frontend-a11y/reference/contrast-visual.md +122 -0
- package/templates/skills/cbp-frontend-a11y/reference/keyboard-patterns.md +154 -0
- package/templates/skills/cbp-frontend-a11y/reference/semantic-html.md +111 -0
- package/templates/skills/cbp-frontend-design/SKILL.md +145 -0
- package/templates/skills/cbp-frontend-design/reference/nextjs-scss.md +118 -0
- package/templates/skills/cbp-frontend-design/reference/rn-expo.md +101 -0
- package/templates/skills/cbp-frontend-design/reference/tauri-react.md +82 -0
- package/templates/skills/cbp-frontend-ui/SKILL.md +262 -0
- package/templates/skills/cbp-frontend-ui/reference/ui-label-maps.md +42 -0
- package/templates/skills/cbp-frontend-ui/reference/ui-layout-patterns.md +105 -0
- package/templates/skills/cbp-frontend-ui/reference/variant-defaults.md +149 -0
- package/templates/skills/cbp-frontend-ux/SKILL.md +181 -0
- package/templates/skills/cbp-git-branch-feat-create/SKILL.md +115 -0
- package/templates/skills/cbp-git-commit/SKILL.md +278 -0
- package/templates/skills/cbp-git-worktree-create/SKILL.md +226 -0
- package/templates/skills/cbp-git-worktree-remove/SKILL.md +145 -0
- package/templates/skills/cbp-merge-main/SKILL.md +228 -0
- package/templates/skills/cbp-round-check/SKILL.md +104 -0
- package/templates/skills/cbp-round-end/SKILL.md +183 -0
- package/templates/skills/cbp-round-end/reference/findings-presentation.md +44 -0
- package/templates/skills/cbp-round-end/reference/inline-fallback.md +35 -0
- package/templates/skills/cbp-round-execute/SKILL.md +211 -0
- package/templates/skills/cbp-round-execute/reference/inline-fallback.md +59 -0
- package/templates/skills/cbp-round-input/SKILL.md +165 -0
- package/templates/skills/cbp-round-start/SKILL.md +222 -0
- package/templates/skills/cbp-round-update/SKILL.md +163 -0
- package/templates/skills/cbp-session-end/SKILL.md +187 -0
- package/templates/skills/cbp-session-start/SKILL.md +155 -0
- package/templates/skills/cbp-ship/SKILL.md +332 -0
- package/templates/skills/cbp-ship/reference/changesets-overview.md +120 -0
- package/templates/skills/cbp-ship/reference/eas-cli-overview.md +60 -0
- package/templates/skills/cbp-ship/reference/gh-cli-overview.md +135 -0
- package/templates/skills/cbp-ship/reference/gh-cli-shipment-commands.md +283 -0
- package/templates/skills/cbp-ship/reference/npm-publish-monorepo.md +252 -0
- package/templates/skills/cbp-ship/reference/npm-publish-oidc-trusted.md +157 -0
- package/templates/skills/cbp-ship/reference/npm-publish-overview.md +171 -0
- package/templates/skills/cbp-ship/reference/preflight-checklist.md +88 -0
- package/templates/skills/cbp-ship/reference/railway-nestjs-deployment.md +169 -0
- package/templates/skills/cbp-ship/reference/railway-overview.md +120 -0
- package/templates/skills/cbp-ship/reference/railway-troubleshooting.md +168 -0
- package/templates/skills/cbp-ship/reference/release-please-overview.md +99 -0
- package/templates/skills/cbp-ship/reference/surface-expo-eas.md +155 -0
- package/templates/skills/cbp-ship/reference/surface-npm.md +180 -0
- package/templates/skills/cbp-ship/reference/surface-railway.md +152 -0
- package/templates/skills/cbp-ship/reference/surface-supabase.md +178 -0
- package/templates/skills/cbp-ship/reference/surface-tauri.md +138 -0
- package/templates/skills/cbp-ship/reference/surface-vercel.md +124 -0
- package/templates/skills/cbp-ship/reference/surface-vscode-ext.md +144 -0
- package/templates/skills/cbp-ship/reference/surfaces.md +60 -0
- package/templates/skills/cbp-ship/reference/testflight-automation.md +215 -0
- package/templates/skills/cbp-ship/reference/testflight-internal-vs-external.md +69 -0
- package/templates/skills/cbp-ship/reference/testflight-overview.md +98 -0
- package/templates/skills/cbp-ship/reference/versioning.md +116 -0
- package/templates/skills/cbp-ship/scripts/detect-surfaces.sh +217 -0
- package/templates/skills/cbp-ship/scripts/verify-expo-eas.sh +35 -0
- package/templates/skills/cbp-ship/scripts/verify-npm.sh +21 -0
- package/templates/skills/cbp-ship/scripts/verify-railway.sh +41 -0
- package/templates/skills/cbp-ship/scripts/verify-supabase.sh +19 -0
- package/templates/skills/cbp-ship/scripts/verify-tauri.sh +24 -0
- package/templates/skills/cbp-ship/scripts/verify-vercel.sh +32 -0
- package/templates/skills/cbp-ship/scripts/verify-vscode-ext.sh +25 -0
- package/templates/skills/cbp-ship/templates/eas.json +66 -0
- package/templates/skills/cbp-ship/templates/railway.toml +15 -0
- package/templates/skills/cbp-ship/templates/release-please-config.json +17 -0
- package/templates/skills/cbp-ship/templates/vercel.json +19 -0
- package/templates/skills/cbp-ship/templates/vscodeignore +21 -0
- package/templates/skills/cbp-ship/templates/workflow-changesets.yml +41 -0
- package/templates/skills/cbp-ship/templates/workflow-eas-submit.yml +53 -0
- package/templates/skills/cbp-ship/templates/workflow-npm-publish.yml +36 -0
- package/templates/skills/cbp-ship/templates/workflow-release-please.yml +21 -0
- package/templates/skills/cbp-ship/templates/workflow-tauri-release.yml +69 -0
- package/templates/skills/cbp-ship/templates/workflow-vsce-publish.yml +31 -0
- package/templates/skills/cbp-ship-configure/SKILL.md +296 -0
- package/templates/skills/cbp-ship-configure/reference/expo-mobile.md +204 -0
- package/templates/skills/cbp-ship-configure/reference/npm-package.md +165 -0
- package/templates/skills/cbp-ship-configure/reference/railway-backend.md +199 -0
- package/templates/skills/cbp-ship-configure/reference/supabase.md +200 -0
- package/templates/skills/cbp-ship-configure/reference/tauri-desktop.md +181 -0
- package/templates/skills/cbp-ship-configure/reference/vercel.md +117 -0
- package/templates/skills/cbp-ship-configure/reference/vscode-ext.md +155 -0
- package/templates/skills/cbp-ship-main/SKILL.md +65 -0
- package/templates/skills/cbp-supabase-branch-check/SKILL.md +337 -0
- package/templates/skills/cbp-supabase-branch-check/reference/dag-steps.md +29 -0
- package/templates/skills/cbp-supabase-migrate/SKILL.md +314 -0
- package/templates/skills/cbp-supabase-migrate/reference/advisor-triage.md +70 -0
- package/templates/skills/cbp-supabase-migrate/reference/cli-fallback.md +87 -0
- package/templates/skills/cbp-supabase-migrate/reference/preflight-dry-run.md +58 -0
- package/templates/skills/cbp-supabase-setup/SKILL.md +239 -0
- package/templates/skills/cbp-supabase-setup/reference/branching-setup.md +121 -0
- package/templates/skills/cbp-supabase-setup/reference/cli-fallback.md +109 -0
- package/templates/skills/cbp-task-check/SKILL.md +166 -0
- package/templates/skills/cbp-task-complete/SKILL.md +206 -0
- package/templates/skills/cbp-task-complete/reference/checkpoint-done-branching.md +48 -0
- package/templates/skills/cbp-task-complete/reference/next-step-heuristic.md +56 -0
- package/templates/skills/cbp-task-create/SKILL.md +167 -0
- package/templates/skills/cbp-task-start/SKILL.md +239 -0
- package/templates/skills/cbp-task-testing/SKILL.md +277 -0
- package/templates/skills/cbp-todo/SKILL.md +111 -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
|