shipwright-cli 1.7.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 (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +926 -0
  3. package/claude-code/CLAUDE.md.shipwright +125 -0
  4. package/claude-code/hooks/notify-idle.sh +35 -0
  5. package/claude-code/hooks/pre-compact-save.sh +57 -0
  6. package/claude-code/hooks/task-completed.sh +170 -0
  7. package/claude-code/hooks/teammate-idle.sh +68 -0
  8. package/claude-code/settings.json.template +184 -0
  9. package/completions/_shipwright +140 -0
  10. package/completions/shipwright.bash +89 -0
  11. package/completions/shipwright.fish +107 -0
  12. package/docs/KNOWN-ISSUES.md +199 -0
  13. package/docs/TIPS.md +331 -0
  14. package/docs/definition-of-done.example.md +16 -0
  15. package/docs/patterns/README.md +139 -0
  16. package/docs/patterns/audit-loop.md +149 -0
  17. package/docs/patterns/bug-hunt.md +183 -0
  18. package/docs/patterns/feature-implementation.md +159 -0
  19. package/docs/patterns/refactoring.md +183 -0
  20. package/docs/patterns/research-exploration.md +144 -0
  21. package/docs/patterns/test-generation.md +173 -0
  22. package/package.json +49 -0
  23. package/scripts/adapters/docker-deploy.sh +50 -0
  24. package/scripts/adapters/fly-deploy.sh +41 -0
  25. package/scripts/adapters/iterm2-adapter.sh +122 -0
  26. package/scripts/adapters/railway-deploy.sh +34 -0
  27. package/scripts/adapters/tmux-adapter.sh +87 -0
  28. package/scripts/adapters/vercel-deploy.sh +35 -0
  29. package/scripts/adapters/wezterm-adapter.sh +103 -0
  30. package/scripts/cct +242 -0
  31. package/scripts/cct-cleanup.sh +172 -0
  32. package/scripts/cct-cost.sh +590 -0
  33. package/scripts/cct-daemon.sh +3189 -0
  34. package/scripts/cct-doctor.sh +328 -0
  35. package/scripts/cct-fix.sh +478 -0
  36. package/scripts/cct-fleet.sh +904 -0
  37. package/scripts/cct-init.sh +282 -0
  38. package/scripts/cct-logs.sh +273 -0
  39. package/scripts/cct-loop.sh +1332 -0
  40. package/scripts/cct-memory.sh +1148 -0
  41. package/scripts/cct-pipeline.sh +3844 -0
  42. package/scripts/cct-prep.sh +1352 -0
  43. package/scripts/cct-ps.sh +168 -0
  44. package/scripts/cct-reaper.sh +390 -0
  45. package/scripts/cct-session.sh +284 -0
  46. package/scripts/cct-status.sh +169 -0
  47. package/scripts/cct-templates.sh +242 -0
  48. package/scripts/cct-upgrade.sh +422 -0
  49. package/scripts/cct-worktree.sh +405 -0
  50. package/scripts/postinstall.mjs +96 -0
  51. package/templates/pipelines/autonomous.json +71 -0
  52. package/templates/pipelines/cost-aware.json +95 -0
  53. package/templates/pipelines/deployed.json +79 -0
  54. package/templates/pipelines/enterprise.json +114 -0
  55. package/templates/pipelines/fast.json +63 -0
  56. package/templates/pipelines/full.json +104 -0
  57. package/templates/pipelines/hotfix.json +63 -0
  58. package/templates/pipelines/standard.json +91 -0
  59. package/tmux/claude-teams-overlay.conf +109 -0
  60. package/tmux/templates/architecture.json +19 -0
  61. package/tmux/templates/bug-fix.json +24 -0
  62. package/tmux/templates/code-review.json +24 -0
  63. package/tmux/templates/devops.json +19 -0
  64. package/tmux/templates/documentation.json +19 -0
  65. package/tmux/templates/exploration.json +19 -0
  66. package/tmux/templates/feature-dev.json +24 -0
  67. package/tmux/templates/full-stack.json +24 -0
  68. package/tmux/templates/migration.json +24 -0
  69. package/tmux/templates/refactor.json +19 -0
  70. package/tmux/templates/security-audit.json +24 -0
  71. package/tmux/templates/testing.json +24 -0
  72. package/tmux/tmux.conf +167 -0
@@ -0,0 +1,125 @@
1
+ # Shipwright — Agent Instructions
2
+
3
+ This project uses [Shipwright](https://github.com/sethdford/shipwright) for autonomous Claude Code agent teams.
4
+
5
+ ## Commands
6
+
7
+ | Command | Purpose |
8
+ |---------|---------|
9
+ | `shipwright pipeline start --issue <N>` | Run full delivery pipeline for an issue |
10
+ | `shipwright pipeline start --issue <N> --worktree` | Pipeline in isolated git worktree (parallel-safe) |
11
+ | `shipwright pipeline start --goal "..." --worktree=name` | Pipeline with named worktree |
12
+ | `shipwright session <name> --template <tpl>` | Create a team session with agent panes |
13
+ | `shipwright daemon start` | Watch repo for labeled issues, auto-process |
14
+ | `shipwright fleet start` | Orchestrate daemons across multiple repos |
15
+ | `shipwright fix "<goal>" --repos <paths>` | Apply the same fix across repos in parallel |
16
+ | `shipwright prep` | Analyze repo and generate preparation report |
17
+ | `shipwright loop` | Continuous improvement loop |
18
+ | `shipwright status` | Show team dashboard |
19
+ | `shipwright cost show` | Token usage and spending dashboard |
20
+ | `shipwright cost budget set <amount>` | Set daily budget limit |
21
+ | `shipwright cost remaining-budget` | Check remaining daily budget (used by auto-scaler) |
22
+ | `shipwright memory list` | View captured failure patterns |
23
+
24
+ ## Pipeline Stages
25
+
26
+ ```
27
+ intake → plan → design → build → test → review → compound_quality → pr → deploy → validate → monitor
28
+ ```
29
+
30
+ ## Parallel Pipelines
31
+
32
+ Use `--worktree` to run multiple pipelines concurrently on the same repo:
33
+
34
+ ```bash
35
+ # Each runs in its own git worktree — no conflicts
36
+ shipwright pipeline start --issue 42 --worktree
37
+ shipwright pipeline start --issue 43 --worktree
38
+ shipwright pipeline start --goal "Refactor auth" --worktree=auth-refactor
39
+ ```
40
+
41
+ The daemon uses worktrees automatically. Use `--worktree` for ad-hoc parallel runs.
42
+
43
+ ## Auto-Scaling (Daemon)
44
+
45
+ The daemon can dynamically adjust worker count based on system resources:
46
+
47
+ ```json
48
+ {
49
+ "auto_scale": true,
50
+ "auto_scale_interval": 5,
51
+ "max_workers": 8,
52
+ "min_workers": 1,
53
+ "worker_mem_gb": 4,
54
+ "estimated_cost_per_job_usd": 5.0
55
+ }
56
+ ```
57
+
58
+ Scaling factors (takes the minimum):
59
+ - **CPU**: 75% of cores (e.g., 8-core → max 6 workers)
60
+ - **Memory**: available GB / `worker_mem_gb`
61
+ - **Budget**: remaining daily budget / `estimated_cost_per_job_usd`
62
+ - **Queue**: current demand (active + queued issues)
63
+
64
+ ## Fleet Worker Pool
65
+
66
+ Distribute a total worker budget across repos proportionally to demand:
67
+
68
+ ```json
69
+ {
70
+ "worker_pool": {
71
+ "enabled": true,
72
+ "total_workers": 12,
73
+ "rebalance_interval_seconds": 120
74
+ }
75
+ }
76
+ ```
77
+
78
+ When enabled, the fleet rebalancer runs in the background and redistributes workers every N seconds. Repos with more queued issues get more workers. Each repo always gets at least 1 worker.
79
+
80
+ ## tmux Conventions
81
+
82
+ - Team windows are named `claude-<team-name>` (get the lambda icon in the status bar)
83
+ - Pane titles: `<team>-<role>` (visible in pane borders)
84
+ - Set pane title: `printf '\033]2;agent-name\033\\'`
85
+ - Prefix key: **Ctrl-a**
86
+ - Layouts: `prefix + M-1` (horizontal), `M-2` (vertical), `M-3` (tiled)
87
+ - Zoom: `prefix + G` (toggle focus on one pane)
88
+ - Capture output: `prefix + M-s` (current pane), `prefix + M-a` (all panes)
89
+
90
+ ## Team Patterns
91
+
92
+ - Assign each agent **different files** to avoid merge conflicts
93
+ - Use `--worktree` for file isolation between agents
94
+ - Keep tasks self-contained (5-6 focused tasks per agent)
95
+ - Use the task list for coordination, not direct messaging
96
+
97
+ ## Memory System
98
+
99
+ Failure patterns are automatically captured after each pipeline run and injected into future builds. Agents receive relevant context from previous runs — fixes, root causes, and codebase conventions — so they don't repeat mistakes.
100
+
101
+ ## Pipeline Templates
102
+
103
+ | Template | Use Case |
104
+ |----------|----------|
105
+ | `fast` | Simple changes (score >= 70) — skip review |
106
+ | `standard` | Medium complexity — full pipeline |
107
+ | `full` | Complex changes — extra review cycles |
108
+ | `hotfix` | Urgent fixes — minimal stages |
109
+ | `autonomous` | Daemon-driven — all stages enabled |
110
+ | `cost-aware` | Budget-conscious — model routing by stage |
111
+
112
+ ## Daemon Configuration
113
+
114
+ Generate with `shipwright daemon init`, then edit `.claude/daemon-config.json`:
115
+
116
+ | Field | Default | Purpose |
117
+ |-------|---------|---------|
118
+ | `max_parallel` | `2` | Static worker limit (overridden by auto_scale) |
119
+ | `auto_scale` | `false` | Enable resource-aware dynamic scaling |
120
+ | `max_workers` | `8` | Ceiling for auto-scaler |
121
+ | `min_workers` | `1` | Floor for auto-scaler |
122
+ | `self_optimize` | `false` | Auto-tune based on DORA metrics |
123
+ | `auto_template` | `false` | Pick pipeline template by issue complexity |
124
+ | `max_retries` | `2` | Retry failed pipelines with escalation |
125
+ | `priority_lane` | `false` | Reserve a slot for urgent/hotfix issues |
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ # ═══════════════════════════════════════════════════════════════════════
3
+ # notify-idle.sh — Desktop notification when Claude needs your attention
4
+ # ═══════════════════════════════════════════════════════════════════════
5
+ #
6
+ # Works on macOS (osascript) and Linux (notify-send).
7
+ #
8
+ # Install:
9
+ # 1. Copy this file to ~/.claude/hooks/notify-idle.sh
10
+ # 2. chmod +x ~/.claude/hooks/notify-idle.sh
11
+ # 3. Add to ~/.claude/settings.json:
12
+ # "hooks": {
13
+ # "Notification": [
14
+ # {
15
+ # "hooks": [
16
+ # {
17
+ # "type": "command",
18
+ # "command": "~/.claude/hooks/notify-idle.sh",
19
+ # "async": true
20
+ # }
21
+ # ]
22
+ # }
23
+ # ]
24
+ # }
25
+ # ═══════════════════════════════════════════════════════════════════════
26
+
27
+ set -euo pipefail
28
+
29
+ if [[ "$(uname)" == "Darwin" ]]; then
30
+ osascript -e 'display notification "An agent needs your attention" with title "Claude Code Teams" sound name "Ping"'
31
+ elif command -v notify-send &>/dev/null; then
32
+ notify-send "Claude Code Teams" "An agent needs your attention" --urgency=normal
33
+ fi
34
+
35
+ exit 0
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env bash
2
+ # ═══════════════════════════════════════════════════════════════════════
3
+ # pre-compact-save.sh — Save important context before compaction
4
+ # ═══════════════════════════════════════════════════════════════════════
5
+ #
6
+ # Outputs text to stdout that gets injected into Claude's context after
7
+ # compaction. Helps Claude remember project state across compaction events.
8
+ #
9
+ # Install:
10
+ # 1. Copy this file to ~/.claude/hooks/pre-compact-save.sh
11
+ # 2. chmod +x ~/.claude/hooks/pre-compact-save.sh
12
+ # 3. Add to ~/.claude/settings.json:
13
+ # "hooks": {
14
+ # "PreCompact": [
15
+ # {
16
+ # "matcher": "auto",
17
+ # "hooks": [
18
+ # {
19
+ # "type": "command",
20
+ # "command": "~/.claude/hooks/pre-compact-save.sh",
21
+ # "statusMessage": "Saving context before compaction..."
22
+ # }
23
+ # ]
24
+ # }
25
+ # ]
26
+ # }
27
+ # ═══════════════════════════════════════════════════════════════════════
28
+
29
+ set -euo pipefail
30
+
31
+ INPUT=$(cat)
32
+ CWD=$(echo "$INPUT" | jq -r '.cwd // empty' 2>/dev/null || true)
33
+
34
+ if [[ -n "$CWD" ]] && [[ -d "$CWD" ]]; then
35
+ cd "$CWD"
36
+ fi
37
+
38
+ # Remind Claude of project context after compaction
39
+ echo "Post-compaction context refresh:"
40
+
41
+ # Show recent git activity
42
+ if git rev-parse --is-inside-work-tree &>/dev/null 2>&1; then
43
+ echo ""
44
+ echo "Recent commits:"
45
+ git log --oneline -5 2>/dev/null || true
46
+ echo ""
47
+ echo "Current branch: $(git branch --show-current 2>/dev/null || echo 'unknown')"
48
+ echo "Changed files: $(git diff --name-only 2>/dev/null | head -10 || true)"
49
+ fi
50
+
51
+ # Show CLAUDE.md reminder if present
52
+ if [[ -f "CLAUDE.md" ]]; then
53
+ echo ""
54
+ echo "Project has CLAUDE.md — re-read it for project conventions."
55
+ fi
56
+
57
+ exit 0
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env bash
2
+ # ═══════════════════════════════════════════════════════════════════════
3
+ # task-completed.sh — Quality gate: block task completion if quality fails
4
+ # ═══════════════════════════════════════════════════════════════════════
5
+ #
6
+ # Runs when a Claude Code agent marks a task as completed. Checks lint
7
+ # and tests on changed files. If any check fails, exit code 2 tells
8
+ # Claude the task isn't really done yet.
9
+ #
10
+ # Install:
11
+ # 1. Copy this file to ~/.claude/hooks/task-completed.sh
12
+ # 2. chmod +x ~/.claude/hooks/task-completed.sh
13
+ # 3. Add to ~/.claude/settings.json:
14
+ # "hooks": {
15
+ # "TaskCompleted": [
16
+ # {
17
+ # "hooks": [
18
+ # {
19
+ # "type": "command",
20
+ # "command": "~/.claude/hooks/task-completed.sh",
21
+ # "timeout": 60
22
+ # }
23
+ # ]
24
+ # }
25
+ # ]
26
+ # }
27
+ #
28
+ # Exit codes:
29
+ # 0 = allow completion (all checks passed)
30
+ # 2 = block completion (fix issues first)
31
+ # ═══════════════════════════════════════════════════════════════════════
32
+
33
+ set -euo pipefail
34
+
35
+ # Read hook input (JSON on stdin) — contains session_id, cwd, etc.
36
+ INPUT=$(cat)
37
+ HOOK_CWD=$(echo "$INPUT" | jq -r '.cwd // empty' 2>/dev/null || true)
38
+ if [[ -n "$HOOK_CWD" ]]; then
39
+ cd "$HOOK_CWD"
40
+ fi
41
+
42
+ FAILED=0
43
+
44
+ # Find the project root (walk up from cwd looking for package.json)
45
+ find_project_root() {
46
+ local dir="$PWD"
47
+ while [[ "$dir" != "/" ]]; do
48
+ if [[ -f "$dir/package.json" ]]; then
49
+ echo "$dir"
50
+ return 0
51
+ fi
52
+ dir="$(dirname "$dir")"
53
+ done
54
+ return 1
55
+ }
56
+
57
+ PROJECT_ROOT="$(find_project_root)" || {
58
+ # No package.json found — not a JS/TS project, allow completion
59
+ exit 0
60
+ }
61
+
62
+ cd "$PROJECT_ROOT"
63
+
64
+ # ─── Step 1: Lint changed files ──────────────────────────────────────
65
+
66
+ # Get files changed relative to HEAD (staged + unstaged)
67
+ CHANGED_FILES=$(git diff --name-only HEAD 2>/dev/null || true)
68
+ if [[ -z "$CHANGED_FILES" ]]; then
69
+ # Also check staged files not yet committed
70
+ CHANGED_FILES=$(git diff --cached --name-only 2>/dev/null || true)
71
+ fi
72
+
73
+ # Filter to lintable files (ts, tsx, js, jsx)
74
+ LINT_FILES=$(echo "$CHANGED_FILES" | grep -E '\.(ts|tsx|js|jsx)$' || true)
75
+
76
+ if [[ -n "$LINT_FILES" ]]; then
77
+ echo "Linting $(echo "$LINT_FILES" | wc -l | tr -d ' ') changed file(s)..."
78
+
79
+ # Build file list as arguments (handle spaces in filenames)
80
+ LINT_ARGS=()
81
+ while IFS= read -r file; do
82
+ [[ -f "$file" ]] && LINT_ARGS+=("$file")
83
+ done <<< "$LINT_FILES"
84
+
85
+ if [[ ${#LINT_ARGS[@]} -gt 0 ]]; then
86
+ if command -v pnpm &>/dev/null && [[ -f "pnpm-lock.yaml" ]]; then
87
+ pnpm eslint --no-error-on-unmatched-pattern "${LINT_ARGS[@]}" 2>&1 || {
88
+ echo "::error::Lint errors in changed files."
89
+ FAILED=1
90
+ }
91
+ elif npx --no-install eslint --version &>/dev/null 2>&1; then
92
+ npx eslint --no-error-on-unmatched-pattern "${LINT_ARGS[@]}" 2>&1 || {
93
+ echo "::error::Lint errors in changed files."
94
+ FAILED=1
95
+ }
96
+ else
97
+ echo "ESLint not available — skipping lint check."
98
+ fi
99
+ fi
100
+ else
101
+ echo "No lintable files changed — skipping lint."
102
+ fi
103
+
104
+ # ─── Step 2: Run related tests ───────────────────────────────────────
105
+
106
+ # Find test files related to changed source files
107
+ TEST_FILES=()
108
+ while IFS= read -r file; do
109
+ [[ -z "$file" ]] && continue
110
+
111
+ # Skip if file is itself a test
112
+ if [[ "$file" =~ \.(test|spec)\.(ts|tsx|js|jsx)$ ]]; then
113
+ [[ -f "$file" ]] && TEST_FILES+=("$file")
114
+ continue
115
+ fi
116
+
117
+ # Look for corresponding test file
118
+ base="${file%.*}"
119
+ ext="${file##*.}"
120
+ for pattern in "${base}.test.${ext}" "${base}.spec.${ext}"; do
121
+ [[ -f "$pattern" ]] && TEST_FILES+=("$pattern")
122
+ done
123
+
124
+ # Also check __tests__ directory
125
+ dir="$(dirname "$file")"
126
+ name="$(basename "$file")"
127
+ namebase="${name%.*}"
128
+ for pattern in "${dir}/__tests__/${namebase}.test.${ext}" "${dir}/__tests__/${namebase}.spec.${ext}"; do
129
+ [[ -f "$pattern" ]] && TEST_FILES+=("$pattern")
130
+ done
131
+ done <<< "$CHANGED_FILES"
132
+
133
+ if [[ ${#TEST_FILES[@]} -gt 0 ]]; then
134
+ # Deduplicate
135
+ readarray -t TEST_FILES < <(printf '%s\n' "${TEST_FILES[@]}" | sort -u)
136
+
137
+ echo "Running ${#TEST_FILES[@]} related test file(s)..."
138
+
139
+ if command -v pnpm &>/dev/null && [[ -f "pnpm-lock.yaml" ]]; then
140
+ pnpm vitest run --reporter=verbose "${TEST_FILES[@]}" 2>&1 || {
141
+ echo "::error::Tests failed for changed files."
142
+ FAILED=1
143
+ }
144
+ elif npx --no-install vitest --version &>/dev/null 2>&1; then
145
+ npx vitest run --reporter=verbose "${TEST_FILES[@]}" 2>&1 || {
146
+ echo "::error::Tests failed for changed files."
147
+ FAILED=1
148
+ }
149
+ elif npx --no-install jest --version &>/dev/null 2>&1; then
150
+ npx jest --bail "${TEST_FILES[@]}" 2>&1 || {
151
+ echo "::error::Tests failed for changed files."
152
+ FAILED=1
153
+ }
154
+ else
155
+ echo "No test runner (vitest/jest) available — skipping tests."
156
+ fi
157
+ else
158
+ echo "No related test files found — skipping tests."
159
+ fi
160
+
161
+ # ─── Result ───────────────────────────────────────────────────────────
162
+
163
+ if [[ "$FAILED" -ne 0 ]]; then
164
+ echo ""
165
+ echo "Task completion blocked — fix the issues above first."
166
+ exit 2
167
+ fi
168
+
169
+ echo "All quality checks passed."
170
+ exit 0
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env bash
2
+ # ═══════════════════════════════════════════════════════════════════════
3
+ # teammate-idle.sh — Quality gate: block idle if typecheck fails
4
+ # ═══════════════════════════════════════════════════════════════════════
5
+ #
6
+ # Runs when a Claude Code teammate goes idle. If there are TypeScript
7
+ # errors, exit code 2 tells Claude to keep working and fix them first.
8
+ #
9
+ # Install:
10
+ # 1. Copy this file to ~/.claude/hooks/teammate-idle.sh
11
+ # 2. chmod +x ~/.claude/hooks/teammate-idle.sh
12
+ # 3. Add to ~/.claude/settings.json:
13
+ # "hooks": {
14
+ # "teammate-idle": {
15
+ # "command": "~/.claude/hooks/teammate-idle.sh",
16
+ # "timeout": 30000
17
+ # }
18
+ # }
19
+ #
20
+ # Exit codes:
21
+ # 0 = allow idle (typecheck passed)
22
+ # 2 = keep working (typecheck failed — fix errors first)
23
+ # ═══════════════════════════════════════════════════════════════════════
24
+
25
+ set -euo pipefail
26
+
27
+ # Find the project root (walk up from cwd looking for package.json)
28
+ find_project_root() {
29
+ local dir="$PWD"
30
+ while [[ "$dir" != "/" ]]; do
31
+ if [[ -f "$dir/package.json" ]]; then
32
+ echo "$dir"
33
+ return 0
34
+ fi
35
+ dir="$(dirname "$dir")"
36
+ done
37
+ return 1
38
+ }
39
+
40
+ PROJECT_ROOT="$(find_project_root)" || {
41
+ # No package.json found — not a TypeScript project, allow idle
42
+ exit 0
43
+ }
44
+
45
+ cd "$PROJECT_ROOT"
46
+
47
+ # Check if this project uses TypeScript
48
+ if [[ ! -f "tsconfig.json" ]]; then
49
+ exit 0
50
+ fi
51
+
52
+ # Run typecheck — try pnpm first, fall back to npx
53
+ if command -v pnpm &>/dev/null && [[ -f "pnpm-lock.yaml" ]]; then
54
+ pnpm typecheck 2>&1 || {
55
+ echo "::error::TypeScript errors found. Fix them before going idle."
56
+ exit 2
57
+ }
58
+ elif command -v npm &>/dev/null; then
59
+ npx tsc --noEmit 2>&1 || {
60
+ echo "::error::TypeScript errors found. Fix them before going idle."
61
+ exit 2
62
+ }
63
+ else
64
+ # No package manager available — skip check, allow idle
65
+ exit 0
66
+ fi
67
+
68
+ exit 0
@@ -0,0 +1,184 @@
1
+ {
2
+ // ═══════════════════════════════════════════════════════════════════════
3
+ // Claude Code Settings — Agent Teams + tmux Configuration
4
+ // ═══════════════════════════════════════════════════════════════════════
5
+ //
6
+ // Copy this to ~/.claude/settings.json and customize for your project.
7
+ //
8
+ // NOTE: Standard JSON does not support comments. This file uses JSONC
9
+ // (JSON with Comments) syntax for documentation purposes. Before using
10
+ // as your actual settings.json, either:
11
+ // 1. Use an editor that supports JSONC (VS Code, Zed, etc.)
12
+ // 2. Strip comments: sed '/^\s*\/\//d' settings.json.template > settings.json
13
+ //
14
+ // Docs: https://docs.anthropic.com/en/docs/claude-code/settings
15
+
16
+ // ─── Teammate Mode ────────────────────────────────────────────────────
17
+ // Agent teams auto-detect tmux: when you launch Claude Code inside a
18
+ // tmux session, teammates automatically get their own split panes.
19
+ // No explicit setting needed — just run inside tmux!
20
+ //
21
+ // TIP: Use `new-window` (not `split-window`) when spawning 4+ agents
22
+ // to avoid the tmux send-keys race condition. See KNOWN-ISSUES.md.
23
+
24
+ // ─── Hooks ─────────────────────────────────────────────────────────────
25
+ // Shell commands that run on lifecycle events.
26
+ // See claude-code/hooks/ for the scripts referenced below.
27
+ // Docs: https://code.claude.com/docs/en/hooks-guide
28
+ //
29
+ // Event reference:
30
+ // TeammateIdle — when an agent teammate is about to go idle
31
+ // TaskCompleted — when a task is being marked as completed
32
+ // Notification — when Claude needs your attention
33
+ // Stop — when Claude finishes responding
34
+ // PreCompact — before context window compaction
35
+ // PostToolUse — after a tool call succeeds (e.g., auto-format)
36
+ // SessionStart — when a session begins or resumes
37
+ //
38
+ // Exit codes: 0 = allow, 2 = block action (agent gets feedback to fix)
39
+ "hooks": {
40
+ // Quality gate: block idle if typecheck fails
41
+ "TeammateIdle": [
42
+ {
43
+ "hooks": [
44
+ {
45
+ "type": "command",
46
+ "command": "~/.claude/hooks/teammate-idle.sh",
47
+ "timeout": 30,
48
+ "statusMessage": "Running typecheck before idle..."
49
+ }
50
+ ]
51
+ }
52
+ ],
53
+ // Quality gate: block task completion if lint/tests fail
54
+ "TaskCompleted": [
55
+ {
56
+ "hooks": [
57
+ {
58
+ "type": "command",
59
+ "command": "~/.claude/hooks/task-completed.sh",
60
+ "timeout": 60,
61
+ "statusMessage": "Running quality checks..."
62
+ }
63
+ ]
64
+ }
65
+ ],
66
+ // Desktop notification when Claude needs attention
67
+ "Notification": [
68
+ {
69
+ "hooks": [
70
+ {
71
+ "type": "command",
72
+ "command": "~/.claude/hooks/notify-idle.sh",
73
+ "async": true
74
+ }
75
+ ]
76
+ }
77
+ ],
78
+ // Save context before compaction
79
+ "PreCompact": [
80
+ {
81
+ "matcher": "auto",
82
+ "hooks": [
83
+ {
84
+ "type": "command",
85
+ "command": "~/.claude/hooks/pre-compact-save.sh",
86
+ "statusMessage": "Saving context before compaction..."
87
+ }
88
+ ]
89
+ }
90
+ ],
91
+ // Auto-format files after Claude edits them
92
+ "PostToolUse": [
93
+ {
94
+ "matcher": "Edit|Write",
95
+ "hooks": [
96
+ {
97
+ "type": "command",
98
+ "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write 2>/dev/null || true"
99
+ }
100
+ ]
101
+ }
102
+ ]
103
+ },
104
+
105
+ // ─── Status Line ──────────────────────────────────────────────────────
106
+ // Custom status line shown at the bottom of Claude Code.
107
+ // "type": "command" — runs a shell script and displays its stdout
108
+ // "type": "static" — shows fixed text
109
+ //
110
+ // Uncomment to enable:
111
+ // "statusLine": {
112
+ // "type": "command",
113
+ // "command": "echo \"$(git branch --show-current) | $(date +%H:%M)\""
114
+ // },
115
+
116
+ // ─── Plugins ──────────────────────────────────────────────────────────
117
+ // Enable/disable official and community plugins.
118
+ // Browse available plugins: claude plugins list
119
+ "enabledPlugins": {
120
+ // Code quality & review
121
+ "typescript-lsp@claude-plugins-official": true,
122
+ "feature-dev@claude-plugins-official": true,
123
+ "code-review@claude-plugins-official": true,
124
+ "pr-review-toolkit@claude-plugins-official": true,
125
+ "commit-commands@claude-plugins-official": true,
126
+
127
+ // Integrations — enable the ones you use
128
+ "github@claude-plugins-official": true,
129
+ "linear@claude-plugins-official": false,
130
+ "firebase@claude-plugins-official": false,
131
+ "slack@claude-plugins-official": false,
132
+
133
+ // Documentation & context
134
+ "context7@claude-plugins-official": true,
135
+ "frontend-design@claude-plugins-official": false,
136
+
137
+ // Workflow & output styles
138
+ "hookify@claude-plugins-official": true,
139
+ "learning-output-style@claude-plugins-official": false,
140
+ "explanatory-output-style@claude-plugins-official": false
141
+ },
142
+
143
+ // ─── Extended Thinking ────────────────────────────────────────────────
144
+ // When true, Claude thinks through complex problems step-by-step.
145
+ // Recommended for agent teams doing multi-file coordinated work.
146
+ "alwaysThinkingEnabled": true,
147
+
148
+ // ─── Environment Variables ────────────────────────────────────────────
149
+ // These env vars configure Claude Code's runtime behavior.
150
+ "env": {
151
+ // REQUIRED: Enable agent teams feature
152
+ "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
153
+
154
+ // Performance: max concurrent tool calls per agent (default: 3)
155
+ // Higher = faster parallel work, but more API usage
156
+ "CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY": "5",
157
+
158
+ // Auto-compact conversation when context usage hits this % (default: 80)
159
+ // Lower = more aggressive compaction, less risk of hitting limits
160
+ "CLAUDE_CODE_AUTOCOMPACT_PCT_OVERRIDE": "70",
161
+
162
+ // Use haiku for subagent tasks (cheaper + faster for simple lookups)
163
+ // Remove to use the same model as the parent agent
164
+ "CLAUDE_CODE_SUBAGENT_MODEL": "haiku",
165
+
166
+ // Include hidden files (dotfiles) in glob searches
167
+ "CLAUDE_CODE_GLOB_HIDDEN": "1",
168
+
169
+ // Keep bash working directory consistent across tool calls
170
+ "CLAUDE_CODE_BASH_MAINTAIN_PROJECT_WORKING_DIR": "1",
171
+
172
+ // Show tool use summaries in output (helpful for debugging agent behavior)
173
+ "CLAUDE_CODE_EMIT_TOOL_USE_SUMMARIES": "1",
174
+
175
+ // Show teammate names in messages (makes multi-agent output readable)
176
+ "CLAUDE_CODE_TST_NAMES_IN_MESSAGES": "1",
177
+
178
+ // Flush output eagerly (better for streaming, reduces perceived latency)
179
+ "CLAUDE_CODE_EAGER_FLUSH": "1",
180
+
181
+ // Enable prompt suggestions after idle
182
+ "CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION": "1"
183
+ }
184
+ }