crewforth 0.0.1 → 3.0.0-rc.1

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 (168) hide show
  1. package/CHANGELOG.md +3784 -0
  2. package/LICENSE +21 -0
  3. package/README.md +37 -7
  4. package/VERSION +1 -0
  5. package/adopt.sh +1670 -0
  6. package/bin/cli.js +497 -0
  7. package/kit/AGENT_TEMPLATE.md +92 -0
  8. package/kit/CLAUDE.md +228 -0
  9. package/kit/README.md +107 -0
  10. package/kit/agents/crew-backend-expert.md +95 -0
  11. package/kit/agents/crew-commit-agent.md +96 -0
  12. package/kit/agents/crew-database-expert.md +84 -0
  13. package/kit/agents/crew-devops-expert.md +82 -0
  14. package/kit/agents/crew-frontend-expert.md +85 -0
  15. package/kit/agents/crew-performance-expert.md +78 -0
  16. package/kit/agents/crew-planner.md +60 -0
  17. package/kit/agents/crew-privacy-agent.md +71 -0
  18. package/kit/agents/crew-review-agent.md +95 -0
  19. package/kit/agents/crew-security-expert.md +73 -0
  20. package/kit/agents/crew-session-manager.md +77 -0
  21. package/kit/agents/crew-test-expert.md +64 -0
  22. package/kit/eval/doctor.sh +465 -0
  23. package/kit/eval/gate-report.sh +137 -0
  24. package/kit/eval/golden-holdout.txt +53 -0
  25. package/kit/eval/golden-routing.txt +199 -0
  26. package/kit/eval/lib/crew-env.sh +14 -0
  27. package/kit/eval/lib/settings-json.awk +154 -0
  28. package/kit/eval/lib/star.sh +70 -0
  29. package/kit/eval/parser-conformance.sh +612 -0
  30. package/kit/eval/preflight.sh +186 -0
  31. package/kit/eval/routing-eval.sh +209 -0
  32. package/kit/eval/scan-skill.sh +162 -0
  33. package/kit/eval/smoke-test.sh +6693 -0
  34. package/kit/eval/update-guard.sh +81 -0
  35. package/kit/eval/utilization.sh +130 -0
  36. package/kit/hooks/board-sync.sh +106 -0
  37. package/kit/hooks/board.sh +962 -0
  38. package/kit/hooks/commit-msg +49 -0
  39. package/kit/hooks/context-usage.sh +353 -0
  40. package/kit/hooks/floor-blocklist.txt +124 -0
  41. package/kit/hooks/guard-bash.sh +1431 -0
  42. package/kit/hooks/guard-commit-scan.sh +511 -0
  43. package/kit/hooks/guard-write.sh +513 -0
  44. package/kit/hooks/pre-commit +577 -0
  45. package/kit/hooks/route-hint.sh +185 -0
  46. package/kit/hooks/secret-blocklist.txt +82 -0
  47. package/kit/hooks/session-guard.sh +149 -0
  48. package/kit/hooks/session-rehydrate.sh +41 -0
  49. package/kit/hooks/session-stats.sh +252 -0
  50. package/kit/hooks/session-update-check.sh +236 -0
  51. package/kit/hooks/skill-trust.sh +150 -0
  52. package/kit/hooks/trace-blocklist.txt +53 -0
  53. package/kit/settings.json +132 -0
  54. package/kit/skills/a11y/SKILL.md +44 -0
  55. package/kit/skills/adr/SKILL.md +74 -0
  56. package/kit/skills/api-design/SKILL.md +50 -0
  57. package/kit/skills/automode-policy/SKILL.md +91 -0
  58. package/kit/skills/automode-policy/references/policy.json +13 -0
  59. package/kit/skills/automode-policy/scripts/apply.sh +84 -0
  60. package/kit/skills/automode-policy/scripts/check.sh +102 -0
  61. package/kit/skills/backend-architecture/SKILL.md +103 -0
  62. package/kit/skills/brainstorm/SKILL.md +47 -0
  63. package/kit/skills/ci-pipeline/SKILL.md +38 -0
  64. package/kit/skills/commit-message/SKILL.md +82 -0
  65. package/kit/skills/commit-message/references/examples.md +8 -0
  66. package/kit/skills/confidence-check/SKILL.md +86 -0
  67. package/kit/skills/crew-board/SKILL.md +55 -0
  68. package/kit/skills/crew-brainstorm/SKILL.md +19 -0
  69. package/kit/skills/crew-code-review/SKILL.md +151 -0
  70. package/kit/skills/crew-code-review/references/history-search.md +19 -0
  71. package/kit/skills/crew-code-review/references/panel-mode.md +32 -0
  72. package/kit/skills/crew-code-review/references/receiving.md +23 -0
  73. package/kit/skills/crew-doctor/SKILL.md +36 -0
  74. package/kit/skills/crew-gates/SKILL.md +25 -0
  75. package/kit/skills/crew-handoff/SKILL.md +14 -0
  76. package/kit/skills/crew-plan/SKILL.md +18 -0
  77. package/kit/skills/crew-review/SKILL.md +23 -0
  78. package/kit/skills/crew-ship/SKILL.md +19 -0
  79. package/kit/skills/crew-skill/SKILL.md +61 -0
  80. package/kit/skills/crew-studio/SKILL.md +129 -0
  81. package/kit/skills/crew-update/SKILL.md +43 -0
  82. package/kit/skills/db-migration/SKILL.md +120 -0
  83. package/kit/skills/db-migration/references/backup-restore.md +33 -0
  84. package/kit/skills/db-migration/references/raw-sql.md +30 -0
  85. package/kit/skills/db-migration/references/tool-matrix.md +35 -0
  86. package/kit/skills/dependency-audit/SKILL.md +61 -0
  87. package/kit/skills/dependency-upgrade/SKILL.md +82 -0
  88. package/kit/skills/deploy/SKILL.md +100 -0
  89. package/kit/skills/deploy/references/proxy-ssl.md +56 -0
  90. package/kit/skills/deploy/references/rollback.md +18 -0
  91. package/kit/skills/deploy/references/scripts.md +9 -0
  92. package/kit/skills/deploy/references/topology-a.md +128 -0
  93. package/kit/skills/deploy/references/topology-b.md +44 -0
  94. package/kit/skills/docs-writer/SKILL.md +53 -0
  95. package/kit/skills/docs-writer/references/coauthoring.md +34 -0
  96. package/kit/skills/eval-grader/SKILL.md +75 -0
  97. package/kit/skills/eval-grader/references/method.md +51 -0
  98. package/kit/skills/frontend/SKILL.md +56 -0
  99. package/kit/skills/frontend/references/verify-contract.md +41 -0
  100. package/kit/skills/frontend-design/SKILL.md +71 -0
  101. package/kit/skills/frontend-design/references/design-review.md +34 -0
  102. package/kit/skills/frontend-rn-expo/SKILL.md +25 -0
  103. package/kit/skills/handoff/SKILL.md +71 -0
  104. package/kit/skills/handoff/references/cold-reader.md +51 -0
  105. package/kit/skills/i18n-integrity/SKILL.md +31 -0
  106. package/kit/skills/incident-runbook/SKILL.md +40 -0
  107. package/kit/skills/incident-runbook/references/postmortem.md +16 -0
  108. package/kit/skills/iterate/SKILL.md +40 -0
  109. package/kit/skills/mcp-builder/SKILL.md +54 -0
  110. package/kit/skills/mcp-builder/references/building.md +71 -0
  111. package/kit/skills/observability/SKILL.md +50 -0
  112. package/kit/skills/performance/SKILL.md +38 -0
  113. package/kit/skills/performance/references/bottlenecks.md +10 -0
  114. package/kit/skills/privacy-compliance/SKILL.md +75 -0
  115. package/kit/skills/red-team/SKILL.md +48 -0
  116. package/kit/skills/reflect/SKILL.md +57 -0
  117. package/kit/skills/release/SKILL.md +44 -0
  118. package/kit/skills/security-scan/SKILL.md +99 -0
  119. package/kit/skills/security-scan/references/ai-agents.md +107 -0
  120. package/kit/skills/security-scan/references/fronts.md +99 -0
  121. package/kit/skills/security-scan/references/prompting.md +23 -0
  122. package/kit/skills/security-scan/references/reporting.md +75 -0
  123. package/kit/skills/security-scan/references/verify.md +131 -0
  124. package/kit/skills/sonarqube-check/SKILL.md +108 -0
  125. package/kit/skills/sonarqube-check/references/local-engines.md +32 -0
  126. package/kit/skills/sonarqube-check/references/stand-up-server.md +25 -0
  127. package/kit/skills/spec-planning/SKILL.md +92 -0
  128. package/kit/skills/systematic-debugging/SKILL.md +57 -0
  129. package/kit/skills/systematic-debugging/references/techniques.md +44 -0
  130. package/kit/skills/teamboard/SKILL.md +88 -0
  131. package/kit/skills/teamboard/references/setup.md +37 -0
  132. package/kit/skills/testing/SKILL.md +49 -0
  133. package/kit/skills/testing/references/flaky-triage.md +51 -0
  134. package/kit/skills/threat-model/SKILL.md +57 -0
  135. package/kit/skills/threat-model/references/interview.md +51 -0
  136. package/kit/skills/threat-model/references/schema.md +42 -0
  137. package/kit/skills/token-budget/SKILL.md +51 -0
  138. package/kit/skills/trace-scan/SKILL.md +43 -0
  139. package/kit/skills/worktree/SKILL.md +40 -0
  140. package/kit/studio/README.md +266 -0
  141. package/kit/studio/ensure-node.sh +471 -0
  142. package/kit/studio/package.json +14 -0
  143. package/kit/studio/server/hooks/studio-gate.sh +169 -0
  144. package/kit/studio/server/index.js +902 -0
  145. package/kit/studio/server/lib/crew-env.js +11 -0
  146. package/kit/studio/server/lib/fleet.js +146 -0
  147. package/kit/studio/server/lib/graph.js +533 -0
  148. package/kit/studio/server/lib/instance.js +135 -0
  149. package/kit/studio/server/lib/kit-telemetry.js +182 -0
  150. package/kit/studio/server/lib/kit.js +158 -0
  151. package/kit/studio/server/lib/palette.js +118 -0
  152. package/kit/studio/server/lib/peers.js +72 -0
  153. package/kit/studio/server/lib/permissions.js +150 -0
  154. package/kit/studio/server/lib/projects.js +294 -0
  155. package/kit/studio/server/lib/roster.js +191 -0
  156. package/kit/studio/server/lib/session.js +309 -0
  157. package/kit/studio/server/lib/terminal.js +91 -0
  158. package/kit/studio/server/lib/transcript.js +100 -0
  159. package/kit/studio/web/app.js +1098 -0
  160. package/kit/studio/web/canvas.js +1179 -0
  161. package/kit/studio/web/chat.js +543 -0
  162. package/kit/studio/web/index.html +86 -0
  163. package/kit/studio/web/md.js +110 -0
  164. package/kit/studio/web/storage-migrate.js +23 -0
  165. package/kit/studio/web/style.css +1453 -0
  166. package/package.json +46 -8
  167. package/start.sh +748 -0
  168. package/bin/crewforth.js +0 -10
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: trace-scan
3
+ description: |
4
+ Trace scan (§4.1/§4.2): before a commit, scans the staged changes and the message for AI traces (co-author
5
+ trailers, footers, robot emoji, tool names) and vendor template names. The git hooks apply it automatically.
6
+ ---
7
+
8
+ # Trace Scan (trace-scan)
9
+
10
+ <!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
11
+ Trigger phrases: "scan traces", "trace scan", "AI trace", "check vendor name", "pre-commit audit"
12
+
13
+ Purpose: to bind §4.1/§4.2 to a *gate* rather than to *memory*. If the rule lives only in text,
14
+ a trace leaks sooner or later; this skill + the hooks stop the leak at commit time.
15
+
16
+ ## When
17
+ - Before every commit (automatic: `pre-commit` + `commit-msg` hooks).
18
+ - Before crew-commit-agent proposes a message (manual verification).
19
+
20
+ ## How
21
+ Pattern list: `./.claude/hooks/trace-blocklist.txt` (grep -iE, one pattern per line).
22
+ - **Defaults are high-hit:** co-author trailers, auto-generation footers, robot emoji, and AI-assistant/tool
23
+ brand names. Standalone words that occur too often (model/assistant) are DELIBERATELY excluded. See trace-blocklist.txt for the exact list.
24
+ - **Vendor name is project-specific:** ADD the name of the third-party template in use to the list (§4.2).
25
+
26
+ Manual scan (a quick look without the hook):
27
+ ```bash
28
+ git diff --cached --unified=0 | grep -E '^\+' | grep -Ev '^\+\+\+' \
29
+ | grep -iEf .claude/hooks/trace-blocklist.txt
30
+ ```
31
+
32
+ ## Hook setup
33
+ `start.sh` sets `git config core.hooksPath .claude/hooks` (if there is a git repo). The hooks live
34
+ under `.claude` → they are in gitignore and stay local (§4.3). To do it later for a repo:
35
+ ```bash
36
+ git config core.hooksPath .claude/hooks
37
+ chmod +x .claude/hooks/pre-commit .claude/hooks/commit-msg
38
+ ```
39
+
40
+ ## Rules
41
+ - If there is a finding, the commit STOPS; the phrase is removed and the real rationale is written in the project's commit language (CLAUDE.md).
42
+ - Skipping with `--no-verify` only on an EXPLICIT request (§4.5); the hook is not skipped silently.
43
+ - On a false positive, narrow/remove the pattern — the list is set up by the project owner.
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: worktree
3
+ description: |
4
+ Isolate risky or parallel file-mutating work in a git worktree so the main tree's uncommitted changes are never
5
+ clobbered. For fan-out agents that edit files, throwaway experiments, or any change you may want to discard cleanly.
6
+ ---
7
+
8
+ # Worktree Isolation
9
+
10
+ <!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
11
+ Trigger phrases: "worktree", "git worktree", "isolate the changes", "sandbox this work", "parallel file edits"
12
+
13
+ One rule: **never let risky or parallel work run on top of uncommitted changes in the shared tree.** A git worktree
14
+ gives a second working copy of the same repo on its own branch — you experiment or fan out agents there, and the main
15
+ tree (with your in-progress edits) is physically untouched. Throw the worktree away and nothing you cared about is lost.
16
+
17
+ > **Crewforth adaptation (local, .claude/):** this exists because verification/fan-out subagents have discarded a session's
18
+ > **uncommitted** work by running a destructive git command over the shared tree. Those commands (`reset --hard`,
19
+ > `clean -f`, `checkout -- .`, `restore`) are §4.5-gated — but the real fix is to not put them near unsaved work.
20
+ > The Agent tool's `isolation: "worktree"` does this automatically for parallel mutating agents; reach for it there.
21
+
22
+ ## When to isolate
23
+ - **Fan-out that writes files** — two+ agents editing the same repo in parallel would collide; give each its own worktree.
24
+ - **A throwaway experiment** — you might keep it or bin it; a worktree makes "bin it" a one-liner, not a `reset --hard`.
25
+ - **A dirty tree you can't commit yet** — you have unsaved work but need to try something risky; isolate rather than stash-and-pray.
26
+ - Skip it for a single, in-place edit on a clean tree — a worktree is overhead there.
27
+
28
+ ## How
29
+ 1. **Detect** — are you already in a worktree? `[ "$(git rev-parse --git-dir)" != "$(git rev-parse --git-common-dir)" ]` is true inside one; don't nest.
30
+ 2. **Create** — `git worktree add ../wt-<name> -b <branch>` (new branch) or `git worktree add ../wt-<name> <existing>`. It shares the object store, so it's cheap.
31
+ 3. **Work there** — cd into it; edits, builds, and agent runs stay local to that copy.
32
+ 4. **Fold back or discard** — keep: commit on its branch, then merge. Discard: `git worktree remove ../wt-<name>` (add `--force` only if you mean to drop its changes).
33
+ 5. **Clean up** — `git worktree prune` removes stale entries. Never leave orphaned worktrees around.
34
+
35
+ ## Invariant rules
36
+ 1. **Isolate before risk, don't revert after** — a worktree replaces "run `checkout -- .` to undo"; the undo is `worktree remove`.
37
+ 2. **One worktree per parallel writer** — never two agents mutating the same tree at once.
38
+ 3. **Don't nest** — creating a worktree from inside a worktree; detect first.
39
+ 4. **Commit or isolate before delegating file-mutating work** — a subagent must never be able to discard the main tree's unsaved changes.
40
+ 5. **Remove what you add** — no orphaned worktrees; `remove` + `prune` when done.
@@ -0,0 +1,266 @@
1
+ # Crewforth Studio
2
+
3
+ A visual orchestration panel for Claude Code: which agent is running, what it is
4
+ doing right now, what it has spent, and which gates fired.
5
+
6
+ Studio **is installed into your project**, because it lives inside the payload:
7
+ this directory is `kit/studio/`, and `kit/` is what every
8
+ channel already ships. `start.sh` and `adopt.sh` copy it to `.claude/studio/`,
9
+ beside `agents`, `skills`, `commands`, `hooks` and `eval` — the sixth of six.
10
+
11
+ That was the other way round until a real project updated with `/crew-update`,
12
+ ran the documented command and got ENOENT: the project had no `package.json`,
13
+ and nothing had ever installed the panel into it. Excluding it from every
14
+ channel was a decision; a documented command that cannot work is a defect.
15
+
16
+ ## Run
17
+
18
+ From any project that has Crewforth:
19
+
20
+ ```bash
21
+ /crew-studio # the command; probes node, starts it, reports the URL
22
+ node .claude/studio/server/index.js --open # the same thing without the picker
23
+ ```
24
+
25
+ **`node` may not be on your PATH, and that is on purpose.** When Crewforth fetched the runtime for you
26
+ (`ensure-node.sh --install`), it promised to touch nothing outside `~/.claude/studio-runtime` — no PATH edit,
27
+ no shell profile, no admin rights. Measured on a stock Windows 11 machine: after a successful install
28
+ `node --version` reports v24.21.0 through the full path while `command -v node` finds nothing, which is the
29
+ promise being kept rather than a broken install. So every `node …` line on this page means "the node Crewforth
30
+ can find". Ask for it instead of assuming it:
31
+
32
+ ```bash
33
+ NODE="$(bash .claude/studio/ensure-node.sh)" # prints an absolute path, exits 1 if there is none
34
+ "$NODE" .claude/studio/server/index.js --open
35
+ ```
36
+
37
+ `/crew-studio` does exactly this for you, which is why it is the first line above and not the second.
38
+
39
+ Other flags, same file:
40
+
41
+ ```bash
42
+ node .claude/studio/server/index.js --port 8080
43
+ node .claude/studio/server/index.js --selftest # offline checks, no browser
44
+ ```
45
+
46
+ **Started per project, scoped to the machine.** Studio reads
47
+ `~/.claude/projects`, which holds every session on this machine. The count is
48
+ whatever that directory holds; the panel prints it rather than claiming it here,
49
+ because a number measured on one machine describes only that machine. So a
50
+ running panel already sees a kit-installed project without being started inside
51
+ it, and the working directory only decides which project the panel opens on.
52
+ Run it from wherever is convenient, or run it once and leave it up.
53
+
54
+ `--open` exists so the URL is not copied by hand: the token is generated per run
55
+ and the panel refuses requests without it. When a browser cannot be opened — over
56
+ SSH, or headless — the server says so rather than looking like it worked, and
57
+ `/crew-studio` reports the URL either way.
58
+
59
+ **Both editions carry the panel, in different places.** A full install has it
60
+ at `.claude/studio/`; the plugin edition has it at `studio/` in the plugin's own
61
+ root. One `/crew-studio` file serves both, and its first step tells them apart
62
+ by reading `${CLAUDE_PLUGIN_ROOT}/studio/server/index.js` literally: Claude Code
63
+ replaces that placeholder before the command is read, and only when the command
64
+ came from the plugin. A real absolute path is the plugin's panel; the
65
+ placeholder left standing means a full install. Neither path on disk means an
66
+ install older than the panel, which `/crew-update` brings up to date.
67
+ In the plugin the command is namespaced: `/crewforth:crew-studio`.
68
+
69
+ **What the plugin edition cannot show.** A plugin install puts no
70
+ `.claude/VERSION`, `kit.conf` or Crewforth scripts into a project. That project's row
71
+ in the list has no version badge, and for the project the panel was opened from, the
72
+ inspector's gates, stats and board tabs say "Not measured" with the reason rather
73
+ than zero. The gates tab can still list what the gate log observed: the plugin's
74
+ Bash guard records its blocks, approval prompts and pre-authorised git actions,
75
+ and its gate-file write guard its blocks, in `.claude/gate-log.tsv` when the
76
+ project has a `.claude/` directory, the file is git-ignored or the project is
77
+ not a repo, and `CREW_GATE_LOG` does not send the log elsewhere.
78
+ Everything else — the live
79
+ agent graph, owned sessions, the permission bridge — works the same in both
80
+ editions.
81
+
82
+ **The suite is not here.** It lives in `packaging/studio-test/`, beside the
83
+ repo's other gates, and asserts things about this *repository* — the root
84
+ `package.json`, the payload beside it — which an installed project does not
85
+ have. Keeping it under `kit/` would also have shipped 104 KB of test
86
+ code through all four channels only for the installer to delete it on arrival.
87
+ The installed diagnostic is `--selftest`, which lives in `server/index.js`.
88
+
89
+ There is no install step. Studio has **zero dependencies** — `node:http` and
90
+ `node:child_process` are the whole stack, matching Crewforth's own promise. If
91
+ `node_modules` ever appears here, something has gone wrong.
92
+
93
+ Requires Node 18+. In Crewforth's own repository `bash packaging/verify.sh studio`
94
+ runs the same checks CI runs; a machine without node reports a skip rather than a
95
+ pass, and a missing `kit/studio/` is a failure rather than a skip.
96
+
97
+ ## What it does
98
+
99
+ **Watches.** The delegation graph of any session on this machine, live: one node
100
+ per agent, what it is doing right now, what it has spent, what it reported.
101
+ Nodes are draggable and their positions are remembered; a workflow run is a
102
+ container you can fold.
103
+
104
+ **Talks.** Sessions the panel starts are driven over stdin/stdout, so you can
105
+ write to one and watch its agents appear beneath it. They are given a session id
106
+ up front, which means their transcripts land where every other session's do and
107
+ the graph reads them without a special case.
108
+
109
+ **Shows every conversation, drives only its own.** Selecting any session opens
110
+ what was said in it, read from the transcript. A session the panel did not start
111
+ has no channel to write to, so that pane says so and offers the two things that
112
+ do work: continue it here, or open it in a real terminal.
113
+
114
+ **Asks before it acts.** Every tool call in an owned session is parked by a
115
+ PreToolUse hook and shown in the panel — the command itself, not just the tool's
116
+ name — until you allow it, allow that tool for the session, or deny it.
117
+
118
+ **Runs several at once.** Each session the panel starts is a tab that keeps its
119
+ own stream open whether or not it is on screen, so work continuing in the
120
+ background is continuing, not replayed when you look back.
121
+
122
+ **Hands a session to a real terminal.** The panel cannot drive a session it did
123
+ not start, so for an observed one it offers the only thing that is true: a
124
+ button that opens it where it can be driven. What it will run is shown before
125
+ anything launches.
126
+
127
+ **Reaches other machines.** Transcripts are local files and nothing enumerates
128
+ another machine's sessions, so a peer is another Studio.
129
+
130
+ ## What it reads
131
+
132
+ | Source | What it gives |
133
+ |---|---|
134
+ | `claude agents --json` | Live sessions on this machine: name, cwd, busy/waiting/idle, what it is waiting for |
135
+ | `<session>.jsonl` and `<session>/subagents/` | The delegation graph, nested workflow runs included |
136
+ | `.claude/VERSION` per project | Which projects run an old Crewforth, against the npm dist-tags feed |
137
+
138
+ That call spawns a process, so it is cached rather than repeated. The browser
139
+ polls every 2 s and the server caches for 1 s, which bounds the cost at one
140
+ spawn per poll. What the spawn costs is a property of the machine, not of this
141
+ file — two machines here measured 131 ms and 164 ms medians — so `--selftest`
142
+ measures it wherever it runs and prints that number instead of quoting one.
143
+
144
+ More sources land in later sprints: the transcript tree (per-agent live JSONL),
145
+ the owned-session event stream, `gate-log.tsv`, and the team board.
146
+
147
+ ## Two honesty rules
148
+
149
+ These are load-bearing, not stylistic.
150
+
151
+ **"Not measured" is never drawn as zero.** If the `claude` CLI is missing or a
152
+ read fails, the panel says so and names the reason. An empty list would read as
153
+ a quiet, healthy machine — which is the kind of lie this panel exists to stop
154
+ telling.
155
+
156
+ **Unknown data is never coerced into something familiar.** An unrecognised
157
+ status keeps a neutral ring; an unrecognised field is carried through untouched
158
+ rather than dropped. Claude Code's event shapes are undocumented and move with
159
+ the version, so the panel is built to notice that rather than to guess.
160
+
161
+ ## Sessions on other machines
162
+
163
+ The fleet lists them under **Reachable elsewhere**, with the time they were
164
+ seen. That wording is the whole of it: this is a snapshot, not a feed.
165
+
166
+ Only a session connected to Remote Control can see peers on other machines.
167
+ Measured: a headless session's `ListAgents` returns the local peers where a
168
+ connected one returns those plus five remote, and passing `--remote-control` to
169
+ a headless session does not change that — the flag starts an *interactive*
170
+ session. There is no documented API or non-interactive command that enumerates
171
+ them; `/list-agents` is an in-session tool, `--cloud` refuses without a TTY, and
172
+ the Claude API's `/v1/sessions` belongs to Managed Agents, a different product.
173
+
174
+ So the panel does not try to be that session. It reads what one already wrote:
175
+ a connected session's `ListAgents` result lands in its transcript as structured
176
+ text, and that is where this comes from. When no session here has ever asked,
177
+ that is reported as not measured — which is not the same as having no peers.
178
+
179
+ Listed, not opened. Those sessions' transcripts are on those machines' disks,
180
+ so the panel can name them but cannot draw their graphs. For that, run Studio
181
+ there too:
182
+
183
+ ## Other machines
184
+
185
+ ```bash
186
+ # on the other machine
187
+ node .claude/studio/server/index.js
188
+
189
+ # here — forward its port, then point at the forwarded one
190
+ ssh -N -L 7778:127.0.0.1:7777 other-machine
191
+ node .claude/studio/server/index.js --peer http://127.0.0.1:7778 --name mac
192
+ ```
193
+
194
+ Sessions, projects, graphs and agent reports from a peer appear alongside local
195
+ ones, tagged with the machine they came from. A peer that cannot be reached is
196
+ reported as unreachable, never as empty.
197
+
198
+ Nothing listens on a network interface in this arrangement: both Studios stay on
199
+ loopback and the tunnel does the crossing.
200
+
201
+ ## What Crewforth already measured
202
+
203
+ The panel does not recompute any of it. Selecting the session node opens what
204
+ Crewforth's own tools say, including when they say they cannot answer:
205
+
206
+ | Tab | Source |
207
+ |---|---|
208
+ | gates | `gate-report.sh --json` for the rule inventory, `.claude/gate-log.tsv` for what fired |
209
+ | stats | `session-stats.sh --raw` — fifteen metrics over this transcript |
210
+ | board | `board.sh status` |
211
+
212
+ One distinction is carried all the way to the screen. A gate event from a
213
+ session the panel started arrives through `--include-hook-events` and carries
214
+ the moment it happened, so it is listed under **Happened**. A line in
215
+ `gate-log.tsv` does not — that format has no timestamp column — so those are
216
+ listed under **Observed**, with the reason written out. Drawing the second as
217
+ the first would be the first untrue thing in this panel.
218
+
219
+ `gate-report.sh` finds the hooks relative to where it runs: `./.claude/hooks`
220
+ in an installed project, `./hooks` otherwise. Both layouts are handed what they
221
+ expect rather than the script being asked to guess. Where it still cannot
222
+ answer — a directory with no Crewforth install, a project with no log — that is reported as
223
+ not measured, never as zero.
224
+
225
+ ## The permission gate
226
+
227
+ A hook injected through `--settings` parks each tool call, writes it into a
228
+ spool, and waits for the panel's answer. Exit 0 allows, exit 2 blocks.
229
+
230
+ It answers at 45 seconds against a 90-second harness timeout, and that gap is
231
+ the whole design. Measured here: a hook killed at its timeout emits nothing and
232
+ **the tool proceeds** — `permission_denials` came back 0 and the command ran. A
233
+ hook the harness never has to kill fails closed instead, so a shut panel is a
234
+ denial rather than an opening.
235
+
236
+ The waiting costs no processes. A bounded read on a fifo held open read-write
237
+ blocks for its timeout and never sees EOF; the alternative, a `sleep` per poll,
238
+ spends seconds of fork overhead on Git Bash. Both the fifo and the shell's
239
+ support for fractional timeouts are probed with exactly what the loop will run —
240
+ bash 3.2 ignores a fractional `-t` and turns the poll into a hot spin, which is
241
+ how the first version passed while spinning 185,000 times in five seconds.
242
+
243
+ Interactive prompts have a limit worth stating: `AskUserQuestion`, `ExitPlanMode`
244
+ and `EnterPlanMode` are absent from a headless session's 78-tool list, in every
245
+ permission mode, while an interactive session has them. So there is no
246
+ structured choice to render. When a reply offers options in prose the panel
247
+ makes them clickable, which sends that text — a shortcut for typing it, not a
248
+ channel that does not exist.
249
+
250
+ ## Security
251
+
252
+ The server binds to `127.0.0.1` only, and the host is deliberately not
253
+ configurable — it reads a developer's live sessions and can start new ones.
254
+
255
+ A token is always required for `/api/`. Supply one, or let the server generate
256
+ one and print it with the URL:
257
+
258
+ ```bash
259
+ CREW_STUDIO_TOKEN=$(uuidgen) node .claude/studio/server/index.js
260
+ ```
261
+
262
+ Anything that changes state needs, on top of the token, a header no cross-origin
263
+ page can attach without a preflight this server never answers. Permission modes
264
+ are an allow-list — `plan` (the default), `acceptEdits`, `default` — so a mode
265
+ that skips Crewforth's gates cannot be requested, and the panel never has to name
266
+ one to refuse it.