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.
- package/LICENSE +21 -0
- package/README.md +926 -0
- package/claude-code/CLAUDE.md.shipwright +125 -0
- package/claude-code/hooks/notify-idle.sh +35 -0
- package/claude-code/hooks/pre-compact-save.sh +57 -0
- package/claude-code/hooks/task-completed.sh +170 -0
- package/claude-code/hooks/teammate-idle.sh +68 -0
- package/claude-code/settings.json.template +184 -0
- package/completions/_shipwright +140 -0
- package/completions/shipwright.bash +89 -0
- package/completions/shipwright.fish +107 -0
- package/docs/KNOWN-ISSUES.md +199 -0
- package/docs/TIPS.md +331 -0
- package/docs/definition-of-done.example.md +16 -0
- package/docs/patterns/README.md +139 -0
- package/docs/patterns/audit-loop.md +149 -0
- package/docs/patterns/bug-hunt.md +183 -0
- package/docs/patterns/feature-implementation.md +159 -0
- package/docs/patterns/refactoring.md +183 -0
- package/docs/patterns/research-exploration.md +144 -0
- package/docs/patterns/test-generation.md +173 -0
- package/package.json +49 -0
- package/scripts/adapters/docker-deploy.sh +50 -0
- package/scripts/adapters/fly-deploy.sh +41 -0
- package/scripts/adapters/iterm2-adapter.sh +122 -0
- package/scripts/adapters/railway-deploy.sh +34 -0
- package/scripts/adapters/tmux-adapter.sh +87 -0
- package/scripts/adapters/vercel-deploy.sh +35 -0
- package/scripts/adapters/wezterm-adapter.sh +103 -0
- package/scripts/cct +242 -0
- package/scripts/cct-cleanup.sh +172 -0
- package/scripts/cct-cost.sh +590 -0
- package/scripts/cct-daemon.sh +3189 -0
- package/scripts/cct-doctor.sh +328 -0
- package/scripts/cct-fix.sh +478 -0
- package/scripts/cct-fleet.sh +904 -0
- package/scripts/cct-init.sh +282 -0
- package/scripts/cct-logs.sh +273 -0
- package/scripts/cct-loop.sh +1332 -0
- package/scripts/cct-memory.sh +1148 -0
- package/scripts/cct-pipeline.sh +3844 -0
- package/scripts/cct-prep.sh +1352 -0
- package/scripts/cct-ps.sh +168 -0
- package/scripts/cct-reaper.sh +390 -0
- package/scripts/cct-session.sh +284 -0
- package/scripts/cct-status.sh +169 -0
- package/scripts/cct-templates.sh +242 -0
- package/scripts/cct-upgrade.sh +422 -0
- package/scripts/cct-worktree.sh +405 -0
- package/scripts/postinstall.mjs +96 -0
- package/templates/pipelines/autonomous.json +71 -0
- package/templates/pipelines/cost-aware.json +95 -0
- package/templates/pipelines/deployed.json +79 -0
- package/templates/pipelines/enterprise.json +114 -0
- package/templates/pipelines/fast.json +63 -0
- package/templates/pipelines/full.json +104 -0
- package/templates/pipelines/hotfix.json +63 -0
- package/templates/pipelines/standard.json +91 -0
- package/tmux/claude-teams-overlay.conf +109 -0
- package/tmux/templates/architecture.json +19 -0
- package/tmux/templates/bug-fix.json +24 -0
- package/tmux/templates/code-review.json +24 -0
- package/tmux/templates/devops.json +19 -0
- package/tmux/templates/documentation.json +19 -0
- package/tmux/templates/exploration.json +19 -0
- package/tmux/templates/feature-dev.json +24 -0
- package/tmux/templates/full-stack.json +24 -0
- package/tmux/templates/migration.json +24 -0
- package/tmux/templates/refactor.json +19 -0
- package/tmux/templates/security-audit.json +24 -0
- package/tmux/templates/testing.json +24 -0
- package/tmux/tmux.conf +167 -0
|
@@ -0,0 +1,328 @@
|
|
|
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 ""
|