shipwright-cli 1.7.0 → 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/.claude/agents/code-reviewer.md +90 -0
- package/.claude/agents/devops-engineer.md +142 -0
- package/.claude/agents/pipeline-agent.md +80 -0
- package/.claude/agents/shell-script-specialist.md +150 -0
- package/.claude/agents/test-specialist.md +196 -0
- package/.claude/hooks/post-tool-use.sh +38 -0
- package/.claude/hooks/pre-tool-use.sh +25 -0
- package/.claude/hooks/session-started.sh +37 -0
- package/README.md +212 -814
- package/claude-code/CLAUDE.md.shipwright +54 -0
- package/claude-code/hooks/notify-idle.sh +2 -2
- package/claude-code/hooks/session-start.sh +24 -0
- package/claude-code/hooks/task-completed.sh +6 -2
- package/claude-code/settings.json.template +12 -0
- package/dashboard/public/app.js +4422 -0
- package/dashboard/public/index.html +816 -0
- package/dashboard/public/styles.css +4755 -0
- package/dashboard/server.ts +4315 -0
- package/docs/KNOWN-ISSUES.md +18 -10
- package/docs/TIPS.md +38 -26
- package/docs/patterns/README.md +33 -23
- package/package.json +9 -5
- package/scripts/adapters/iterm2-adapter.sh +1 -1
- package/scripts/adapters/tmux-adapter.sh +52 -23
- package/scripts/adapters/wezterm-adapter.sh +26 -14
- package/scripts/lib/compat.sh +200 -0
- package/scripts/lib/helpers.sh +72 -0
- package/scripts/postinstall.mjs +72 -13
- package/scripts/{cct → sw} +109 -21
- package/scripts/sw-adversarial.sh +274 -0
- package/scripts/sw-architecture-enforcer.sh +330 -0
- package/scripts/sw-checkpoint.sh +390 -0
- package/scripts/{cct-cleanup.sh → sw-cleanup.sh} +3 -1
- package/scripts/sw-connect.sh +619 -0
- package/scripts/{cct-cost.sh → sw-cost.sh} +368 -34
- package/scripts/{cct-daemon.sh → sw-daemon.sh} +2217 -204
- package/scripts/sw-dashboard.sh +477 -0
- package/scripts/sw-developer-simulation.sh +252 -0
- package/scripts/sw-docs.sh +635 -0
- package/scripts/sw-doctor.sh +907 -0
- package/scripts/{cct-fix.sh → sw-fix.sh} +10 -6
- package/scripts/{cct-fleet.sh → sw-fleet.sh} +498 -22
- package/scripts/sw-github-checks.sh +521 -0
- package/scripts/sw-github-deploy.sh +533 -0
- package/scripts/sw-github-graphql.sh +972 -0
- package/scripts/sw-heartbeat.sh +293 -0
- package/scripts/sw-init.sh +522 -0
- package/scripts/sw-intelligence.sh +1196 -0
- package/scripts/sw-jira.sh +643 -0
- package/scripts/sw-launchd.sh +364 -0
- package/scripts/sw-linear.sh +648 -0
- package/scripts/{cct-logs.sh → sw-logs.sh} +72 -2
- package/scripts/{cct-loop.sh → sw-loop.sh} +534 -44
- package/scripts/{cct-memory.sh → sw-memory.sh} +321 -38
- package/scripts/sw-patrol-meta.sh +417 -0
- package/scripts/sw-pipeline-composer.sh +455 -0
- package/scripts/{cct-pipeline.sh → sw-pipeline.sh} +2319 -178
- package/scripts/sw-predictive.sh +820 -0
- package/scripts/{cct-prep.sh → sw-prep.sh} +339 -49
- package/scripts/{cct-ps.sh → sw-ps.sh} +6 -4
- package/scripts/{cct-reaper.sh → sw-reaper.sh} +6 -4
- package/scripts/sw-remote.sh +687 -0
- package/scripts/sw-self-optimize.sh +947 -0
- package/scripts/sw-session.sh +519 -0
- package/scripts/sw-setup.sh +234 -0
- package/scripts/sw-status.sh +605 -0
- package/scripts/{cct-templates.sh → sw-templates.sh} +9 -4
- package/scripts/sw-tmux.sh +591 -0
- package/scripts/sw-tracker-jira.sh +277 -0
- package/scripts/sw-tracker-linear.sh +292 -0
- package/scripts/sw-tracker.sh +409 -0
- package/scripts/{cct-upgrade.sh → sw-upgrade.sh} +103 -46
- package/scripts/{cct-worktree.sh → sw-worktree.sh} +3 -0
- package/templates/pipelines/autonomous.json +27 -5
- package/templates/pipelines/full.json +12 -0
- package/templates/pipelines/standard.json +12 -0
- package/tmux/{claude-teams-overlay.conf → shipwright-overlay.conf} +27 -9
- package/tmux/templates/accessibility.json +34 -0
- package/tmux/templates/api-design.json +35 -0
- package/tmux/templates/architecture.json +1 -0
- package/tmux/templates/bug-fix.json +9 -0
- package/tmux/templates/code-review.json +1 -0
- package/tmux/templates/compliance.json +36 -0
- package/tmux/templates/data-pipeline.json +36 -0
- package/tmux/templates/debt-paydown.json +34 -0
- package/tmux/templates/devops.json +1 -0
- package/tmux/templates/documentation.json +1 -0
- package/tmux/templates/exploration.json +1 -0
- package/tmux/templates/feature-dev.json +1 -0
- package/tmux/templates/full-stack.json +8 -0
- package/tmux/templates/i18n.json +34 -0
- package/tmux/templates/incident-response.json +36 -0
- package/tmux/templates/migration.json +1 -0
- package/tmux/templates/observability.json +35 -0
- package/tmux/templates/onboarding.json +33 -0
- package/tmux/templates/performance.json +35 -0
- package/tmux/templates/refactor.json +1 -0
- package/tmux/templates/release.json +35 -0
- package/tmux/templates/security-audit.json +8 -0
- package/tmux/templates/spike.json +34 -0
- package/tmux/templates/testing.json +1 -0
- package/tmux/tmux.conf +98 -9
- package/scripts/cct-doctor.sh +0 -328
- package/scripts/cct-init.sh +0 -282
- package/scripts/cct-session.sh +0 -284
- package/scripts/cct-status.sh +0 -169
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "release",
|
|
3
|
+
"description": "Release management with preparation, validation, and announcement agents",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"release",
|
|
6
|
+
"version",
|
|
7
|
+
"publish",
|
|
8
|
+
"changelog",
|
|
9
|
+
"tag",
|
|
10
|
+
"package",
|
|
11
|
+
"ship",
|
|
12
|
+
"launch",
|
|
13
|
+
"npm publish"
|
|
14
|
+
],
|
|
15
|
+
"agents": [
|
|
16
|
+
{
|
|
17
|
+
"name": "preparer",
|
|
18
|
+
"role": "Changelog generation, version bumps, dependency audit, license check, breaking change detection",
|
|
19
|
+
"focus": "package.json, CHANGELOG.md, Cargo.toml, go.mod, *.lock, version.*"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"name": "validator",
|
|
23
|
+
"role": "Full test suite, smoke tests, canary checks, rollback verification, binary/package size check",
|
|
24
|
+
"focus": "*.test.*, scripts/, e2e/, *.spec.*"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "announcer",
|
|
28
|
+
"role": "Release notes, migration guide, deprecation notices, upgrade instructions, API diff summary",
|
|
29
|
+
"focus": "docs/, *.md, CHANGELOG.md, MIGRATION.md, UPGRADING.md"
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"layout": "tiled",
|
|
33
|
+
"layout_style": "main-horizontal",
|
|
34
|
+
"main_pane_percent": 65
|
|
35
|
+
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "security-audit",
|
|
3
3
|
"description": "Security audit with code analysis, dependency scanning, and config review agents",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"security",
|
|
6
|
+
"vulnerability",
|
|
7
|
+
"xss",
|
|
8
|
+
"injection",
|
|
9
|
+
"auth",
|
|
10
|
+
"patch"
|
|
11
|
+
],
|
|
4
12
|
"agents": [
|
|
5
13
|
{
|
|
6
14
|
"name": "code-analysis",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "spike",
|
|
3
|
+
"description": "Proof of concept and technical spike with researcher, prototyper, and evaluator agents",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"spike",
|
|
6
|
+
"poc",
|
|
7
|
+
"proof of concept",
|
|
8
|
+
"prototype",
|
|
9
|
+
"experiment",
|
|
10
|
+
"evaluate",
|
|
11
|
+
"feasibility",
|
|
12
|
+
"compare"
|
|
13
|
+
],
|
|
14
|
+
"agents": [
|
|
15
|
+
{
|
|
16
|
+
"name": "researcher",
|
|
17
|
+
"role": "Evaluate libraries, APIs, and approaches. Compare trade-offs, licensing, maintenance status, community support.",
|
|
18
|
+
"focus": "docs/, package.json, go.mod, Cargo.toml, requirements.txt"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "prototyper",
|
|
22
|
+
"role": "Build minimal working prototype. Throwaway code is fine — optimize for speed of learning, not production quality.",
|
|
23
|
+
"focus": "spike/, prototype/, src/"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "evaluator",
|
|
27
|
+
"role": "Write decision document with recommendation, risks, migration path, and effort estimate. Zero attachment to the prototype.",
|
|
28
|
+
"focus": "docs/, *.md, spike/"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"layout": "tiled",
|
|
32
|
+
"layout_style": "main-horizontal",
|
|
33
|
+
"main_pane_percent": 65
|
|
34
|
+
}
|
package/tmux/tmux.conf
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ╔═══════════════════════════════════════════════════════════════════════════╗
|
|
2
2
|
# ║ TMUX CONFIGURATION ║
|
|
3
|
-
# ║
|
|
3
|
+
# ║ Shipwright — Optimized for Claude Code ║
|
|
4
4
|
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
5
5
|
|
|
6
6
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -8,16 +8,63 @@
|
|
|
8
8
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
9
9
|
|
|
10
10
|
set -g default-terminal "tmux-256color"
|
|
11
|
+
|
|
12
|
+
# ─── Terminal-specific overrides ────────────────────────────────────────
|
|
13
|
+
# True color + italics for modern terminals
|
|
11
14
|
set -ag terminal-overrides ",xterm-256color:RGB"
|
|
15
|
+
set -ag terminal-overrides ",xterm-256color:Tc"
|
|
16
|
+
set -ag terminal-overrides ",iTerm2*:RGB:Tc"
|
|
17
|
+
# Ghostty, kitty, WezTerm, Alacritty true color
|
|
18
|
+
set -ag terminal-overrides ",xterm-ghostty:RGB:Tc"
|
|
19
|
+
set -ag terminal-overrides ",xterm-kitty:RGB:Tc"
|
|
20
|
+
set -ag terminal-overrides ",wezterm:RGB:Tc"
|
|
21
|
+
set -ag terminal-overrides ",alacritty:RGB:Tc"
|
|
22
|
+
# Styled underline (curly, dotted, dashed)
|
|
23
|
+
set -ag terminal-overrides ",*:Smulx=\\E[4::%p1%dm"
|
|
24
|
+
set -ag terminal-overrides ",*:Setulc=\\E[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m"
|
|
25
|
+
# Terminal.app: 256 color only, basic mouse
|
|
26
|
+
set -ag terminal-overrides ",Apple_Terminal*:colors=256"
|
|
27
|
+
|
|
28
|
+
# ─── Claude Code TUI Compatibility ────────────────────────────────────
|
|
29
|
+
# Passthrough: enables DEC 2026 synchronized output (eliminates flicker),
|
|
30
|
+
# OSC 52 clipboard, OSC notifications, and image protocols.
|
|
31
|
+
# Critical for Claude Code's rapid TUI updates inside tmux.
|
|
32
|
+
set -g allow-passthrough on
|
|
33
|
+
|
|
34
|
+
# Extended keys: lets TUI apps (Claude Code, vim, etc.) receive modifier
|
|
35
|
+
# key combos that plain terminals would swallow (Ctrl+Shift+key, etc.)
|
|
36
|
+
set -g extended-keys on
|
|
37
|
+
set -as terminal-features 'xterm*:extkeys'
|
|
38
|
+
|
|
39
|
+
# ─── Mouse ──────────────────────────────────────────────────────────────
|
|
12
40
|
set -g mouse on
|
|
41
|
+
# Fix: tmux 3.4+ defaults MouseDown1Status to switch-client (sessions),
|
|
42
|
+
# but we want select-window so clicking status bar windows actually works
|
|
43
|
+
bind -T root MouseDown1Status select-window -t =
|
|
44
|
+
# Double-click on status bar word to rename window
|
|
45
|
+
bind -T root DoubleClick1Status command-prompt -I "#W" "rename-window -- '%%'"
|
|
46
|
+
|
|
47
|
+
# ─── Core Behavior ─────────────────────────────────────────────────────
|
|
13
48
|
set -g base-index 1
|
|
14
49
|
setw -g pane-base-index 1
|
|
15
50
|
set -g renumber-windows on
|
|
16
|
-
set -g history-limit 50000
|
|
17
51
|
set -sg escape-time 0
|
|
18
52
|
set -g focus-events on
|
|
19
53
|
setw -g monitor-activity on
|
|
20
54
|
set -g visual-activity off
|
|
55
|
+
# Display messages for 3 seconds (default 750ms is too fast)
|
|
56
|
+
set -g display-time 3000
|
|
57
|
+
# Display pane indicators for 2 seconds
|
|
58
|
+
set -g display-panes-time 2000
|
|
59
|
+
# Smoother repeated key operations (600ms window)
|
|
60
|
+
set -g repeat-time 600
|
|
61
|
+
# Clipboard: native OSC 52 — copies work across SSH + tmux nesting
|
|
62
|
+
set -g set-clipboard on
|
|
63
|
+
|
|
64
|
+
# ─── History ───────────────────────────────────────────────────────────
|
|
65
|
+
# Claude Code generates 4,000-6,700 scroll events/sec during streaming.
|
|
66
|
+
# 250k lines prevents buffer exhaustion during long agent runs.
|
|
67
|
+
set -g history-limit 250000
|
|
21
68
|
|
|
22
69
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
23
70
|
# STATUS BAR CONFIGURATION
|
|
@@ -35,14 +82,12 @@ set -g status-left "#[fg=#1e1e32,bg=#00d4ff,bold] #S #[fg=#00d4ff,bg=#0066ff]#[
|
|
|
35
82
|
|
|
36
83
|
setw -g window-status-separator " "
|
|
37
84
|
# Inactive windows; team windows (claude-*) get a λ icon
|
|
38
|
-
# NOTE: use separate #[fg=]#[bg=] blocks — commas inside #{?} branches break parsing
|
|
39
85
|
setw -g window-status-format "#{?#{m:claude-*,#W},#[fg=#7c3aed]#[bg=#252538] λ #I:#W ,#[fg=#71717a]#[bg=#252538] #I:#W }#[fg=#252538]#[bg=#1a1a2e]"
|
|
40
86
|
# Active window; team windows get λ icon in cyan
|
|
41
87
|
setw -g window-status-current-format "#{?#{m:claude-*,#W},#[fg=#1e1e32]#[bg=#00d4ff]#[bold] λ #I:#W ,#[fg=#1e1e32]#[bg=#00d4ff]#[bold] #I:#W }#[fg=#00d4ff]#[bg=#1a1a2e]"
|
|
42
88
|
|
|
43
|
-
# Right side:
|
|
44
|
-
#
|
|
45
|
-
set -g status-right "#{?client_prefix,#[fg=#1e1e32]#[bg=#0066ff]#[bold] T team | split - split hjkl nav G zoom S sync x kill #[fg=#1e1e32]#[bg=#00d4ff]#[bold] ^a ,#[fg=#71717a]#[bg=#252538] #(whoami)@#h #[fg=#1e1e32]#[bg=#7c3aed]#[bold] %H:%M #[fg=#e4e4e7]#[bg=#0066ff]#[bold] %b %d #[fg=#1e1e32]#[bg=#00d4ff]#[bold] %a }"
|
|
89
|
+
# Right side: key hints when prefix is active, otherwise clock + date
|
|
90
|
+
set -g status-right "#{?client_prefix,#[fg=#1e1e32]#[bg=#0066ff]#[bold] T team | split - split hjkl nav G zoom S sync x kill F fzf #[fg=#1e1e32]#[bg=#00d4ff]#[bold] ^a ,#[fg=#71717a]#[bg=#252538] #(whoami)@#h #[fg=#1e1e32]#[bg=#7c3aed]#[bold] %H:%M #[fg=#e4e4e7]#[bg=#0066ff]#[bold] %b %d #[fg=#1e1e32]#[bg=#00d4ff]#[bold] %a }"
|
|
46
91
|
|
|
47
92
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
48
93
|
# PANE STYLING
|
|
@@ -52,9 +97,16 @@ set -g window-style 'bg=#1a1a2e,fg=#e4e4e7'
|
|
|
52
97
|
set -g window-active-style 'bg=#1a1a2e,fg=#e4e4e7'
|
|
53
98
|
set -g pane-border-style "fg=#333355,bg=#1a1a2e"
|
|
54
99
|
set -g pane-active-border-style "fg=#00d4ff,bg=#1a1a2e"
|
|
100
|
+
# Heavy pane border lines for better visibility (tmux 3.2+)
|
|
101
|
+
set -g pane-border-lines heavy
|
|
55
102
|
set -g display-panes-colour "#333355"
|
|
56
103
|
set -g display-panes-active-colour "#00d4ff"
|
|
57
104
|
|
|
105
|
+
# ─── Popup Styling (tmux 3.3+) ─────────────────────────────────────────
|
|
106
|
+
set -gq popup-style 'bg=#252538'
|
|
107
|
+
set -gq popup-border-style 'fg=#00d4ff'
|
|
108
|
+
set -gq popup-border-lines rounded
|
|
109
|
+
|
|
58
110
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
59
111
|
# MESSAGE STYLING
|
|
60
112
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -139,23 +191,54 @@ bind s choose-tree -sZ -O name
|
|
|
139
191
|
bind N new-session
|
|
140
192
|
|
|
141
193
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
142
|
-
#
|
|
194
|
+
# FLOATING POPUP TERMINALS (tmux 3.2+)
|
|
195
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
196
|
+
|
|
197
|
+
# prefix + F → floating popup terminal in current directory
|
|
198
|
+
bind F display-popup -E -w 80% -h 75% -d "#{pane_current_path}"
|
|
199
|
+
|
|
200
|
+
# prefix + C-f → FZF session/window switcher in a popup
|
|
201
|
+
bind C-f display-popup -E -w 60% -h 50% "\
|
|
202
|
+
tmux list-sessions -F '#{session_name}' | \
|
|
203
|
+
fzf --reverse --header='Switch session' | \
|
|
204
|
+
xargs -I{} tmux switch-client -t {}"
|
|
205
|
+
|
|
206
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
207
|
+
# PLUGINS (via TPM)
|
|
143
208
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
144
209
|
|
|
145
210
|
set -g @plugin 'tmux-plugins/tpm'
|
|
146
211
|
set -g @plugin 'tmux-plugins/tmux-sensible'
|
|
147
212
|
set -g @plugin 'tmux-plugins/tmux-resurrect'
|
|
148
213
|
set -g @plugin 'tmux-plugins/tmux-continuum'
|
|
214
|
+
set -g @plugin 'tmux-plugins/tmux-yank'
|
|
215
|
+
set -g @plugin 'sainnhe/tmux-fzf'
|
|
216
|
+
|
|
217
|
+
# ─── Plugin Configuration ──────────────────────────────────────────────
|
|
149
218
|
|
|
219
|
+
# Resurrect: persist full pane content + programs
|
|
150
220
|
set -g @resurrect-capture-pane-contents 'on'
|
|
221
|
+
set -g @resurrect-strategy-nvim 'session'
|
|
222
|
+
|
|
223
|
+
# Continuum: auto-save every 15 min, auto-restore on tmux start
|
|
151
224
|
set -g @continuum-restore 'on'
|
|
225
|
+
set -g @continuum-save-interval '15'
|
|
226
|
+
|
|
227
|
+
# Yank: use system clipboard, stay in copy mode after yanking
|
|
228
|
+
set -g @yank_selection_mouse 'clipboard'
|
|
229
|
+
set -g @yank_action 'copy-pipe'
|
|
230
|
+
|
|
231
|
+
# FZF: use popup window (tmux 3.2+), Shipwright color scheme
|
|
232
|
+
set -g @tmux-fzf-launch-key 'C-f'
|
|
233
|
+
TMUX_FZF_OPTIONS="-p -w 60% -h 50%"
|
|
234
|
+
TMUX_FZF_PREVIEW=0
|
|
152
235
|
|
|
153
236
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
154
|
-
#
|
|
237
|
+
# SHIPWRIGHT INTEGRATION
|
|
155
238
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
156
239
|
|
|
157
240
|
# Source teams overlay (agent pane styling, keybindings)
|
|
158
|
-
source-file -q ~/.tmux/
|
|
241
|
+
source-file -q ~/.tmux/shipwright-overlay.conf
|
|
159
242
|
|
|
160
243
|
# Quick launch: prefix + T → start a Claude team session
|
|
161
244
|
bind T run-shell "shipwright session"
|
|
@@ -163,5 +246,11 @@ bind T run-shell "shipwright session"
|
|
|
163
246
|
# Quick status: prefix + C-t → show team dashboard in floating popup
|
|
164
247
|
bind C-t display-popup -w 80% -h 70% -E "shipwright status; echo ''; echo 'Press ENTER to close'; read"
|
|
165
248
|
|
|
249
|
+
# Quick logs: prefix + C-l → tail agent logs in popup
|
|
250
|
+
bind M-L display-popup -w 85% -h 80% -E "shipwright logs --follow 2>/dev/null || echo 'No active logs'; echo ''; echo 'Press ENTER to close'; read"
|
|
251
|
+
|
|
252
|
+
# Quick cost: prefix + C-c → cost dashboard in popup
|
|
253
|
+
bind M-C display-popup -w 70% -h 60% -E "shipwright cost show 2>/dev/null || echo 'Cost tracking not configured'; echo ''; echo 'Press ENTER to close'; read"
|
|
254
|
+
|
|
166
255
|
# Initialize TPM (keep at very bottom)
|
|
167
256
|
run-shell '~/.tmux/plugins/tpm/tpm'
|
package/scripts/cct-doctor.sh
DELETED
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# ╔═══════════════════════════════════════════════════════════════════════════╗
|
|
3
|
-
# ║ cct-doctor.sh — Validate Claude Code Teams setup ║
|
|
4
|
-
# ║ ║
|
|
5
|
-
# ║ Checks prerequisites, installed files, PATH, and common issues. ║
|
|
6
|
-
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
7
|
-
set -euo pipefail
|
|
8
|
-
|
|
9
|
-
# ─── Colors ──────────────────────────────────────────────────────────────────
|
|
10
|
-
CYAN='\033[38;2;0;212;255m'
|
|
11
|
-
PURPLE='\033[38;2;124;58;237m'
|
|
12
|
-
BLUE='\033[38;2;0;102;255m'
|
|
13
|
-
GREEN='\033[38;2;74;222;128m'
|
|
14
|
-
YELLOW='\033[38;2;250;204;21m'
|
|
15
|
-
RED='\033[38;2;248;113;113m'
|
|
16
|
-
DIM='\033[2m'
|
|
17
|
-
BOLD='\033[1m'
|
|
18
|
-
RESET='\033[0m'
|
|
19
|
-
|
|
20
|
-
# ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
21
|
-
info() { echo -e "${CYAN}${BOLD}▸${RESET} $*"; }
|
|
22
|
-
success() { echo -e "${GREEN}${BOLD}✓${RESET} $*"; }
|
|
23
|
-
warn() { echo -e "${YELLOW}${BOLD}⚠${RESET} $*"; }
|
|
24
|
-
error() { echo -e "${RED}${BOLD}✗${RESET} $*"; }
|
|
25
|
-
|
|
26
|
-
PASS=0
|
|
27
|
-
WARN=0
|
|
28
|
-
FAIL=0
|
|
29
|
-
|
|
30
|
-
check_pass() { success "$*"; PASS=$((PASS + 1)); }
|
|
31
|
-
check_warn() { warn "$*"; WARN=$((WARN + 1)); }
|
|
32
|
-
check_fail() { error "$*"; FAIL=$((FAIL + 1)); }
|
|
33
|
-
|
|
34
|
-
# ─── Header ─────────────────────────────────────────────────────────────────
|
|
35
|
-
echo ""
|
|
36
|
-
echo -e "${CYAN}${BOLD} Claude Code Teams — Doctor${RESET}"
|
|
37
|
-
echo -e "${DIM} $(date '+%Y-%m-%d %H:%M:%S')${RESET}"
|
|
38
|
-
echo -e "${DIM} ══════════════════════════════════════════${RESET}"
|
|
39
|
-
echo ""
|
|
40
|
-
|
|
41
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
42
|
-
# 1. Prerequisites
|
|
43
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
44
|
-
echo -e "${PURPLE}${BOLD} PREREQUISITES${RESET}"
|
|
45
|
-
echo -e "${DIM} ──────────────────────────────────────────${RESET}"
|
|
46
|
-
|
|
47
|
-
# tmux
|
|
48
|
-
if command -v tmux &>/dev/null; then
|
|
49
|
-
TMUX_VERSION="$(tmux -V | grep -oE '[0-9]+\.[0-9a-z]+')"
|
|
50
|
-
TMUX_MAJOR="$(echo "$TMUX_VERSION" | cut -d. -f1)"
|
|
51
|
-
TMUX_MINOR="$(echo "$TMUX_VERSION" | cut -d. -f2 | tr -dc '0-9')"
|
|
52
|
-
if [[ "$TMUX_MAJOR" -ge 3 && "$TMUX_MINOR" -ge 2 ]] || [[ "$TMUX_MAJOR" -ge 4 ]]; then
|
|
53
|
-
check_pass "tmux ${TMUX_VERSION}"
|
|
54
|
-
else
|
|
55
|
-
check_warn "tmux ${TMUX_VERSION} — 3.2+ recommended for pane-border-format"
|
|
56
|
-
fi
|
|
57
|
-
else
|
|
58
|
-
check_fail "tmux not installed"
|
|
59
|
-
echo -e " ${DIM}brew install tmux (macOS)${RESET}"
|
|
60
|
-
echo -e " ${DIM}sudo apt install tmux (Ubuntu/Debian)${RESET}"
|
|
61
|
-
fi
|
|
62
|
-
|
|
63
|
-
# jq
|
|
64
|
-
if command -v jq &>/dev/null; then
|
|
65
|
-
check_pass "jq $(jq --version 2>&1 | tr -d 'jq-')"
|
|
66
|
-
else
|
|
67
|
-
check_fail "jq not installed — required for template parsing"
|
|
68
|
-
echo -e " ${DIM}brew install jq${RESET} (macOS)"
|
|
69
|
-
echo -e " ${DIM}sudo apt install jq${RESET} (Ubuntu/Debian)"
|
|
70
|
-
fi
|
|
71
|
-
|
|
72
|
-
# Claude Code CLI
|
|
73
|
-
if command -v claude &>/dev/null; then
|
|
74
|
-
check_pass "Claude Code CLI found"
|
|
75
|
-
else
|
|
76
|
-
check_fail "Claude Code CLI not found"
|
|
77
|
-
echo -e " ${DIM}npm install -g @anthropic-ai/claude-code${RESET}"
|
|
78
|
-
fi
|
|
79
|
-
|
|
80
|
-
# Node.js
|
|
81
|
-
if command -v node &>/dev/null; then
|
|
82
|
-
NODE_VERSION="$(node -v | tr -d 'v')"
|
|
83
|
-
NODE_MAJOR="$(echo "$NODE_VERSION" | cut -d. -f1)"
|
|
84
|
-
if [[ "$NODE_MAJOR" -ge 20 ]]; then
|
|
85
|
-
check_pass "Node.js ${NODE_VERSION}"
|
|
86
|
-
else
|
|
87
|
-
check_warn "Node.js ${NODE_VERSION} — 20+ recommended"
|
|
88
|
-
fi
|
|
89
|
-
else
|
|
90
|
-
check_fail "Node.js not found"
|
|
91
|
-
fi
|
|
92
|
-
|
|
93
|
-
# Git
|
|
94
|
-
if command -v git &>/dev/null; then
|
|
95
|
-
check_pass "git $(git --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')"
|
|
96
|
-
else
|
|
97
|
-
check_fail "git not found"
|
|
98
|
-
fi
|
|
99
|
-
|
|
100
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
101
|
-
# 2. Installed Files
|
|
102
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
103
|
-
echo ""
|
|
104
|
-
echo -e "${PURPLE}${BOLD} INSTALLED FILES${RESET}"
|
|
105
|
-
echo -e "${DIM} ──────────────────────────────────────────${RESET}"
|
|
106
|
-
|
|
107
|
-
# tmux overlay
|
|
108
|
-
if [[ -f "$HOME/.tmux/claude-teams-overlay.conf" ]]; then
|
|
109
|
-
check_pass "Overlay: ~/.tmux/claude-teams-overlay.conf"
|
|
110
|
-
else
|
|
111
|
-
check_fail "Overlay not found: ~/.tmux/claude-teams-overlay.conf"
|
|
112
|
-
echo -e " ${DIM}Re-run install.sh to install it${RESET}"
|
|
113
|
-
fi
|
|
114
|
-
|
|
115
|
-
# Overlay sourced in tmux.conf
|
|
116
|
-
if [[ -f "$HOME/.tmux.conf" ]]; then
|
|
117
|
-
if grep -q "claude-teams-overlay" "$HOME/.tmux.conf" 2>/dev/null; then
|
|
118
|
-
check_pass "Overlay sourced in ~/.tmux.conf"
|
|
119
|
-
else
|
|
120
|
-
check_warn "Overlay not sourced in ~/.tmux.conf"
|
|
121
|
-
echo -e " ${DIM}Add: source-file -q ~/.tmux/claude-teams-overlay.conf${RESET}"
|
|
122
|
-
fi
|
|
123
|
-
else
|
|
124
|
-
check_warn "No ~/.tmux.conf found"
|
|
125
|
-
fi
|
|
126
|
-
|
|
127
|
-
# Claude settings
|
|
128
|
-
if [[ -f "$HOME/.claude/settings.json" ]]; then
|
|
129
|
-
check_pass "Settings: ~/.claude/settings.json"
|
|
130
|
-
else
|
|
131
|
-
check_warn "No ~/.claude/settings.json"
|
|
132
|
-
echo -e " ${DIM}Copy from settings.json.template${RESET}"
|
|
133
|
-
fi
|
|
134
|
-
|
|
135
|
-
# Hooks directory
|
|
136
|
-
HOOKS_DIR="$HOME/.claude/hooks"
|
|
137
|
-
if [[ -d "$HOOKS_DIR" ]]; then
|
|
138
|
-
hook_count=0
|
|
139
|
-
non_exec=0
|
|
140
|
-
while IFS= read -r hook; do
|
|
141
|
-
[[ -z "$hook" ]] && continue
|
|
142
|
-
hook_count=$((hook_count + 1))
|
|
143
|
-
if [[ ! -x "$hook" ]]; then
|
|
144
|
-
non_exec=$((non_exec + 1))
|
|
145
|
-
fi
|
|
146
|
-
done < <(find "$HOOKS_DIR" -maxdepth 1 -name '*.sh' -type f 2>/dev/null)
|
|
147
|
-
|
|
148
|
-
if [[ $hook_count -gt 0 && $non_exec -eq 0 ]]; then
|
|
149
|
-
check_pass "Hooks: ${hook_count} scripts, all executable"
|
|
150
|
-
elif [[ $hook_count -gt 0 && $non_exec -gt 0 ]]; then
|
|
151
|
-
check_warn "Hooks: ${non_exec}/${hook_count} scripts not executable"
|
|
152
|
-
echo -e " ${DIM}chmod +x ~/.claude/hooks/*.sh${RESET}"
|
|
153
|
-
else
|
|
154
|
-
check_warn "Hooks dir exists but no .sh scripts found"
|
|
155
|
-
fi
|
|
156
|
-
else
|
|
157
|
-
check_warn "No hooks directory at ~/.claude/hooks/"
|
|
158
|
-
fi
|
|
159
|
-
|
|
160
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
161
|
-
# 3. PATH & CLI
|
|
162
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
163
|
-
echo ""
|
|
164
|
-
echo -e "${PURPLE}${BOLD} PATH & CLI${RESET}"
|
|
165
|
-
echo -e "${DIM} ──────────────────────────────────────────${RESET}"
|
|
166
|
-
|
|
167
|
-
BIN_DIR="$HOME/.local/bin"
|
|
168
|
-
|
|
169
|
-
if echo "$PATH" | tr ':' '\n' | grep -q "$BIN_DIR"; then
|
|
170
|
-
check_pass "${BIN_DIR} is in PATH"
|
|
171
|
-
else
|
|
172
|
-
check_warn "${BIN_DIR} is NOT in PATH"
|
|
173
|
-
echo -e " ${DIM}Add to ~/.zshrc or ~/.bashrc:${RESET}"
|
|
174
|
-
echo -e " ${DIM}export PATH=\"\$HOME/.local/bin:\$PATH\"${RESET}"
|
|
175
|
-
fi
|
|
176
|
-
|
|
177
|
-
# Check cct subcommands are installed alongside the router
|
|
178
|
-
if command -v cct &>/dev/null; then
|
|
179
|
-
CCT_DIR="$(dirname "$(command -v cct)")"
|
|
180
|
-
check_pass "shipwright router found at ${CCT_DIR}/cct"
|
|
181
|
-
|
|
182
|
-
missing_subs=()
|
|
183
|
-
for sub in cct-session.sh cct-status.sh cct-cleanup.sh; do
|
|
184
|
-
if [[ ! -x "${CCT_DIR}/${sub}" ]]; then
|
|
185
|
-
missing_subs+=("$sub")
|
|
186
|
-
fi
|
|
187
|
-
done
|
|
188
|
-
|
|
189
|
-
if [[ ${#missing_subs[@]} -eq 0 ]]; then
|
|
190
|
-
check_pass "All core subcommands installed"
|
|
191
|
-
else
|
|
192
|
-
check_warn "Missing subcommands: ${missing_subs[*]}"
|
|
193
|
-
echo -e " ${DIM}Re-run install.sh or shipwright upgrade --apply${RESET}"
|
|
194
|
-
fi
|
|
195
|
-
else
|
|
196
|
-
check_fail "shipwright command not found in PATH"
|
|
197
|
-
echo -e " ${DIM}Re-run install.sh to install the CLI${RESET}"
|
|
198
|
-
fi
|
|
199
|
-
|
|
200
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
201
|
-
# 4. Pane Display
|
|
202
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
203
|
-
echo ""
|
|
204
|
-
echo -e "${PURPLE}${BOLD} PANE DISPLAY${RESET}"
|
|
205
|
-
echo -e "${DIM} ──────────────────────────────────────────${RESET}"
|
|
206
|
-
|
|
207
|
-
# Check overlay file exists
|
|
208
|
-
if [[ -f "$HOME/.tmux/claude-teams-overlay.conf" ]]; then
|
|
209
|
-
# Check for set-hook color enforcement
|
|
210
|
-
if grep -q "set-hook.*after-split-window" "$HOME/.tmux/claude-teams-overlay.conf" 2>/dev/null; then
|
|
211
|
-
check_pass "Overlay has color hooks (set-hook)"
|
|
212
|
-
else
|
|
213
|
-
check_warn "Overlay missing color hooks — new panes may flash white"
|
|
214
|
-
echo -e " ${DIM}Run: shipwright upgrade --apply or shipwright init${RESET}"
|
|
215
|
-
fi
|
|
216
|
-
else
|
|
217
|
-
check_fail "Overlay not found — pane display features unavailable"
|
|
218
|
-
fi
|
|
219
|
-
|
|
220
|
-
# Check if set-hook commands are active in tmux
|
|
221
|
-
if [[ -n "${TMUX:-}" ]]; then
|
|
222
|
-
if tmux show-hooks -g 2>/dev/null | grep -q "after-split-window"; then
|
|
223
|
-
check_pass "set-hook commands active in tmux"
|
|
224
|
-
else
|
|
225
|
-
check_warn "set-hook commands not active — reload config: prefix + r"
|
|
226
|
-
fi
|
|
227
|
-
|
|
228
|
-
# Check default-terminal
|
|
229
|
-
TMUX_TERM="$(tmux show-option -gv default-terminal 2>/dev/null || echo "unknown")"
|
|
230
|
-
if [[ "$TMUX_TERM" == *"256color"* ]]; then
|
|
231
|
-
check_pass "default-terminal: $TMUX_TERM"
|
|
232
|
-
else
|
|
233
|
-
check_warn "default-terminal: $TMUX_TERM — 256color variant recommended"
|
|
234
|
-
echo -e " ${DIM}set -g default-terminal 'tmux-256color'${RESET}"
|
|
235
|
-
fi
|
|
236
|
-
|
|
237
|
-
# Check pane border includes cyan accent
|
|
238
|
-
BORDER_FMT="$(tmux show-option -gv pane-border-format 2>/dev/null || echo "")"
|
|
239
|
-
if echo "$BORDER_FMT" | grep -q "#00d4ff"; then
|
|
240
|
-
check_pass "Pane border format includes cyan accent"
|
|
241
|
-
else
|
|
242
|
-
check_warn "Pane border format missing cyan accent — overlay may not be loaded"
|
|
243
|
-
fi
|
|
244
|
-
else
|
|
245
|
-
info "Not in tmux session — skipping runtime display checks"
|
|
246
|
-
fi
|
|
247
|
-
|
|
248
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
249
|
-
# 5. Orphaned Sessions
|
|
250
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
251
|
-
echo ""
|
|
252
|
-
echo -e "${PURPLE}${BOLD} ORPHAN CHECK${RESET}"
|
|
253
|
-
echo -e "${DIM} ──────────────────────────────────────────${RESET}"
|
|
254
|
-
|
|
255
|
-
orphaned_teams=0
|
|
256
|
-
TEAMS_DIR="$HOME/.claude/teams"
|
|
257
|
-
if [[ -d "$TEAMS_DIR" ]]; then
|
|
258
|
-
while IFS= read -r team_dir; do
|
|
259
|
-
[[ -z "$team_dir" ]] && continue
|
|
260
|
-
team_name="$(basename "$team_dir")"
|
|
261
|
-
config_file="${team_dir}/config.json"
|
|
262
|
-
if [[ ! -f "$config_file" ]]; then
|
|
263
|
-
orphaned_teams=$((orphaned_teams + 1))
|
|
264
|
-
check_warn "Orphaned team dir: ${team_name} (no config.json)"
|
|
265
|
-
fi
|
|
266
|
-
done < <(find "$TEAMS_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null)
|
|
267
|
-
fi
|
|
268
|
-
|
|
269
|
-
if [[ $orphaned_teams -eq 0 ]]; then
|
|
270
|
-
check_pass "No orphaned team sessions"
|
|
271
|
-
fi
|
|
272
|
-
|
|
273
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
274
|
-
# 6. Terminal Compatibility
|
|
275
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
276
|
-
echo ""
|
|
277
|
-
echo -e "${PURPLE}${BOLD} TERMINAL${RESET}"
|
|
278
|
-
echo -e "${DIM} ──────────────────────────────────────────${RESET}"
|
|
279
|
-
|
|
280
|
-
TERM_PROGRAM="${TERM_PROGRAM:-unknown}"
|
|
281
|
-
|
|
282
|
-
case "$TERM_PROGRAM" in
|
|
283
|
-
iTerm.app|iTerm2)
|
|
284
|
-
check_pass "iTerm2 — full support"
|
|
285
|
-
;;
|
|
286
|
-
Apple_Terminal)
|
|
287
|
-
check_pass "Terminal.app — supported"
|
|
288
|
-
;;
|
|
289
|
-
WezTerm)
|
|
290
|
-
check_pass "WezTerm — full support"
|
|
291
|
-
;;
|
|
292
|
-
tmux)
|
|
293
|
-
check_pass "Running inside tmux (nested)"
|
|
294
|
-
;;
|
|
295
|
-
vscode)
|
|
296
|
-
check_warn "VS Code integrated terminal"
|
|
297
|
-
echo -e " ${DIM}Some pane border features may not render correctly.${RESET}"
|
|
298
|
-
echo -e " ${DIM}Consider running tmux in an external terminal.${RESET}"
|
|
299
|
-
;;
|
|
300
|
-
Ghostty)
|
|
301
|
-
check_warn "Ghostty — may have tmux rendering quirks"
|
|
302
|
-
echo -e " ${DIM}If pane borders look wrong, try: set -g default-terminal 'xterm-256color'${RESET}"
|
|
303
|
-
;;
|
|
304
|
-
*)
|
|
305
|
-
info "Terminal: ${TERM_PROGRAM}"
|
|
306
|
-
;;
|
|
307
|
-
esac
|
|
308
|
-
|
|
309
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
310
|
-
# Summary
|
|
311
|
-
# ═════════════════════════════════════════════════════════════════════════════
|
|
312
|
-
echo ""
|
|
313
|
-
echo -e "${DIM} ══════════════════════════════════════════${RESET}"
|
|
314
|
-
echo ""
|
|
315
|
-
|
|
316
|
-
TOTAL=$((PASS + WARN + FAIL))
|
|
317
|
-
|
|
318
|
-
echo -e " ${GREEN}${BOLD}${PASS}${RESET} passed ${YELLOW}${BOLD}${WARN}${RESET} warnings ${RED}${BOLD}${FAIL}${RESET} failed ${DIM}(${TOTAL} checks)${RESET}"
|
|
319
|
-
echo ""
|
|
320
|
-
|
|
321
|
-
if [[ $FAIL -gt 0 ]]; then
|
|
322
|
-
error "Some checks failed. Fix the issues above and re-run ${CYAN}shipwright doctor${RESET}"
|
|
323
|
-
elif [[ $WARN -gt 0 ]]; then
|
|
324
|
-
warn "Setup mostly OK, but there are warnings above"
|
|
325
|
-
else
|
|
326
|
-
success "Everything looks good!"
|
|
327
|
-
fi
|
|
328
|
-
echo ""
|