codebyplan 1.13.22 → 1.13.24
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/README.md +0 -109
- package/dist/cli.js +476 -690
- package/package.json +1 -1
- package/templates/hooks/README.md +3 -53
- package/templates/hooks/cbp-statusline.mjs +106 -11
- package/templates/hooks/cbp-statusline.py +79 -13
- package/templates/hooks/cbp-statusline.sh +97 -17
- package/templates/hooks/cbp-test-hooks.sh +0 -71
- package/templates/hooks/hooks.json +0 -20
- package/templates/settings.project.base.json +0 -7
- package/templates/skills/cbp-round-execute/SKILL.md +0 -18
- package/templates/skills/cbp-session-start/SKILL.md +2 -0
- package/templates/skills/cbp-task-complete/SKILL.md +0 -14
- package/templates/skills/cbp-task-start/SKILL.md +0 -8
- package/templates/hooks/cbp-cmux-branch-watch.sh +0 -39
- package/templates/hooks/cbp-cmux-workspace-sync.sh +0 -19
- package/templates/skills/cbp-setup-cmux/SKILL.md +0 -170
|
@@ -255,77 +255,6 @@ fi
|
|
|
255
255
|
|
|
256
256
|
echo ""
|
|
257
257
|
|
|
258
|
-
# ===== HOOK SMOKE TESTS — cbp-cmux-workspace-sync + cbp-cmux-branch-watch =====
|
|
259
|
-
echo "## Hook Smoke Tests — cbp-cmux-workspace-sync + cbp-cmux-branch-watch (CHK-162)"
|
|
260
|
-
|
|
261
|
-
# --- cbp-cmux-workspace-sync.sh ---
|
|
262
|
-
|
|
263
|
-
if [ ! -f "$HOOKS_DIR/cbp-cmux-workspace-sync.sh" ]; then
|
|
264
|
-
test_result "cbp-cmux-workspace-sync.sh present" "passed" "missing"
|
|
265
|
-
else
|
|
266
|
-
test_result "cbp-cmux-workspace-sync.sh present" "passed" "passed"
|
|
267
|
-
|
|
268
|
-
FIRST_LINE=$(head -1 "$HOOKS_DIR/cbp-cmux-workspace-sync.sh")
|
|
269
|
-
if echo "$FIRST_LINE" | grep -q '^#!/'; then
|
|
270
|
-
test_result "cbp-cmux-workspace-sync.sh has shebang" "passed" "passed"
|
|
271
|
-
else
|
|
272
|
-
test_result "cbp-cmux-workspace-sync.sh has shebang" "passed" "missing"
|
|
273
|
-
fi
|
|
274
|
-
|
|
275
|
-
if grep -q '@scope: org-shared' "$HOOKS_DIR/cbp-cmux-workspace-sync.sh"; then
|
|
276
|
-
test_result "cbp-cmux-workspace-sync.sh has @scope: org-shared" "passed" "passed"
|
|
277
|
-
else
|
|
278
|
-
test_result "cbp-cmux-workspace-sync.sh has @scope: org-shared" "passed" "missing"
|
|
279
|
-
fi
|
|
280
|
-
|
|
281
|
-
# Graceful-degrade: CMUX_WORKSPACE_ID unset → fast-path exit 0, no output
|
|
282
|
-
ACTUAL_EXIT=$(env -u CMUX_WORKSPACE_ID bash "$HOOKS_DIR/cbp-cmux-workspace-sync.sh" <<< '{}' >/dev/null 2>&1; echo $?)
|
|
283
|
-
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
284
|
-
test_result "cbp-cmux-workspace-sync.sh graceful-degrade (no CMUX_WORKSPACE_ID) exits 0" "passed" "passed"
|
|
285
|
-
else
|
|
286
|
-
test_result "cbp-cmux-workspace-sync.sh graceful-degrade (no CMUX_WORKSPACE_ID) exits 0" "passed" "failed"
|
|
287
|
-
fi
|
|
288
|
-
fi
|
|
289
|
-
|
|
290
|
-
# --- cbp-cmux-branch-watch.sh ---
|
|
291
|
-
|
|
292
|
-
if [ ! -f "$HOOKS_DIR/cbp-cmux-branch-watch.sh" ]; then
|
|
293
|
-
test_result "cbp-cmux-branch-watch.sh present" "passed" "missing"
|
|
294
|
-
else
|
|
295
|
-
test_result "cbp-cmux-branch-watch.sh present" "passed" "passed"
|
|
296
|
-
|
|
297
|
-
FIRST_LINE=$(head -1 "$HOOKS_DIR/cbp-cmux-branch-watch.sh")
|
|
298
|
-
if echo "$FIRST_LINE" | grep -q '^#!/'; then
|
|
299
|
-
test_result "cbp-cmux-branch-watch.sh has shebang" "passed" "passed"
|
|
300
|
-
else
|
|
301
|
-
test_result "cbp-cmux-branch-watch.sh has shebang" "passed" "missing"
|
|
302
|
-
fi
|
|
303
|
-
|
|
304
|
-
if grep -q '@scope: org-shared' "$HOOKS_DIR/cbp-cmux-branch-watch.sh"; then
|
|
305
|
-
test_result "cbp-cmux-branch-watch.sh has @scope: org-shared" "passed" "passed"
|
|
306
|
-
else
|
|
307
|
-
test_result "cbp-cmux-branch-watch.sh has @scope: org-shared" "passed" "missing"
|
|
308
|
-
fi
|
|
309
|
-
|
|
310
|
-
# Graceful-degrade: CMUX_WORKSPACE_ID unset → fast-path exit 0
|
|
311
|
-
ACTUAL_EXIT=$(env -u CMUX_WORKSPACE_ID bash "$HOOKS_DIR/cbp-cmux-branch-watch.sh" <<< '{"tool_input":{"command":"git checkout main"}}' >/dev/null 2>&1; echo $?)
|
|
312
|
-
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
313
|
-
test_result "cbp-cmux-branch-watch.sh graceful-degrade (no CMUX_WORKSPACE_ID) exits 0" "passed" "passed"
|
|
314
|
-
else
|
|
315
|
-
test_result "cbp-cmux-branch-watch.sh graceful-degrade (no CMUX_WORKSPACE_ID) exits 0" "passed" "failed"
|
|
316
|
-
fi
|
|
317
|
-
|
|
318
|
-
# Non-checkout command → no-op exit 0 (even with CMUX_WORKSPACE_ID set, non-checkout should skip sync)
|
|
319
|
-
ACTUAL_EXIT=$(CMUX_WORKSPACE_ID=test-ws bash "$HOOKS_DIR/cbp-cmux-branch-watch.sh" <<< '{"tool_input":{"command":"git status"}}' >/dev/null 2>&1; echo $?)
|
|
320
|
-
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
321
|
-
test_result "cbp-cmux-branch-watch.sh non-checkout command exits 0" "passed" "passed"
|
|
322
|
-
else
|
|
323
|
-
test_result "cbp-cmux-branch-watch.sh non-checkout command exits 0" "passed" "failed"
|
|
324
|
-
fi
|
|
325
|
-
fi
|
|
326
|
-
|
|
327
|
-
echo ""
|
|
328
|
-
|
|
329
258
|
# ===== SUMMARY =====
|
|
330
259
|
echo "=== TEST SUMMARY ==="
|
|
331
260
|
echo -e "Passed: ${GREEN}$PASSED${NC}"
|
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"hooks": {
|
|
3
|
-
"SessionStart": [
|
|
4
|
-
{
|
|
5
|
-
"matcher": "*",
|
|
6
|
-
"hooks": [
|
|
7
|
-
{
|
|
8
|
-
"type": "command",
|
|
9
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-cmux-workspace-sync.sh"
|
|
10
|
-
}
|
|
11
|
-
]
|
|
12
|
-
}
|
|
13
|
-
],
|
|
14
3
|
"PreToolUse": [
|
|
15
4
|
{
|
|
16
5
|
"matcher": "Edit|Write|MultiEdit",
|
|
@@ -70,15 +59,6 @@
|
|
|
70
59
|
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-mcp-round-sync.sh"
|
|
71
60
|
}
|
|
72
61
|
]
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
"matcher": "Bash",
|
|
76
|
-
"hooks": [
|
|
77
|
-
{
|
|
78
|
-
"type": "command",
|
|
79
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-cmux-branch-watch.sh"
|
|
80
|
-
}
|
|
81
|
-
]
|
|
82
62
|
}
|
|
83
63
|
]
|
|
84
64
|
}
|
|
@@ -118,7 +118,6 @@
|
|
|
118
118
|
"Skill(cbp-round-input)",
|
|
119
119
|
"Skill(cbp-round-start)",
|
|
120
120
|
"Skill(cbp-session-start)",
|
|
121
|
-
"Skill(cbp-setup-cmux)",
|
|
122
121
|
"Skill(cbp-setup-e2e)",
|
|
123
122
|
"Skill(cbp-setup-eslint)",
|
|
124
123
|
"Skill(cbp-ship-configure)",
|
|
@@ -179,12 +178,6 @@
|
|
|
179
178
|
"Bash(npx codebyplan whoami:*)",
|
|
180
179
|
"Bash(codebyplan resolve-worktree:*)",
|
|
181
180
|
"Bash(npx codebyplan resolve-worktree:*)",
|
|
182
|
-
"Bash(codebyplan cmux-sync:*)",
|
|
183
|
-
"Bash(npx codebyplan cmux-sync:*)",
|
|
184
|
-
"Bash(codebyplan cmux-status:*)",
|
|
185
|
-
"Bash(npx codebyplan cmux-status:*)",
|
|
186
|
-
"Bash(codebyplan cmux-serve:*)",
|
|
187
|
-
"Bash(npx codebyplan cmux-serve:*)",
|
|
188
181
|
"Bash(codebyplan version-status:*)",
|
|
189
182
|
"Bash(npx codebyplan version-status:*)",
|
|
190
183
|
"Bash(codebyplan statusline:*)",
|
|
@@ -57,16 +57,6 @@ Read the plan from round context (`context.planner_output`). If no plan: `No app
|
|
|
57
57
|
|
|
58
58
|
Read effective testing profile: `round.context.testing_profile_override` if set (user override for this round only), else `task.context.testing_profile` (set by planner Phase 4.8), else default `'web'`. Pass the effective profile to all per-wave `cbp-testing-qa-agent` spawns.
|
|
59
59
|
|
|
60
|
-
### Step 2a: Auto-Dev-Server (cmux)
|
|
61
|
-
|
|
62
|
-
Fire the dev-server hook at round-execution start. Self-no-ops outside cmux or when `auto_dev_server` is disabled in `.codebyplan/cmux.json`.
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
npx codebyplan cmux-serve --files "<comma-separated approved_plan.files_to_modify[].path>"
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
The subcommand reads `.codebyplan/server.json` `port_allocations[]`, resolves which apps' source dirs intersect the round's files, probes each allocated port, and starts a cmux terminal split + browser pane for any app not already serving. Idempotent — if the port is already listening it only opens the browser pane (mitigating the multi-worktree port collision).
|
|
69
|
-
|
|
70
60
|
### Step 3: Route Execution Path
|
|
71
61
|
|
|
72
62
|
Inspect `approved_plan.files_to_modify[]` and `approved_plan.round_type`. Four execution paths exist; pick the one that matches BEFORE Step 3a/3b.
|
|
@@ -153,14 +143,6 @@ If the approved plan includes database schema changes, RLS policies, or type gen
|
|
|
153
143
|
- `status: 'blocked'` → present blocker to user via AskUserQuestion, resolve, re-spawn executor with remaining work
|
|
154
144
|
- Deliverables incomplete → re-spawn executor with remaining deliverables (max 3 re-triggers). After 3 re-triggers, save partial output and proceed.
|
|
155
145
|
|
|
156
|
-
### Step 3d: Push cmux QA Status
|
|
157
|
-
|
|
158
|
-
Push the round's QA outcome to the cmux workspace sidebar. Self-no-ops outside cmux or when `auto_status` is disabled. Status is one of: `completed`, `blocked`, or `re-triggering`.
|
|
159
|
-
|
|
160
|
-
```bash
|
|
161
|
-
npx codebyplan cmux-status --qa "R{round_number} {status}"
|
|
162
|
-
```
|
|
163
|
-
|
|
164
146
|
### Step 4: Dev-Server Probe (rounds 2+, web/desktop profile)
|
|
165
147
|
|
|
166
148
|
When `round_number >= 2` AND `testing_profile` is `'web'` or `'desktop'` AND `files_changed` contains any UI file, probe the dev server BEFORE cbp-testing-qa-agent spawns (saves a full agent spawn when the server is down).
|
|
@@ -97,6 +97,8 @@ Check whether a newer `codebyplan` is published and safe to auto-install on this
|
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
99
|
VERSION_JSON=$(npx codebyplan version-status 2>/dev/null)
|
|
100
|
+
# Populate the claude-status cache best-effort (pure cache population — never gates session-start).
|
|
101
|
+
npx codebyplan claude status --write-cache --quiet 2>/dev/null || true
|
|
100
102
|
```
|
|
101
103
|
|
|
102
104
|
Parse `$VERSION_JSON` as JSON and branch on the result:
|
|
@@ -138,20 +138,6 @@ Skip the push only when nothing was committed in Step 5 AND `/cbp-merge-main` re
|
|
|
138
138
|
|
|
139
139
|
Call `complete_task(task_id)`. The server resolves the caller's worktree identity from the JWT/ctx and enforces the mutate-lock (CHK-140 TASK-3 — `caller_worktree_id` input field removed). The server auto-clears `assigned_user_id` + `assigned_worktree_id` on the task; if this was the last sibling task, it also clears the parent checkpoint's assignment. (Per CHK-104 hard-lock.)
|
|
140
140
|
|
|
141
|
-
### Step 7.3: Push cmux Status (task done + progress)
|
|
142
|
-
|
|
143
|
-
Push completion status and checkpoint progress to the cmux workspace sidebar. Self-no-ops outside cmux or when `auto_status` is disabled.
|
|
144
|
-
|
|
145
|
-
Compute progress from the `get_tasks` data already loaded by the routing step: `completed = count of tasks with status 'completed'`, `total = total task count for the checkpoint`. For standalone tasks (no checkpoint), omit `--progress`.
|
|
146
|
-
|
|
147
|
-
```bash
|
|
148
|
-
# Checkpoint-bound task:
|
|
149
|
-
npx codebyplan cmux-status --task "TASK-{N}: {task-title} done" --progress {completed}/{total}
|
|
150
|
-
|
|
151
|
-
# Standalone task:
|
|
152
|
-
npx codebyplan cmux-status --task "TASK-{N}: {task-title} done"
|
|
153
|
-
```
|
|
154
|
-
|
|
155
141
|
### Step 8: Run Cleanup + Migration (inline)
|
|
156
142
|
|
|
157
143
|
Apply the `cleanup` skill inline to remove orphan references to deleted/modified files. Then apply `migration` to propagate renames/moves to consumers. Both run without sub-agent spawns. Skip cleanup if no deletions/modifications; skip migration if cleanup handled everything.
|
|
@@ -228,14 +228,6 @@ Display context summary:
|
|
|
228
228
|
- **Previous rounds**: [count] completed
|
|
229
229
|
```
|
|
230
230
|
|
|
231
|
-
### Step 4.5: Push cmux Status
|
|
232
|
-
|
|
233
|
-
Push the active checkpoint and task context to the cmux workspace sidebar. Self-no-ops outside cmux or when `auto_status` is disabled in `.codebyplan/cmux.json`.
|
|
234
|
-
|
|
235
|
-
```bash
|
|
236
|
-
npx codebyplan cmux-status --checkpoint "CHK-{NNN}: {checkpoint-title}" --task "TASK-{N}: {task-title}"
|
|
237
|
-
```
|
|
238
|
-
|
|
239
231
|
### Step 5: Set Task Status
|
|
240
232
|
|
|
241
233
|
Use MCP `update_task(task_id, status: "in_progress")`.
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# @scope: org-shared
|
|
3
|
-
# Hook: PostToolUse Bash
|
|
4
|
-
# Purpose: After a Bash tool call that contains a git checkout or git switch command,
|
|
5
|
-
# sync the active cmux workspace title to the current git branch and the
|
|
6
|
-
# workspace description to the repo folder basename.
|
|
7
|
-
# Delegates entirely to `codebyplan cmux-sync` — no cmux or git logic here.
|
|
8
|
-
# Matching is broad: it also fires on file-restore forms such as
|
|
9
|
-
# `git checkout -- <file>`. That is intentional — `codebyplan cmux-sync` is
|
|
10
|
-
# idempotent, so a redundant sync on a non-branch-change is harmless, and the
|
|
11
|
-
# broad match guarantees a real branch change is never missed.
|
|
12
|
-
# No-ops silently when CMUX_WORKSPACE_ID is unset or the command contains no
|
|
13
|
-
# checkout/switch. Exit 0 on every path — never blocks tool execution.
|
|
14
|
-
|
|
15
|
-
# Fast-path: skip npx spawn when clearly not in a cmux workspace.
|
|
16
|
-
[ -n "$CMUX_WORKSPACE_ID" ] || exit 0
|
|
17
|
-
|
|
18
|
-
# Parse stdin — PostToolUse hooks receive JSON on stdin.
|
|
19
|
-
# Guard against jq absence: if jq is not available the whole block is skipped.
|
|
20
|
-
if command -v jq >/dev/null 2>&1; then
|
|
21
|
-
INPUT=$(cat 2>/dev/null || true)
|
|
22
|
-
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
23
|
-
|
|
24
|
-
# Run the sync when the command contains git checkout/switch. Broad match by design:
|
|
25
|
-
# also catches file-restore forms (e.g. `git checkout -- <file>`); cmux-sync is
|
|
26
|
-
# idempotent so a redundant sync is harmless, and a real branch change is never missed.
|
|
27
|
-
if ! echo "$CMD" | grep -qE 'git[[:space:]]+(checkout|switch)' 2>/dev/null; then
|
|
28
|
-
exit 0
|
|
29
|
-
fi
|
|
30
|
-
else
|
|
31
|
-
# jq not available — drain stdin and skip.
|
|
32
|
-
cat >/dev/null 2>&1 || true
|
|
33
|
-
exit 0
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
# Delegate to the CLI subcommand (self-no-ops when cmux binary is absent).
|
|
37
|
-
npx codebyplan cmux-sync >/dev/null 2>&1 || true
|
|
38
|
-
|
|
39
|
-
exit 0
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# @scope: org-shared
|
|
3
|
-
# Hook: SessionStart
|
|
4
|
-
# Purpose: On session start, sync the active cmux workspace title to the current git branch
|
|
5
|
-
# and the workspace description to the repo folder basename.
|
|
6
|
-
# Delegates entirely to `codebyplan cmux-sync` — no cmux or git logic here.
|
|
7
|
-
# No-ops silently when CMUX_WORKSPACE_ID is unset (not inside a cmux workspace).
|
|
8
|
-
# Exit 0 on every path — never blocks session start.
|
|
9
|
-
|
|
10
|
-
# Fast-path: skip npx spawn when clearly not in a cmux workspace.
|
|
11
|
-
[ -n "$CMUX_WORKSPACE_ID" ] || exit 0
|
|
12
|
-
|
|
13
|
-
# Drain stdin — SessionStart hooks receive JSON on stdin; we don't use it.
|
|
14
|
-
cat >/dev/null 2>&1
|
|
15
|
-
|
|
16
|
-
# Delegate to the CLI subcommand (self-no-ops when cmux binary is absent).
|
|
17
|
-
npx codebyplan cmux-sync >/dev/null 2>&1 || true
|
|
18
|
-
|
|
19
|
-
exit 0
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
scope: org-shared
|
|
3
|
-
name: cbp-setup-cmux
|
|
4
|
-
description: Configure .codebyplan/cmux.json — choose workspace color and toggle auto_status / auto_dev_server. Interactive, idempotent.
|
|
5
|
-
argument-hint: "[--force]"
|
|
6
|
-
model: sonnet
|
|
7
|
-
effort: xhigh
|
|
8
|
-
allowed-tools: Read, Write, Edit, Bash(cat *), Bash(jq *), Bash(test *), Bash(mv *), Bash(git check-ignore *), Bash(cmux *), AskUserQuestion
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# cmux Setup
|
|
12
|
-
|
|
13
|
-
Configure `.codebyplan/cmux.json` so the cmux workspace integration knows which color to
|
|
14
|
-
apply on session start and whether auto_status / auto_dev_server are enabled.
|
|
15
|
-
|
|
16
|
-
Invoke at any time. Existing values are preserved unless `--force` is passed.
|
|
17
|
-
Pass `--force` to re-ask all questions including already-configured fields.
|
|
18
|
-
|
|
19
|
-
## Arguments
|
|
20
|
-
|
|
21
|
-
Inspect `$ARGUMENTS` for `--force`. If present, set `force_mode = true`.
|
|
22
|
-
Absent: use idempotent mode — preserve existing configured values, skip re-asking
|
|
23
|
-
already-set fields.
|
|
24
|
-
|
|
25
|
-
## Step 1 — Parse --force and read existing config
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
cat .codebyplan/cmux.json 2>/dev/null || echo '{}'
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
Capture the result as `EXISTING_JSON`. Extract existing values:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
EXISTING_COLOR=$(echo "$EXISTING_JSON" | jq -r '.workspace_color // empty')
|
|
35
|
-
EXISTING_AUTO_STATUS=$(echo "$EXISTING_JSON" | jq -r '.auto_status // empty')
|
|
36
|
-
EXISTING_AUTO_DEV=$(echo "$EXISTING_JSON" | jq -r '.auto_dev_server // empty')
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Step 2 — Ask for workspace color
|
|
40
|
-
|
|
41
|
-
**Idempotency gate**: skip this question if `force_mode = false` AND `EXISTING_COLOR`
|
|
42
|
-
is a non-empty string. Print the preserved value and continue to Step 3.
|
|
43
|
-
|
|
44
|
-
Otherwise, AskUserQuestion:
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
Workspace color for this cmux workspace
|
|
48
|
-
|
|
49
|
-
Choose a named color or enter a custom hex value (#RRGGBB).
|
|
50
|
-
|
|
51
|
-
Named colors:
|
|
52
|
-
A) Red B) Crimson C) Orange D) Amber
|
|
53
|
-
E) Olive F) Green G) Teal H) Aqua
|
|
54
|
-
I) Blue J) Navy K) Indigo L) Purple
|
|
55
|
-
M) Magenta N) Rose O) Brown P) Charcoal
|
|
56
|
-
Q) Custom hex — enter a value in the format #RRGGBB
|
|
57
|
-
|
|
58
|
-
Enter a letter (A-Q) or type a custom hex value directly:
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Validate the input:
|
|
62
|
-
- If a letter A-P: map to the corresponding color name (e.g. "A" → "Red").
|
|
63
|
-
- If "Q": prompt the user to type a custom hex value, then validate the typed value
|
|
64
|
-
against `^#[0-9A-Fa-f]{6}$`. If invalid, re-prompt once with an error. Never pass the
|
|
65
|
-
bare letter "Q" to set-color.
|
|
66
|
-
- If the raw input itself already looks like a hex value: validate it against
|
|
67
|
-
`^#[0-9A-Fa-f]{6}$` and accept on match.
|
|
68
|
-
- Empty input with no existing color: use no color (leave `workspace_color` as `null`).
|
|
69
|
-
|
|
70
|
-
Set `NEW_COLOR` to the chosen color name / hex, or `null` if skipped.
|
|
71
|
-
|
|
72
|
-
## Step 3 — Ask for auto_status and auto_dev_server toggles
|
|
73
|
-
|
|
74
|
-
**Idempotency gate**: skip questions for fields that are already set (non-empty in
|
|
75
|
-
existing config) when `force_mode = false`.
|
|
76
|
-
|
|
77
|
-
For each unset field (or all fields when `force_mode = true`), AskUserQuestion:
|
|
78
|
-
|
|
79
|
-
```
|
|
80
|
-
cmux integration toggles
|
|
81
|
-
|
|
82
|
-
auto_status: automatically run `cmux status` in this workspace on session start?
|
|
83
|
-
(default: on)
|
|
84
|
-
A) On
|
|
85
|
-
B) Off
|
|
86
|
-
|
|
87
|
-
auto_dev_server: automatically start the dev server via cmux on session start?
|
|
88
|
-
(default: on)
|
|
89
|
-
A) On
|
|
90
|
-
B) Off
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
Ask both in a single question when both are unset. Set `NEW_AUTO_STATUS` and
|
|
94
|
-
`NEW_AUTO_DEV` to `true` or `false` based on the answers.
|
|
95
|
-
|
|
96
|
-
## Step 4 — Write .codebyplan/cmux.json
|
|
97
|
-
|
|
98
|
-
Build the updated payload using jq deep-merge so sibling fields added by future
|
|
99
|
-
schema versions are preserved. Assemble variables first.
|
|
100
|
-
|
|
101
|
-
Backfill any field that the Step 2/3 idempotency gates skipped, so each `jq
|
|
102
|
-
--argjson` always receives valid JSON — an empty shell variable makes `jq` exit 1,
|
|
103
|
-
which would leave `NEW_PAYLOAD` empty and silently no-op the write. Fall back to the
|
|
104
|
-
existing value, then to the default (`true` for the toggles):
|
|
105
|
-
|
|
106
|
-
```bash
|
|
107
|
-
NEW_COLOR="${NEW_COLOR:-$EXISTING_COLOR}"
|
|
108
|
-
NEW_AUTO_STATUS="${NEW_AUTO_STATUS:-${EXISTING_AUTO_STATUS:-true}}"
|
|
109
|
-
NEW_AUTO_DEV="${NEW_AUTO_DEV:-${EXISTING_AUTO_DEV:-true}}"
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
NEW_COLOR_JSON=$(echo "$NEW_COLOR" | jq -R 'if . == "null" or . == "" then null else . end')
|
|
114
|
-
NEW_PAYLOAD=$(jq -n \
|
|
115
|
-
--argjson color "$NEW_COLOR_JSON" \
|
|
116
|
-
--argjson auto_status "$NEW_AUTO_STATUS" \
|
|
117
|
-
--argjson auto_dev_server "$NEW_AUTO_DEV" \
|
|
118
|
-
'{workspace_color: $color, auto_status: $auto_status, auto_dev_server: $auto_dev_server}')
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
Atomic write via jq tmp+mv deep-merge (`. * $new` deep-merges, preserving any
|
|
122
|
-
sibling keys not in the new payload):
|
|
123
|
-
|
|
124
|
-
```bash
|
|
125
|
-
jq --argjson new "$NEW_PAYLOAD" '. * $new' \
|
|
126
|
-
.codebyplan/cmux.json > .codebyplan/cmux.json.tmp \
|
|
127
|
-
&& mv .codebyplan/cmux.json.tmp .codebyplan/cmux.json
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## Step 5 — Apply color immediately
|
|
131
|
-
|
|
132
|
-
If `NEW_COLOR` is a non-empty, non-null string AND cmux is available in the current
|
|
133
|
-
environment (`$CMUX_WORKSPACE_ID` is set), apply the color immediately so the change
|
|
134
|
-
is visible without needing to restart the session:
|
|
135
|
-
|
|
136
|
-
```bash
|
|
137
|
-
if [ -n "$CMUX_WORKSPACE_ID" ] && [ -n "$NEW_COLOR" ] && [ "$NEW_COLOR" != "null" ]; then
|
|
138
|
-
CMUX_BIN="${CMUX_BUNDLED_CLI_PATH:-${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}}"
|
|
139
|
-
"$CMUX_BIN" workspace-action --action set-color --color "$NEW_COLOR" 2>/dev/null || true
|
|
140
|
-
fi
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
The guard (`2>/dev/null || true`) ensures a missing or non-zero cmux never blocks
|
|
144
|
-
the skill — applying the color is best-effort.
|
|
145
|
-
|
|
146
|
-
## Step 6 — Verify and report
|
|
147
|
-
|
|
148
|
-
Re-read `.codebyplan/cmux.json` and emit a summary:
|
|
149
|
-
|
|
150
|
-
```
|
|
151
|
-
cmux Setup — Complete
|
|
152
|
-
|
|
153
|
-
workspace_color : <value or "(none)">
|
|
154
|
-
auto_status : <true|false>
|
|
155
|
-
auto_dev_server : <true|false>
|
|
156
|
-
|
|
157
|
-
Config written to .codebyplan/cmux.json
|
|
158
|
-
|
|
159
|
-
Next: on the next SessionStart, codebyplan cmux-sync will apply the color
|
|
160
|
-
automatically. Run `/cbp-setup-cmux --force` at any time to reconfigure.
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
## Key Rules
|
|
164
|
-
|
|
165
|
-
- Atomic write (tmp + mv) — never leaves cmux.json in a partial state
|
|
166
|
-
- Deep-merge with `. * $new` — sibling keys from future schema versions are preserved
|
|
167
|
-
- Color apply is best-effort — a missing cmux binary never causes an error
|
|
168
|
-
- `auto_status` and `auto_dev_server` default to `true` when absent (documented in
|
|
169
|
-
`packages/codebyplan-package/src/lib/types.ts` CmuxConfig)
|
|
170
|
-
- cmux.json is COMMITTED (not gitignored) — workspace color is shared across team members
|