@clearlysh/beehaven 0.8.16
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 +201 -0
- package/dist/__tests__/_cli-switch.js +105 -0
- package/dist/__tests__/agent-wrap-probe.js +136 -0
- package/dist/agent-attribution.js +192 -0
- package/dist/agent-identity-daemon.js +135 -0
- package/dist/agent-onboard.js +156 -0
- package/dist/agent-scope.js +79 -0
- package/dist/agent-sessions.js +370 -0
- package/dist/agent-state.js +482 -0
- package/dist/app-manifest.js +221 -0
- package/dist/app-signer.js +54 -0
- package/dist/app-signing.js +127 -0
- package/dist/audio-play.js +98 -0
- package/dist/avatar-protocol.js +25 -0
- package/dist/avatar-route.js +79 -0
- package/dist/bee/cloud-proxy.js +130 -0
- package/dist/blocked-actions.js +120 -0
- package/dist/build-channel.js +101 -0
- package/dist/buildings/daemon-workspace.js +475 -0
- package/dist/claude-bridge.js +310 -0
- package/dist/claude-credential-store.js +633 -0
- package/dist/clearly-sync.js +518 -0
- package/dist/clearly.js +616 -0
- package/dist/cli-state.js +334 -0
- package/dist/cli.js +6973 -0
- package/dist/commands/agent-skills.js +302 -0
- package/dist/commands/agent.js +1310 -0
- package/dist/commands/app.js +1123 -0
- package/dist/commands/auth.js +171 -0
- package/dist/commands/building-shell.js +392 -0
- package/dist/commands/canvas.js +932 -0
- package/dist/commands/claude.js +218 -0
- package/dist/commands/compliance.js +387 -0
- package/dist/commands/compose.js +507 -0
- package/dist/commands/composition.js +95 -0
- package/dist/commands/connect-session.js +409 -0
- package/dist/commands/conversations.js +160 -0
- package/dist/commands/costs.js +443 -0
- package/dist/commands/d1.js +253 -0
- package/dist/commands/daemon-cmd.js +162 -0
- package/dist/commands/deploy.js +164 -0
- package/dist/commands/design.js +617 -0
- package/dist/commands/dev-generate.js +125 -0
- package/dist/commands/dev.js +109 -0
- package/dist/commands/devices.js +135 -0
- package/dist/commands/explain-router.js +24 -0
- package/dist/commands/explain.js +882 -0
- package/dist/commands/explore.js +264 -0
- package/dist/commands/help.js +2418 -0
- package/dist/commands/init.js +408 -0
- package/dist/commands/install.js +129 -0
- package/dist/commands/library.js +229 -0
- package/dist/commands/marketplace.js +138 -0
- package/dist/commands/mcp-install.js +476 -0
- package/dist/commands/mention.js +257 -0
- package/dist/commands/omni.js +529 -0
- package/dist/commands/secrets.js +323 -0
- package/dist/commands/self-update.js +206 -0
- package/dist/commands/sheet.js +264 -0
- package/dist/commands/shell-output.js +309 -0
- package/dist/commands/shell.js +1048 -0
- package/dist/commands/shop.js +368 -0
- package/dist/commands/skills.js +311 -0
- package/dist/commands/slides.js +418 -0
- package/dist/commands/swarm.js +341 -0
- package/dist/commands/ticket.js +1301 -0
- package/dist/commands/tool.js +312 -0
- package/dist/commands/trash.js +106 -0
- package/dist/commands/treehouse.js +120 -0
- package/dist/commands/user.js +240 -0
- package/dist/commands/voice-tts.js +319 -0
- package/dist/commands/voice.js +166 -0
- package/dist/commands/watch-git.js +401 -0
- package/dist/commands/webhook.js +159 -0
- package/dist/commands/workspace.js +3354 -0
- package/dist/composition-repos.js +91 -0
- package/dist/daemon-avatar.js +130 -0
- package/dist/daemon-claude-code-auto-install.js +52 -0
- package/dist/daemon-client.js +363 -0
- package/dist/daemon-codex.js +349 -0
- package/dist/daemon-entry.js +101 -0
- package/dist/daemon-fetch-allowlist.js +194 -0
- package/dist/daemon-gemini.js +224 -0
- package/dist/daemon-mcp-clearly.js +353 -0
- package/dist/daemon-mcp-sandbox.js +127 -0
- package/dist/daemon-omni-company.js +338 -0
- package/dist/daemon-omni-hooks.js +375 -0
- package/dist/daemon-omni-identity.js +229 -0
- package/dist/daemon-omni-pipeline.js +251 -0
- package/dist/daemon-omni-policies.js +346 -0
- package/dist/daemon-omni-principal.js +580 -0
- package/dist/daemon-omni-tool-gate.js +116 -0
- package/dist/daemon-omni.js +1442 -0
- package/dist/daemon-path-transform.js +120 -0
- package/dist/daemon-write-sandbox.js +191 -0
- package/dist/daemon.js +4471 -0
- package/dist/dashboard.js +846 -0
- package/dist/dep-installer.js +286 -0
- package/dist/dev-mode.js +67 -0
- package/dist/doc-indexer.js +169 -0
- package/dist/e2e-crypto.js +94 -0
- package/dist/feature-flags.js +154 -0
- package/dist/file-browser.js +88 -0
- package/dist/first-party-hives.js +211 -0
- package/dist/folder-sync.js +226 -0
- package/dist/health.js +56 -0
- package/dist/ipc-auth.js +299 -0
- package/dist/ipc-client.js +495 -0
- package/dist/ipc-server.js +684 -0
- package/dist/keychain.js +224 -0
- package/dist/lib/admin-client.js +73 -0
- package/dist/lib/mobile-build-parser.js +156 -0
- package/dist/local-app-manager.js +660 -0
- package/dist/log-redaction.js +89 -0
- package/dist/logger.js +108 -0
- package/dist/manifest.js +143 -0
- package/dist/marketplace.js +793 -0
- package/dist/min-version-copy.js +51 -0
- package/dist/min-version.js +214 -0
- package/dist/public-surface.js +23 -0
- package/dist/relay-presets.js +89 -0
- package/dist/relay.js +2723 -0
- package/dist/repl.js +619 -0
- package/dist/setup-relay.js +363 -0
- package/dist/setup-service.js +536 -0
- package/dist/shared/bee-memory/index.js +6 -0
- package/dist/shared/bee-memory/types.js +682 -0
- package/dist/shared/claude-code/daemon-types.js +112 -0
- package/dist/shared/claude-code/index.js +2 -0
- package/dist/shared/claude-code/types.js +1 -0
- package/dist/shared/status/schema.js +133 -0
- package/dist/shell-session.js +198 -0
- package/dist/speak-lock.js +97 -0
- package/dist/spinner.js +57 -0
- package/dist/telemetry.js +166 -0
- package/dist/terminal/block-parser.js +207 -0
- package/dist/terminal/shell-integration.js +108 -0
- package/dist/transcript-tailer.js +215 -0
- package/dist/tts-qwen3.js +547 -0
- package/dist/types.js +4 -0
- package/dist/utm.js +38 -0
- package/dist/verb-surface.js +331 -0
- package/dist/version-utils.js +85 -0
- package/dist/watcher.js +207 -0
- package/package.json +88 -0
- package/python/qwen3_tts.py +230 -0
- package/scripts/stamp-build-channel.mjs +115 -0
- package/scripts/sync-installed.mjs +159 -0
- package/scripts/sync-skills.mjs +112 -0
- package/skills/README.md +24 -0
- package/skills/agent-doodle-space/SKILL.md +118 -0
- package/skills/agent-home/SKILL.md +98 -0
- package/skills/beehaven-cli/SKILL.md +144 -0
- package/skills/claude-shopper/README.md +90 -0
- package/skills/claude-shopper/SKILL.md +151 -0
- package/skills/clearly-agent/SKILL.md +183 -0
- package/skills/clearly-canvas/SKILL.md +222 -0
- package/skills/clearly-canvas/authoring.md +160 -0
- package/skills/clearly-canvas/communications.md +32 -0
- package/skills/clearly-canvas/composition-patterns.md +84 -0
- package/skills/clearly-canvas/example.mjs +78 -0
- package/skills/clearly-canvas/project-plans.md +156 -0
- package/skills/clearly-canvas/review.mjs +68 -0
- package/skills/clearly-workspace/SKILL.md +79 -0
- package/skills/clearly-workspace/survey.mjs +101 -0
- package/skills/codebase-map/SKILL.md +142 -0
- package/skills/design-craft/SKILL.md +300 -0
- package/skills/index.json +79 -0
- package/skills/layout-systems/SKILL.md +184 -0
- package/skills/pair-on-canvas/SKILL.md +92 -0
|
@@ -0,0 +1,2418 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* beehaven help <command> — deep per-command help.
|
|
3
|
+
*
|
|
4
|
+
* `beehaven --help` prints the whole surface in one shot (great for
|
|
5
|
+
* humans scanning). `beehaven help <cmd>` prints just one command's
|
|
6
|
+
* synopsis, flags, and 2-3 examples. Agents use this before running
|
|
7
|
+
* unfamiliar commands.
|
|
8
|
+
*
|
|
9
|
+
* The help text lives inline here (not as a parallel docs directory)
|
|
10
|
+
* so it stays in lockstep with the CLI's actual behavior. Each entry
|
|
11
|
+
* mirrors the dispatch logic in cli.ts; change both together.
|
|
12
|
+
*
|
|
13
|
+
* Design constraint: every help page MUST end with "Related:" so the
|
|
14
|
+
* agent can navigate to adjacent commands without re-reading the
|
|
15
|
+
* top-level help. Keeps the "pwd → actions → call" loop tight.
|
|
16
|
+
*/
|
|
17
|
+
import { HIDDEN_PUBLIC_COMMANDS } from '../public-surface.js';
|
|
18
|
+
/** Cheap edit distance for "did you mean" — ranking only, not optimal. */
|
|
19
|
+
function editDistance(a, b) {
|
|
20
|
+
if (a === b)
|
|
21
|
+
return 0;
|
|
22
|
+
if (Math.abs(a.length - b.length) > 3)
|
|
23
|
+
return 99;
|
|
24
|
+
let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
25
|
+
for (let i = 1; i <= a.length; i++) {
|
|
26
|
+
const cur = [i];
|
|
27
|
+
for (let j = 1; j <= b.length; j++) {
|
|
28
|
+
cur[j] = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
29
|
+
}
|
|
30
|
+
prev = cur;
|
|
31
|
+
}
|
|
32
|
+
return prev[b.length];
|
|
33
|
+
}
|
|
34
|
+
const PAGES = {
|
|
35
|
+
/**
|
|
36
|
+
* ⚠⚠ THE WORK ARTIFACTS — `ticket`, `board`, `sheet`, `slides`. `ticket` and `board` shipped
|
|
37
|
+
* 2026-09-04 in NEITHER help output, which is how the busiest new domain on the surface
|
|
38
|
+
* (1,062 calls) became findable only by already knowing it was there. `sheet` and `slides`
|
|
39
|
+
* are new here and documented in the same commit, per this package's own rule: a verb is added
|
|
40
|
+
* to `printHelp()` AND given a page.
|
|
41
|
+
*/
|
|
42
|
+
/**
|
|
43
|
+
* ⚠ `open` IS IN THE DEFAULT HELP AND HAD NO PAGE — the same gap the block below records for
|
|
44
|
+
* the first-run commands, on a verb three of these pages point at. A "Related" link to a page
|
|
45
|
+
* that does not exist is a dead end at exactly the moment someone is looking for more.
|
|
46
|
+
*/
|
|
47
|
+
open: {
|
|
48
|
+
synopsis: 'beehaven open <id|key|title> [--browser]',
|
|
49
|
+
description: 'Put something on screen. Takes a composition, document, board, project or ticket — addressed by '
|
|
50
|
+
+ 'id, by a KEY like CLR-42, or by an exact title — and navigates an already-open tab to it. It '
|
|
51
|
+
+ 'ALWAYS prints the URL, so it is useful with no tab open and safe in a script.\n\n'
|
|
52
|
+
+ 'This is how you hand a person the thing you just made: create it, then open it.\n\n'
|
|
53
|
+
+ '⚠⚠ THE KEY FORM DID NOT WORK UNTIL 2026-09-05 (CBH2-5) — the example below, printed on this '
|
|
54
|
+
+ 'very page, answered "Nothing in this workspace has id \'CLR-42\'". Only a uuid resolved, so the '
|
|
55
|
+
+ 'one verb whose whole job is handing someone a link required a SQL query first, on a workspace '
|
|
56
|
+
+ 'that mints keys precisely so nobody carries a uuid. An ambiguous key or title is now refused '
|
|
57
|
+
+ 'with the candidates listed, never guessed.\n\n'
|
|
58
|
+
+ '⚠ THE PRINTED URL FOLLOWS `beehaven env`. It used to be whichever origin a connected browser '
|
|
59
|
+
+ 'last reported, so a colleague\'s localhost dev tab could make this print a dead link (CBH-45).',
|
|
60
|
+
flags: [
|
|
61
|
+
{ name: '--browser', desc: 'Also open it in your local browser, rather than only navigating an existing tab.' },
|
|
62
|
+
],
|
|
63
|
+
examples: [
|
|
64
|
+
{ cmd: 'beehaven open CLR-42' },
|
|
65
|
+
{ cmd: 'beehaven open S1-14', note: 'a ticket key — opens its board with the card up' },
|
|
66
|
+
{ cmd: 'beehaven open <compositionId> --browser' },
|
|
67
|
+
],
|
|
68
|
+
related: ['ticket', 'sheet', 'slides'],
|
|
69
|
+
},
|
|
70
|
+
comment: {
|
|
71
|
+
synopsis: 'beehaven comment <ref> "text" [--quote|--slide|--cell|--sheet|--column|--pin|--x --y] [--reply <id>]',
|
|
72
|
+
description: 'Comment on ANY workspace item — a document, sheet, deck, ticket, board, thought or canvas — by id, '
|
|
73
|
+
+ 'key (SS-41, CLR-42) or exact title. It dispatches to that surface\'s own comment verb, so every '
|
|
74
|
+
+ 'anchor rule and permission applies unchanged; an anchor the surface cannot carry is REFUSED, never '
|
|
75
|
+
+ 'silently dropped.\n\n'
|
|
76
|
+
+ '`@handle` in the text mentions a person (they are notified) or an agent (it is queued in that '
|
|
77
|
+
+ 'agent\'s inbox and shown in its next brief until acknowledged). The receipt says who was reached '
|
|
78
|
+
+ 'and names any handle that matched nobody. `beehaven mention who` lists the handles that resolve.',
|
|
79
|
+
flags: [
|
|
80
|
+
{ name: '--quote <text>', desc: 'Document: the exact passage to anchor to.' },
|
|
81
|
+
{ name: '--slide <n|id>', desc: 'Deck: the slide (1-based or id). Required on a deck.' },
|
|
82
|
+
{ name: '--cell <A1>', desc: 'Sheet: the cell, optionally with its tab ("Q1!B4"). Omit for the whole sheet.' },
|
|
83
|
+
{ name: '--sheet <tab>', desc: 'Sheet: the tab name or id, when --cell names none.' },
|
|
84
|
+
{ name: '--column <key|label>', desc: 'Board: pin the comment to a column.' },
|
|
85
|
+
{ name: '--pin <id>', desc: 'Canvas: reply to an existing comment pin.' },
|
|
86
|
+
{ name: '--x <n> --y <n>', desc: 'Canvas: drop a new pin at these world coordinates.' },
|
|
87
|
+
{ name: '--reply <id>', desc: 'Reply to an existing comment.' },
|
|
88
|
+
{ name: '--kind <k>', desc: 'Disambiguate a <ref> that names two kinds of thing.' },
|
|
89
|
+
{ name: '--json', desc: 'Raw result instead of the summary.' },
|
|
90
|
+
],
|
|
91
|
+
examples: [
|
|
92
|
+
{ cmd: 'beehaven comment SS-41 "Ready for review @admin"' },
|
|
93
|
+
{ cmd: 'beehaven comment "Q3 plan" "This total looks off @omni" --cell "Plan!D12"' },
|
|
94
|
+
{ cmd: 'beehaven comment <deckId> "Tighten this headline" --slide 3' },
|
|
95
|
+
{ cmd: 'beehaven comments SS-41 --all' },
|
|
96
|
+
],
|
|
97
|
+
related: ['mention', 'ticket'],
|
|
98
|
+
},
|
|
99
|
+
mention: {
|
|
100
|
+
synopsis: 'beehaven mention [list|ack <id>|who [query]|resolve "text"]',
|
|
101
|
+
description: 'Where you were @mentioned, and who an @ can reach. As an agent, `beehaven mention` lists the '
|
|
102
|
+
+ 'mentions queued in your inbox — the same list your brief prints under "Addressed to you". Act on '
|
|
103
|
+
+ 'one (reply with `beehaven comment`), then `ack` it: an unacknowledged mention replays in every '
|
|
104
|
+
+ 'brief, and you will do the work twice. `who` lists people and agents from the same index the '
|
|
105
|
+
+ 'server delivers against, so a handle it offers always resolves.',
|
|
106
|
+
flags: [
|
|
107
|
+
{ name: '--all', desc: 'On list: include acknowledged mentions.' },
|
|
108
|
+
{ name: '--json', desc: 'Raw result.' },
|
|
109
|
+
],
|
|
110
|
+
examples: [
|
|
111
|
+
{ cmd: 'beehaven mention' },
|
|
112
|
+
{ cmd: 'beehaven mention ack 3f2a9c1e' },
|
|
113
|
+
{ cmd: 'beehaven mention who jin' },
|
|
114
|
+
{ cmd: 'beehaven mention resolve "cc @omni and @bob"' },
|
|
115
|
+
],
|
|
116
|
+
related: ['comment'],
|
|
117
|
+
},
|
|
118
|
+
ticket: {
|
|
119
|
+
synopsis: 'beehaven ticket <create|list|move|edit|show|comment|comments|delete> [args]',
|
|
120
|
+
description: 'Cards on a board. A card IS a ticket — one board model — so this is what files work, not `task`, '
|
|
121
|
+
+ 'which makes a NOTE. Every subcommand takes a key (CLR-42) or a row id.\n\n'
|
|
122
|
+
+ 'The verb exists to make three already-shipped traps untypeable: --priority takes a WORD, because '
|
|
123
|
+
+ 'the API scale is 0-3 with 3 the MOST urgent (the opposite of P0/P1, and a card meant as top '
|
|
124
|
+
+ 'priority filed as 0 becomes the least urgent thing on the board with nothing to say so); the body '
|
|
125
|
+
+ 'is sent as `body`, never `description`, which validation would strip; and the type is sent as '
|
|
126
|
+
+ '`issueType`, never `type`, which the wire uses as its own action discriminator.\n\n'
|
|
127
|
+
+ 'WHERE a card is lives on `move` (its column, and its board); WHAT a card says lives on `edit`. '
|
|
128
|
+
+ 'Two verbs writing one field is the two-doors failure this CLI names repeatedly, so `edit` '
|
|
129
|
+
+ 'refuses --status and --board rather than duplicating them.\n\n'
|
|
130
|
+
+ '`delete` is the only DESTRUCTIVE subcommand and behaves unlike `board delete`: it PREVIEWS '
|
|
131
|
+
+ 'the card and refuses without --yes. Board deletion is safe to fire because the server refuses '
|
|
132
|
+
+ 'while any card references the board; nothing equivalent protects a card. Measured against a '
|
|
133
|
+
+ 'real workspace: it is a HARD delete (the row is gone, not archived, with nothing to restore '
|
|
134
|
+
+ 'from), it is NOT idempotent (a second attempt answers not-found, identical to a typo\'d key), '
|
|
135
|
+
+ 'and it ORPHANS the card\'s comments rather than removing them.',
|
|
136
|
+
flags: [
|
|
137
|
+
{ name: '--board <id>', desc: 'Which board. Defaults to the oldest non-archived one. On `move`, where to move it TO.' },
|
|
138
|
+
{ name: '--body <text>', desc: 'The card description. Sent as `body` — `description` would be stripped.' },
|
|
139
|
+
{ name: '--type <t>', desc: 'epic | story | task | bug | subtask' },
|
|
140
|
+
{ name: '--priority <p>', desc: 'low | medium | high | urgent — a WORD, never a number.' },
|
|
141
|
+
{ name: '--status <s>', desc: 'todo | in-progress | in-review | done. On `create` only — to change one, use `move`.' },
|
|
142
|
+
{ name: '--assignee <who>', desc: 'Who owns it.' },
|
|
143
|
+
{ name: '--due <when>', desc: 'ISO date (2026-10-01), a full timestamp, or epoch ms. Parsed to a number — the column is epoch ms.' },
|
|
144
|
+
{ name: '--allow-duplicate', desc: 'On `create`: file a second card with a title already open on this board.' },
|
|
145
|
+
{ name: '--limit <n>', desc: 'On `list`: how many cards, default 100, ceiling 500 (the server\'s). A full page says so.' },
|
|
146
|
+
{ name: '--title <t>', desc: 'On `edit`: rename the card.' },
|
|
147
|
+
{ name: '--points <n>', desc: 'On `edit`: size it. A board nobody sizes reports 0 points in `board report`.' },
|
|
148
|
+
{ name: '--epic <id>', desc: 'On `edit`: file it under an epic.' },
|
|
149
|
+
{ name: '--parent <id>', desc: 'On `edit`: its parent card (a subtask needs one).' },
|
|
150
|
+
{ name: '--sprint <id>', desc: 'On `edit`: the sprint it belongs to. `beehaven sprint plan` is the bulk form.' },
|
|
151
|
+
{ name: '--resolution <r>', desc: 'On `edit`: WHY it closed. Its own column — a reason in `body` is indistinguishable from the report.' },
|
|
152
|
+
{ name: '--reply <id>', desc: 'On `comment`: reply to an existing note.' },
|
|
153
|
+
{ name: '--all', desc: 'On `comments`: include resolved notes.' },
|
|
154
|
+
{ name: '--yes', desc: 'On `delete`: actually destroy the card. Without it the card is shown and nothing is deleted.' },
|
|
155
|
+
{ name: '--json', desc: 'Raw result instead of the summary.' },
|
|
156
|
+
],
|
|
157
|
+
examples: [
|
|
158
|
+
{ cmd: 'beehaven ticket create "Fix the login redirect" --priority high --type bug' },
|
|
159
|
+
{ cmd: 'beehaven ticket list --board <id> --status todo --limit 300' },
|
|
160
|
+
{ cmd: 'beehaven ticket move CLR-42 done' },
|
|
161
|
+
{ cmd: 'beehaven ticket edit CLR-42 --points 3 --due 2026-10-01' },
|
|
162
|
+
{ cmd: 'beehaven ticket comment CLR-42 "shipped in 0.8.2"' },
|
|
163
|
+
],
|
|
164
|
+
related: ['board', 'sprint', 'task', 'open'],
|
|
165
|
+
},
|
|
166
|
+
board: {
|
|
167
|
+
// ⚠ NO `show`. The synopsis said `<list|create|show>` while the description below explained
|
|
168
|
+
// there deliberately is no `board show` — a page contradicting itself in eight lines, and
|
|
169
|
+
// `cmdBoard` implements exactly two subcommands. A synopsis is the part people copy.
|
|
170
|
+
synopsis: 'beehaven board <list|create|delete|columns|report|backlog> [args]',
|
|
171
|
+
description: 'Boards hold cards. A ticket REQUIRES a board — `ticket-create` refuses without one, because a card '
|
|
172
|
+
+ 'with no board is one you made, were told about, and cannot find.\n\n'
|
|
173
|
+
+ 'The board title derives the ticket key prefix ("Sprint 1" → S1-14), and the prefix records where '
|
|
174
|
+
+ 'a card was BORN, not where it lives now: moving a card between boards does not re-key it.\n\n'
|
|
175
|
+
+ 'To read a board WITH its cards, `cat "~/<Board>.board.json"` does it in one call — there is '
|
|
176
|
+
+ 'deliberately no `board show` duplicating that.\n\n'
|
|
177
|
+
+ '`delete` REFUSES while any ticket still references the board, closed ones included — unpinning '
|
|
178
|
+
+ 'them would leave real cards on no board, which is the state `ticket-create` requires a board to '
|
|
179
|
+
+ 'prevent. Move them first. It must be given a name: with none, board resolution falls back to the '
|
|
180
|
+
+ 'OLDEST board in the workspace, which is right for filing a card and catastrophic for a delete.\n\n'
|
|
181
|
+
+ '`columns` is the board\'s WORKFLOW, and it is read-only here. A column key IS a legal status '
|
|
182
|
+
+ 'on that board, so the column set is the vocabulary cards are filed in — and it had no human '
|
|
183
|
+
+ 'reader at all: `board-get` returns it as a JSON STRING in a raw row and says nothing about '
|
|
184
|
+
+ 'cards. This joins it to the cards, so it also reports STRANDED statuses: words held by real '
|
|
185
|
+
+ 'cards that no column defines, which draw in no column and cannot be dragged.\n\n'
|
|
186
|
+
+ 'Changing the workflow stays `beehaven call board-columns-set` on purpose while CBH2-143 is '
|
|
187
|
+
+ 'in review — that ticket is deciding whether the action reports, refuses or migrates stranded '
|
|
188
|
+
+ 'cards, and a CLI writer would be a second implementation of the same safety rule. Read first, '
|
|
189
|
+
+ 'then call: the action migrates nothing, so a card whose status word you remove keeps it.\n\n'
|
|
190
|
+
+ '`report` is the tracker metric (velocity, burndown, cycle-time) — server-computed, so nobody '
|
|
191
|
+
+ 'derives velocity by hand. Points come from the `points` COLUMN, so a board nobody sized reports '
|
|
192
|
+
+ 'zero truthfully. `backlog` is what sprint planning pulls from; it is NOT status-filtered, so '
|
|
193
|
+
+ 'finished cards that were never put in a sprint appear in it too.',
|
|
194
|
+
flags: [
|
|
195
|
+
{ name: '--project <id>', desc: 'On `create`: file the board under a project.' },
|
|
196
|
+
{ name: '--kind <k>', desc: 'On `report`: summary (default) | velocity | burndown | cycle-time.' },
|
|
197
|
+
{ name: '--sprint <id>', desc: 'On `report`: scope a burndown to one sprint.' },
|
|
198
|
+
{ name: '--board <b>', desc: 'Name the board, instead of passing it as a positional.' },
|
|
199
|
+
{ name: '--json', desc: 'Raw result instead of the summary.' },
|
|
200
|
+
],
|
|
201
|
+
examples: [
|
|
202
|
+
{ cmd: 'beehaven board list' },
|
|
203
|
+
{ cmd: 'beehaven board create "Sprint 2"' },
|
|
204
|
+
{ cmd: 'beehaven board delete "Old probe board"', note: 'refuses while cards are on it' },
|
|
205
|
+
{ cmd: 'beehaven board report "Sprint 2" --kind velocity' },
|
|
206
|
+
{ cmd: 'beehaven board backlog "Sprint 2"' },
|
|
207
|
+
{ cmd: 'cat "~/Sprint 2.board.json"', note: 'the board and every card on it' },
|
|
208
|
+
],
|
|
209
|
+
related: ['ticket', 'sprint', 'open'],
|
|
210
|
+
},
|
|
211
|
+
/**
|
|
212
|
+
* ⚠⚠ THIS PAGE EXISTS BECAUSE A SHIPPED PROMPT POINTED AT VERBS THE CLI DID NOT HAVE — CBH2-107.
|
|
213
|
+
* `daemon-omni-company.ts` tells agents to call `sprint-create` / `-plan` / `-start` / `-complete`
|
|
214
|
+
* and `burndown`; all of it was `beehaven call`-only.
|
|
215
|
+
*/
|
|
216
|
+
sprint: {
|
|
217
|
+
synopsis: 'beehaven sprint <list|create|plan|start|complete|delete> [args]',
|
|
218
|
+
description: 'The planning cycle on a board. A sprint is created `planned`, `start` makes it `active` (one per '
|
|
219
|
+
+ 'board at a time), and `complete` closes it and records the velocity datapoint.\n\n'
|
|
220
|
+
+ 'STARTING FREEZES THE COMMITMENT. `committed_points` is captured at `start` and never recomputed, '
|
|
221
|
+
+ 'because velocity measured against a denominator that grows as cards are added mid-sprint always '
|
|
222
|
+
+ 'looks fine — which is the failure the metric exists to catch. So size the cards BEFORE you start; '
|
|
223
|
+
+ 'a card sized afterwards does not count.\n\n'
|
|
224
|
+
+ '⚠ `delete`, NOT `complete`, IS THE UNDO. A completed sprint is a permanent velocity datapoint '
|
|
225
|
+
+ 'that `board report` averages over, so completing a junk sprint corrupts the metric instead of '
|
|
226
|
+
+ 'discarding it. `delete` sends its cards back to the backlog and never deletes them.\n\n'
|
|
227
|
+
+ 'Sprints are addressed by NAME here (or by id). Auto-numbering means two boards routinely both '
|
|
228
|
+
+ 'hold a "Sprint 1", so an ambiguous name is refused rather than guessed — narrow it with --board.\n\n'
|
|
229
|
+
+ '⚠ `sprint plan` resolves card KEYS to row ids before calling. The underlying `sprint-plan` action '
|
|
230
|
+
+ 'takes ROW IDS and answers `{ ok: true, moved: 1 }` for a key it never moved, so `beehaven call '
|
|
231
|
+
+ 'sprint-plan` with keys silently does nothing.',
|
|
232
|
+
flags: [
|
|
233
|
+
{ name: '--board <b>', desc: 'Which board. Required in effect on `create`; narrows an ambiguous name elsewhere.' },
|
|
234
|
+
{ name: '--state <s>', desc: 'On `list`: planned | active | completed. A SPRINT\'s lifecycle, not a card\'s column.' },
|
|
235
|
+
{ name: '--goal "<g>"', desc: 'On `create`: what the sprint is for.' },
|
|
236
|
+
{ name: '--remove', desc: 'On `plan`: take the cards OUT, back to the backlog.' },
|
|
237
|
+
{ name: '--sprint <id>', desc: 'On `complete`: where unfinished cards go. Omitted, they go to the backlog.' },
|
|
238
|
+
{ name: '--force', desc: 'On `delete`: delete an ACTIVE sprint — the one people are working in.' },
|
|
239
|
+
{ name: '--json', desc: 'Raw result instead of the summary.' },
|
|
240
|
+
],
|
|
241
|
+
examples: [
|
|
242
|
+
{ cmd: 'beehaven sprint list --board "Sprint 2"' },
|
|
243
|
+
{ cmd: 'beehaven sprint create "Sprint 3" --board "Sprint 2" --goal "Close the parity gaps"' },
|
|
244
|
+
{ cmd: 'beehaven sprint plan "Sprint 3" CLR-42 CLR-43' },
|
|
245
|
+
{ cmd: 'beehaven sprint start "Sprint 3"' },
|
|
246
|
+
{ cmd: 'beehaven sprint complete "Sprint 3"' },
|
|
247
|
+
{ cmd: 'beehaven board report --kind velocity', note: 'how the last sprints actually went' },
|
|
248
|
+
],
|
|
249
|
+
related: ['board', 'ticket'],
|
|
250
|
+
},
|
|
251
|
+
sheet: {
|
|
252
|
+
synopsis: 'beehaven sheet <list|new|get|set|append|import> [args]',
|
|
253
|
+
description: 'Spreadsheets. A sheet is a document row — key, project filing, trash and search like anything else.\n\n'
|
|
254
|
+
+ '⚠ `set` and `append` are not synonyms. `set` writes a block at an ANCHOR cell and replaces what is '
|
|
255
|
+
+ 'there; `append` adds after the last populated row and never overwrites. The underlying action takes '
|
|
256
|
+
+ '`{ at, rows }`, not a range and a blob — this verb takes the anchor and does the TSV parse, because '
|
|
257
|
+
+ 'sending `{ range, tsv }` is two unknown keys that validation strips, leaving a call that returns ok '
|
|
258
|
+
+ 'having written nothing.\n\n'
|
|
259
|
+
+ 'Formulas work: `=SUM(B2:B9)` comes back as its computed total, not as text.',
|
|
260
|
+
flags: [
|
|
261
|
+
{ name: '--range <a1>', desc: 'get only — the range to read, e.g. A1:D20.' },
|
|
262
|
+
{ name: '--project <id>', desc: 'File a new sheet into a project.' },
|
|
263
|
+
{ name: '--title <t>', desc: 'import only — title for the created sheet.' },
|
|
264
|
+
{ name: '--json', desc: 'Raw result instead of the table.' },
|
|
265
|
+
],
|
|
266
|
+
examples: [
|
|
267
|
+
{ cmd: 'beehaven sheet new "Q1 revenue"' },
|
|
268
|
+
{ cmd: 'beehaven sheet set CLR-42 A1 "Region\\tQ1\\nAPAC\\t7"', note: 'A1 is the top-left cell, not a range' },
|
|
269
|
+
{ cmd: 'beehaven sheet append CLR-42 "EMEA\\t9"' },
|
|
270
|
+
{ cmd: 'beehaven teleport ./data.csv && beehaven sheet import <fileId>' },
|
|
271
|
+
],
|
|
272
|
+
related: ['slides', 'teleport', 'doc'],
|
|
273
|
+
},
|
|
274
|
+
brand: {
|
|
275
|
+
synopsis: 'beehaven brand <list|show|tokens|new|set|edit|default|bind|board|history|revert|rm|restore> [args]',
|
|
276
|
+
description: 'The workspace brand — colours by role (light + dark), five type roles, logos, voice and shape — '
|
|
277
|
+
+ 'the same object agents read with `brand` / clearly_brand and the Brand studio edits.\n\n'
|
|
278
|
+
+ '⚠ `brand set <brand> color.<role> <hex>` changes ONE colour. It always sends the role map; '
|
|
279
|
+
+ 'sending `colors` as an array (e.g. via `brand edit --patch`) REPLACES the whole palette.\n\n'
|
|
280
|
+
+ '`show`, `tokens` and `board` use the workspace default brand when you omit one. Every edit is a '
|
|
281
|
+
+ 'version (`history`, `revert`), and `rm` is recoverable with `restore`.',
|
|
282
|
+
flags: [
|
|
283
|
+
{ name: '--format css|json', desc: 'tokens — CSS custom properties or the token map (default json).' },
|
|
284
|
+
{ name: '--mode dark', desc: 'tokens — the dark-mode values.' },
|
|
285
|
+
{ name: '--composition <id>', desc: "tokens/show — that canvas's bound brand; bind/board — the target canvas." },
|
|
286
|
+
{ name: '--patch <json|@file>', desc: 'edit — any brand patch.' },
|
|
287
|
+
{ name: '--from <brand>', desc: 'new — duplicate an existing brand.' },
|
|
288
|
+
{ name: '-o, --output <file>', desc: 'tokens — write to a file.' },
|
|
289
|
+
{ name: '--json', desc: 'Raw result.' },
|
|
290
|
+
],
|
|
291
|
+
examples: [
|
|
292
|
+
{ cmd: 'beehaven brand show' },
|
|
293
|
+
{ cmd: "beehaven brand set Harbor color.accent '#FF5500'", note: 'one role; the rest of the palette is untouched' },
|
|
294
|
+
{ cmd: 'beehaven brand set Harbor type.heading Fraunces' },
|
|
295
|
+
{ cmd: 'beehaven brand tokens --format css -o brand.css' },
|
|
296
|
+
{ cmd: 'beehaven brand board Harbor', note: 'an editable brand board on a new canvas' },
|
|
297
|
+
],
|
|
298
|
+
related: ['component', 'open'],
|
|
299
|
+
},
|
|
300
|
+
component: {
|
|
301
|
+
synopsis: 'beehaven component <list|show|render|place|save|new|edit|dup|history|revert|rm|restore> [args]',
|
|
302
|
+
description: 'The workspace component library — reusable blocks whose colours and faces are brand tokens, so '
|
|
303
|
+
+ 'they render in whatever brand a canvas uses. The same library as the editor\'s Assets tab and '
|
|
304
|
+
+ 'the agent tool `component` / clearly_component.\n\n'
|
|
305
|
+
+ '`place` puts a component on a canvas (resolved in its brand); `save` turns a canvas node and its '
|
|
306
|
+
+ 'layers into a component, re-binding brand colours and faces to tokens.\n\n'
|
|
307
|
+
+ '⚠ Placing into a canvas you have open in the editor: prefer the Assets tab or ⌘⌥K — the editor '
|
|
308
|
+
+ 'owns its scene while it is open.',
|
|
309
|
+
flags: [
|
|
310
|
+
{ name: '--composition <id>', desc: 'place/save — the canvas.' },
|
|
311
|
+
{ name: '--x <n> --y <n>', desc: 'place — top-left, world coords (frame-relative with --parent).' },
|
|
312
|
+
{ name: '--parent <frame>', desc: 'place — nest inside this frame (id or name).' },
|
|
313
|
+
{ name: '--variant <name>', desc: 'place/render — e.g. Secondary.' },
|
|
314
|
+
{ name: '--props <json>', desc: 'place/render — prop values, e.g. \'{"label":"Buy now"}\'.' },
|
|
315
|
+
{ name: '--brand <brand>', desc: 'place/render/show — render in this brand instead.' },
|
|
316
|
+
{ name: '--patch <json|@file>', desc: 'new/edit — a component spec or patch.' },
|
|
317
|
+
{ name: '--category <c>', desc: 'list/save — actions, inputs, display, navigation, feedback, layout, marketing, brand.' },
|
|
318
|
+
{ name: '-o, --output <file>', desc: 'render — write the SVG.' },
|
|
319
|
+
{ name: '--json', desc: 'Raw result.' },
|
|
320
|
+
],
|
|
321
|
+
examples: [
|
|
322
|
+
{ cmd: 'beehaven component list --category marketing' },
|
|
323
|
+
{ cmd: 'beehaven component render pricing-card --variant Featured -o card.svg' },
|
|
324
|
+
{ cmd: 'beehaven component place button --composition <id> --x 120 --y 80 --props \'{"label":"Start"}\'' },
|
|
325
|
+
{ cmd: 'beehaven component save --composition <id> "Hero frame" --name "Marketing hero"' },
|
|
326
|
+
],
|
|
327
|
+
related: ['brand', 'canvas', 'open'],
|
|
328
|
+
},
|
|
329
|
+
slides: {
|
|
330
|
+
synopsis: 'beehaven slides <list|new|get|add|move|rm|layouts|show|export> [args]',
|
|
331
|
+
description: 'Presentations. A deck is a document row like any other artifact here.\n\n'
|
|
332
|
+
+ '⚠ `show` renders a deck to LOOK at; `export` produces a FILE to take away. They are different '
|
|
333
|
+
+ 'actions with near-identical names, so they are two subcommands named for the job.\n\n'
|
|
334
|
+
+ '⚠ `move` needs a destination and the action refuses without one — so this verb takes it '
|
|
335
|
+
+ 'positionally (`slides move <id> <n> <to>`) rather than as a flag you can forget.\n\n'
|
|
336
|
+
+ '⚠ A layout typed from memory does not error: an unrecognised one silently falls back to '
|
|
337
|
+
+ '`titleBody`. Run `slides layouts` first.',
|
|
338
|
+
flags: [
|
|
339
|
+
{ name: '--layout <id>', desc: 'A layout id from `slides layouts`.' },
|
|
340
|
+
{ name: '--bullets "a|b|c"', desc: 'PIPE-separated — a bullet often contains a comma.' },
|
|
341
|
+
{ name: '--notes <text>', desc: 'Speaker notes.' },
|
|
342
|
+
{ name: '--at <n>', desc: 'add only — 1-based insert position. Omit to append.' },
|
|
343
|
+
{ name: '--slide <n>', desc: 'get / show — one slide instead of the whole deck.' },
|
|
344
|
+
{ name: '--aspect <a>', desc: 'new only — 16:9 (default) or 4:3.' },
|
|
345
|
+
{ name: '--format <f>', desc: 'export — pptx | html | markdown | notes | svg.' },
|
|
346
|
+
{ name: '--json', desc: 'Raw result instead of the outline.' },
|
|
347
|
+
],
|
|
348
|
+
examples: [
|
|
349
|
+
{ cmd: 'beehaven slides new "Q1 review" --aspect 16:9' },
|
|
350
|
+
{ cmd: 'beehaven slides add CLR-42 "Results" --bullets "Revenue up 12%|Churn flat"' },
|
|
351
|
+
{ cmd: 'beehaven slides move CLR-42 5 2', note: '<to> is required — the action refuses without it' },
|
|
352
|
+
{ cmd: 'beehaven slides export CLR-42 --format pptx' },
|
|
353
|
+
],
|
|
354
|
+
related: ['sheet', 'open', 'teleport'],
|
|
355
|
+
},
|
|
356
|
+
/**
|
|
357
|
+
* ⚠⚠ THE FIRST-RUN COMMANDS HAD NO HELP PAGES AT ALL — CLR-1150. `beehaven help login`
|
|
358
|
+
* answered *"No help page for \"login\""* and exited 1. Every command a new user runs in
|
|
359
|
+
* their first five minutes — login, start, stop, restart, status, doctor, env, whoami —
|
|
360
|
+
* was absent, while `cd`, `canvas` and `sql` were richly documented.
|
|
361
|
+
*
|
|
362
|
+
* That is backwards: deep help matters most where the user has least context, and least
|
|
363
|
+
* where they have already found the verb.
|
|
364
|
+
*/
|
|
365
|
+
login: {
|
|
366
|
+
synopsis: 'beehaven login',
|
|
367
|
+
description: `Sign in. Opens your browser, then starts (or restarts) the daemon so the
|
|
368
|
+
new tokens take effect — the daemon reads credentials at startup and has no hot-reload.
|
|
369
|
+
|
|
370
|
+
A restart alone will NOT refresh an expired token; \`login\` is the fix for that.`,
|
|
371
|
+
examples: [
|
|
372
|
+
{ cmd: 'beehaven login' },
|
|
373
|
+
{ cmd: 'beehaven status', note: 'confirms the relay actually connected' },
|
|
374
|
+
],
|
|
375
|
+
related: ['logout', 'whoami', 'status', 'doctor'],
|
|
376
|
+
},
|
|
377
|
+
logout: {
|
|
378
|
+
synopsis: 'beehaven logout',
|
|
379
|
+
description: 'Clear stored credentials (keychain + ~/.beehaven/config.json).',
|
|
380
|
+
related: ['login', 'whoami'],
|
|
381
|
+
},
|
|
382
|
+
whoami: {
|
|
383
|
+
synopsis: 'beehaven whoami',
|
|
384
|
+
description: 'Print the signed-in account and the workspace it resolves to.',
|
|
385
|
+
related: ['login', 'status'],
|
|
386
|
+
},
|
|
387
|
+
start: {
|
|
388
|
+
synopsis: 'beehaven start [--headless] [--dev]',
|
|
389
|
+
description: `Bring up the daemon — the local process every other command talks to.
|
|
390
|
+
|
|
391
|
+
\`--headless\` is the CLI-owned daemon and works on every platform. Bare \`start\`
|
|
392
|
+
opens the Hive Mac tray app instead, which is macOS-only; the tray is required only for
|
|
393
|
+
the LOCAL hive (avatar building, voice, mood), never for calls, MCP or SQL.
|
|
394
|
+
|
|
395
|
+
Only one daemon runs at a time. If one already owns the socket, \`--headless\` refuses.`,
|
|
396
|
+
flags: [
|
|
397
|
+
{ name: '--headless', desc: 'Spawn a standalone daemon (no Mac app needed)' },
|
|
398
|
+
{ name: '--dev', desc: 'Grant developer scope (same as HIVE_DEV_MODE=1)' },
|
|
399
|
+
],
|
|
400
|
+
examples: [
|
|
401
|
+
{ cmd: 'beehaven start --headless' },
|
|
402
|
+
{ cmd: 'HIVE_DEV_MODE=1 beehaven start --headless', note: 'needed for admin:* and raw-VFS commands' },
|
|
403
|
+
{ cmd: 'beehaven stop && beehaven start --headless', note: 'the reliable way to pick up a deploy' },
|
|
404
|
+
],
|
|
405
|
+
related: ['stop', 'restart', 'status', 'doctor', 'env'],
|
|
406
|
+
},
|
|
407
|
+
stop: {
|
|
408
|
+
synopsis: 'beehaven stop',
|
|
409
|
+
description: `Stop the daemon and release the IPC socket.
|
|
410
|
+
|
|
411
|
+
Also the first half of the sequence that makes a fresh worker deploy visible: a resident
|
|
412
|
+
Durable Object keeps serving the OLD code while any client holds a socket open.`,
|
|
413
|
+
examples: [{ cmd: 'beehaven stop && sleep 15 && beehaven start --headless' }],
|
|
414
|
+
related: ['start', 'restart', 'status'],
|
|
415
|
+
},
|
|
416
|
+
restart: {
|
|
417
|
+
synopsis: 'beehaven restart [--dev]',
|
|
418
|
+
description: `Stop and start in one step.
|
|
419
|
+
|
|
420
|
+
It does NOT refresh an expired token — that is \`beehaven login\`. And a bare restart
|
|
421
|
+
DROPS developer scope: pass --dev (or set HIVE_DEV_MODE=1) to keep it.`,
|
|
422
|
+
related: ['start', 'stop', 'login', 'status'],
|
|
423
|
+
},
|
|
424
|
+
doctor: {
|
|
425
|
+
synopsis: 'beehaven doctor',
|
|
426
|
+
description: `Diagnose the whole chain — Node version, daemon process, IPC socket, relay
|
|
427
|
+
state (splitting "token expired" from "socket dropped"), and a live list-actions
|
|
428
|
+
round-trip. Every failing line carries the command that fixes it.
|
|
429
|
+
|
|
430
|
+
Reach for this before debugging anything else.`,
|
|
431
|
+
related: ['status', 'start', 'login', 'env'],
|
|
432
|
+
},
|
|
433
|
+
env: {
|
|
434
|
+
synopsis: 'beehaven env [staging|prod|dev] [--confirm]',
|
|
435
|
+
description: `Show or switch which backend the daemon talks to.
|
|
436
|
+
|
|
437
|
+
Prod requires --confirm: a safety interlock, so a billable or destructive command is not
|
|
438
|
+
run against live customer data in the belief that it is staging.
|
|
439
|
+
|
|
440
|
+
A switch is not live until the daemon cycles.
|
|
441
|
+
|
|
442
|
+
⚠ --env on other commands does NOT do this. Every call goes wherever the daemon points.`,
|
|
443
|
+
examples: [
|
|
444
|
+
{ cmd: 'beehaven env', note: 'print the active env + relay URL' },
|
|
445
|
+
{ cmd: 'beehaven env staging' },
|
|
446
|
+
{ cmd: 'beehaven env prod --confirm' },
|
|
447
|
+
],
|
|
448
|
+
related: ['status', 'doctor', 'restart'],
|
|
449
|
+
},
|
|
450
|
+
cd: {
|
|
451
|
+
synopsis: 'beehaven cd <addr>',
|
|
452
|
+
description: `Set the active target. Writes ~/.beehaven/target.json so subsequent
|
|
453
|
+
commands (call, actions, ls, etc.) know where to route.
|
|
454
|
+
|
|
455
|
+
Address shapes:
|
|
456
|
+
home Your default workspace (alias)
|
|
457
|
+
workspace/<id> Any explicit workspace DO
|
|
458
|
+
<type>/<id> Another cloud DO — e.g. shopifyStore/clearly-demo
|
|
459
|
+
<appName> A local installed app — e.g. recorder, avatar
|
|
460
|
+
|
|
461
|
+
Inside a workspace, each signed human or agent has a personal layer for private drafts,
|
|
462
|
+
recents, sessions and memory. Changing identity changes that layer; it does not change DOs.
|
|
463
|
+
|
|
464
|
+
Aliases: connect, nav, navigate`,
|
|
465
|
+
examples: [
|
|
466
|
+
{ cmd: 'beehaven cd home', note: 'back to default workspace' },
|
|
467
|
+
{ cmd: 'beehaven cd workspace/<workspaceId>', note: 'another workspace' },
|
|
468
|
+
{ cmd: 'beehaven cd shopifyStore/clearly-demo', note: 'cloud DO' },
|
|
469
|
+
{ cmd: 'beehaven cd recorder', note: 'local app' },
|
|
470
|
+
],
|
|
471
|
+
related: ['pwd', 'disconnect', 'buildings', 'actions'],
|
|
472
|
+
},
|
|
473
|
+
pwd: {
|
|
474
|
+
synopsis: 'beehaven pwd',
|
|
475
|
+
description: `Show the current target + "what you can do here" hints. Reads
|
|
476
|
+
~/.beehaven/target.json — works even when the daemon isn't running.
|
|
477
|
+
Agents should call this FIRST in any new session to self-orient.
|
|
478
|
+
|
|
479
|
+
⚠⚠ ITS OWN HINT LINE \`call project-list '{}' --building home\` IS REFUSED IF
|
|
480
|
+
YOU ARE SIGNED IN AS AN AGENT, which almost every reader of pwd is:
|
|
481
|
+
Cannot use --building while signed in as "<name>".
|
|
482
|
+
A proxied call cannot be attributed to an agent in the target workspace.
|
|
483
|
+
Drop the flag — \`beehaven call project-list '{}'\` works and is attributed to
|
|
484
|
+
you. \`--building\` is for a HUMAN making one call against another target;
|
|
485
|
+
an agent switches with \`beehaven connect <address>\` instead.
|
|
486
|
+
|
|
487
|
+
Aliases: where`,
|
|
488
|
+
examples: [
|
|
489
|
+
{ cmd: 'beehaven pwd' },
|
|
490
|
+
{ cmd: `beehaven call project-list '{}'`, note: 'the hint line, without --building' },
|
|
491
|
+
{ cmd: 'beehaven workspaces', note: 'what else could I connect to' },
|
|
492
|
+
],
|
|
493
|
+
related: ['cd', 'status', 'actions', 'workspaces'],
|
|
494
|
+
},
|
|
495
|
+
canvas: {
|
|
496
|
+
synopsis: 'beehaven canvas <open|invoke|query|actions|help|record> [args]',
|
|
497
|
+
description: `Interact with the FAB canvas (notes editor) from the CLI.
|
|
498
|
+
|
|
499
|
+
Subcommands:
|
|
500
|
+
open <noteId> Open a note in the canvas editor
|
|
501
|
+
invoke <action> [json] Call an editor-client action (local UI ops)
|
|
502
|
+
query <action> Read editor-client state
|
|
503
|
+
actions / list List editor-client UI actions (LOCAL — what the
|
|
504
|
+
canvas UI can do)
|
|
505
|
+
help [domain] Show the workspace RPC catalog (CLOUD — what
|
|
506
|
+
agents can call). Different surface from actions.
|
|
507
|
+
help --search <q> Keyword search the workspace RPC catalog
|
|
508
|
+
record start [sessionId] / stop Record canvas interactions
|
|
509
|
+
|
|
510
|
+
Note: 'canvas actions' lists EDITOR-CLIENT UI actions (local). 'canvas
|
|
511
|
+
help' lists WORKSPACE RPC actions (cloud, agent-callable). They're
|
|
512
|
+
different surfaces — both names exist intentionally.`,
|
|
513
|
+
flags: [
|
|
514
|
+
{ name: '--note <noteId>', desc: 'Stamp noteId on the envelope' },
|
|
515
|
+
{ name: '--search <q>', desc: '(help) keyword search the catalog' },
|
|
516
|
+
{ name: '--compact', desc: '(help) condensed markdown output' },
|
|
517
|
+
{ name: '--json', desc: 'Output raw JSON' },
|
|
518
|
+
],
|
|
519
|
+
examples: [
|
|
520
|
+
{ cmd: 'beehaven canvas open note-abc123' },
|
|
521
|
+
{ cmd: 'beehaven canvas actions', note: 'editor UI actions (local)' },
|
|
522
|
+
{ cmd: 'beehaven canvas help', note: 'workspace RPC catalog (cloud)' },
|
|
523
|
+
{ cmd: 'beehaven canvas help --search "image"', note: 'find image-related RPCs' },
|
|
524
|
+
{ cmd: 'beehaven canvas invoke insert-block \'{"type":"text","text":"hi"}\'' },
|
|
525
|
+
],
|
|
526
|
+
related: ['conversations', 'call', 'actions'],
|
|
527
|
+
},
|
|
528
|
+
conversations: {
|
|
529
|
+
synopsis: 'beehaven conversations [list | resume | export <sessionId>]',
|
|
530
|
+
description: `List, resume, or export Clearly FAB conversations.
|
|
531
|
+
|
|
532
|
+
Wraps the workspace's conversation-list / conversation-export RPCs.
|
|
533
|
+
Pairs with the FAB conversation switcher (#51): the GUI picker and
|
|
534
|
+
the CLI list show the same sessions.`,
|
|
535
|
+
flags: [
|
|
536
|
+
{ name: '--limit <N>', desc: 'Max rows (default 20, max 100)' },
|
|
537
|
+
{ name: '--composition <id>', desc: 'Filter to one canvas' },
|
|
538
|
+
{ name: '--out <path>', desc: 'Export destination (export only)' },
|
|
539
|
+
{ name: '--stdout', desc: 'Write export to stdout (export only)' },
|
|
540
|
+
{ name: '--json', desc: 'Raw JSON output' },
|
|
541
|
+
],
|
|
542
|
+
examples: [
|
|
543
|
+
{ cmd: 'beehaven conversations', note: 'list 20 most recent' },
|
|
544
|
+
{ cmd: 'beehaven conversations --composition abc123' },
|
|
545
|
+
{ cmd: 'beehaven conversations resume', note: 'print top sessionId for shell pipelines' },
|
|
546
|
+
{ cmd: 'beehaven conversations export composition:abc --out thread.md' },
|
|
547
|
+
{ cmd: 'beehaven conversations export $(beehaven conversations resume) --stdout' },
|
|
548
|
+
],
|
|
549
|
+
related: ['canvas', 'actions'],
|
|
550
|
+
},
|
|
551
|
+
composition: {
|
|
552
|
+
synopsis: 'beehaven composition <bind|unbind|list> [args]',
|
|
553
|
+
description: `Bind a Clearly composition (canvas board) to a local repo, so a
|
|
554
|
+
daemon-spawned coding agent runs in the real codebase — and shares a
|
|
555
|
+
Claude Code project 1:1 with that repo (its cwd → ~/.claude/projects/<encoded-cwd>).
|
|
556
|
+
|
|
557
|
+
Subcommands:
|
|
558
|
+
bind <compositionId> <repoPath> Bind a board to a local repo
|
|
559
|
+
unbind <compositionId> Remove the binding (back to scratch dir)
|
|
560
|
+
list Show all board→repo bindings
|
|
561
|
+
|
|
562
|
+
The binding lives in ~/.clearly/composition-repos.json and is read fresh
|
|
563
|
+
by the daemon on the next Claude-model run for that board — no daemon
|
|
564
|
+
restart needed. A stale binding (repo moved/deleted) falls back to the
|
|
565
|
+
per-composition scratch dir ~/.clearly/compositions/<id>/.
|
|
566
|
+
|
|
567
|
+
Alias: comp`,
|
|
568
|
+
flags: [{ name: '--json', desc: 'Machine-readable output' }],
|
|
569
|
+
examples: [
|
|
570
|
+
{
|
|
571
|
+
cmd: 'beehaven composition bind 70f779d1-… ~/projects/motion_studio',
|
|
572
|
+
note: 'board → repo',
|
|
573
|
+
},
|
|
574
|
+
{ cmd: 'beehaven composition list' },
|
|
575
|
+
{ cmd: 'beehaven composition unbind 70f779d1-…' },
|
|
576
|
+
],
|
|
577
|
+
related: ['conversations', 'canvas', 'agent'],
|
|
578
|
+
},
|
|
579
|
+
disconnect: {
|
|
580
|
+
synopsis: 'beehaven disconnect',
|
|
581
|
+
description: `Clear the active target. Subsequent commands route to home.
|
|
582
|
+
Same effect as \`beehaven cd home\`.`,
|
|
583
|
+
examples: [{ cmd: 'beehaven disconnect' }],
|
|
584
|
+
related: ['cd', 'pwd'],
|
|
585
|
+
},
|
|
586
|
+
actions: {
|
|
587
|
+
synopsis: 'beehaven actions [--category <cat>] [--search <substr>] [--format <fmt>] [--json]',
|
|
588
|
+
description: `List callable RPCs on the current target.
|
|
589
|
+
|
|
590
|
+
On stale routing (you're on a target that doesn't expose list-actions),
|
|
591
|
+
transparently retries against home. See the dim "retrying against home"
|
|
592
|
+
line in stderr.`,
|
|
593
|
+
flags: [
|
|
594
|
+
{
|
|
595
|
+
name: '--category <cat>',
|
|
596
|
+
desc: 'Filter by action category (e.g. notes, projects, shopify)',
|
|
597
|
+
},
|
|
598
|
+
{ name: '--search <substr>', desc: 'Substring match on action name or description' },
|
|
599
|
+
{ name: '--format <fmt>', desc: 'summary (default), full, or tool-use (LLM-friendly JSON)' },
|
|
600
|
+
{ name: '--json', desc: 'Raw JSON output; skips breadcrumb + formatting' },
|
|
601
|
+
{ name: '--building <type>:<id>', desc: 'Explicit target (overrides active session)' },
|
|
602
|
+
],
|
|
603
|
+
examples: [
|
|
604
|
+
{ cmd: 'beehaven actions' },
|
|
605
|
+
{ cmd: 'beehaven actions --category shopify' },
|
|
606
|
+
{ cmd: 'beehaven actions --format tool-use', note: 'raw JSON with Zod-like schemas' },
|
|
607
|
+
],
|
|
608
|
+
related: ['call', 'pwd', 'workspace'],
|
|
609
|
+
},
|
|
610
|
+
call: {
|
|
611
|
+
synopsis: 'beehaven call <action> [json-input] [--building <type>:<id>] [--json]',
|
|
612
|
+
description: `Invoke an RPC on the current target. Input is a JSON string.
|
|
613
|
+
Schema comes from the action's manifest — use \`beehaven actions\` first
|
|
614
|
+
to see what's available, or \`beehaven explain <action>\` for the exact
|
|
615
|
+
input shape + examples.
|
|
616
|
+
|
|
617
|
+
Emits a routing breadcrumb "→ <target> <action>" to stderr on success/failure.`,
|
|
618
|
+
flags: [
|
|
619
|
+
{ name: '--building <type>:<id>', desc: 'Explicit target (e.g. shopifyStore:clearly-demo)' },
|
|
620
|
+
{ name: '--json', desc: 'Suppress breadcrumb + hint blocks; raw stdout only' },
|
|
621
|
+
{ name: '--timeout <ms>', desc: 'Override the 30s default' },
|
|
622
|
+
],
|
|
623
|
+
examples: [
|
|
624
|
+
{ cmd: 'beehaven call note-create \'{"title":"Hello"}\'' },
|
|
625
|
+
{ cmd: "beehaven call project-list '{}' --building home" },
|
|
626
|
+
{
|
|
627
|
+
cmd: 'beehaven call admin-agent-chat \'{"conversationId":"c1","message":"top sellers?","scope":"read"}\'',
|
|
628
|
+
note: 'Shopify admin agent chat',
|
|
629
|
+
},
|
|
630
|
+
],
|
|
631
|
+
related: ['actions', 'explain', 'pwd', 'workspace'],
|
|
632
|
+
},
|
|
633
|
+
doc: {
|
|
634
|
+
synopsis: 'beehaven doc add <file> [--project <id>] [--title <t>] [--json]',
|
|
635
|
+
description: `Add a local file to the workspace as a searchable DOCUMENT.
|
|
636
|
+
Reads the file, mints a note (note-create) + seeds its body
|
|
637
|
+
(note-content-seed) — the content lands in the workspace SQLite
|
|
638
|
+
note-content table + FTS5 index, so \`search-notes\` and the cloud agent
|
|
639
|
+
can retrieve it.
|
|
640
|
+
|
|
641
|
+
Markdown/text is stored verbatim; code files (.ts/.py/.go/…) are wrapped in
|
|
642
|
+
a fenced block (with the language) so they render and stay full-text
|
|
643
|
+
searchable. Title defaults to the markdown H1 or the filename. The
|
|
644
|
+
single-document guideline is ~1MB — for whole folders or large files,
|
|
645
|
+
prefer the doc-indexer (chunked, agent memory) or \`teleport\` (raw R2 blob).`,
|
|
646
|
+
flags: [
|
|
647
|
+
{ name: '--project <id>', desc: 'Attach the document to a project' },
|
|
648
|
+
{ name: '--title <t>', desc: 'Override the inferred title' },
|
|
649
|
+
{ name: '--json', desc: 'Machine-readable output (noteId, title, bytes)' },
|
|
650
|
+
],
|
|
651
|
+
examples: [
|
|
652
|
+
{ cmd: 'beehaven doc add ./seo_perf/PLAN.md --project 9834a399-...' },
|
|
653
|
+
{
|
|
654
|
+
cmd: 'beehaven doc add ./lib/pricing/tiers.ts --project 9834a399-...',
|
|
655
|
+
note: 'code → fenced + FTS-indexed',
|
|
656
|
+
},
|
|
657
|
+
],
|
|
658
|
+
related: ['teleport', 'search', 'call', 'recall'],
|
|
659
|
+
},
|
|
660
|
+
explain: {
|
|
661
|
+
synopsis: 'beehaven explain <action> [--json]',
|
|
662
|
+
description: `Show input schema + example invocations for one action.
|
|
663
|
+
Use this BEFORE \`beehaven call\` when you're not sure what JSON payload
|
|
664
|
+
the action expects.
|
|
665
|
+
|
|
666
|
+
Falls back through: \`describe-action\` (home) → \`list-actions --format=full\`
|
|
667
|
+
→ raw manifest at /.workspace.json. At least one of these works on every
|
|
668
|
+
DO with a manifest.`,
|
|
669
|
+
flags: [
|
|
670
|
+
{ name: '--json', desc: 'Print the raw manifest object' },
|
|
671
|
+
{ name: '--building <type>:<id>', desc: 'Explicit target' },
|
|
672
|
+
],
|
|
673
|
+
examples: [
|
|
674
|
+
{ cmd: 'beehaven explain note-create' },
|
|
675
|
+
{ cmd: 'beehaven explain shop:create-draft-order' },
|
|
676
|
+
{
|
|
677
|
+
cmd: 'beehaven explain project-create --json',
|
|
678
|
+
note: 'pipe to jq / consume programmatically',
|
|
679
|
+
},
|
|
680
|
+
],
|
|
681
|
+
related: ['actions', 'call'],
|
|
682
|
+
},
|
|
683
|
+
/**
|
|
684
|
+
* ⚠⚠ THE SHELL VERBS ADDRESS TWO FILESYSTEMS, AND THE DEFAULT ONE IS `~`.
|
|
685
|
+
*
|
|
686
|
+
* Every page below used to document the RAW VFS only (`/folders/<collection>/<uuid>.json`),
|
|
687
|
+
* which is the namespace these verbs answered from BEFORE they were repointed at the notes
|
|
688
|
+
* shell. Measured 2026-09-05: 4 of 4 shell pages had examples that failed on a default daemon
|
|
689
|
+
* with "RPC 'shell:exec' requires developer scope" — 0 of them mentioned `~` even once.
|
|
690
|
+
*
|
|
691
|
+
* The runtime error handler already knew better than the help did: when a raw-VFS example
|
|
692
|
+
* fails it prints "beehaven ls ~ # the notes workspace (no extra scope)". A help page that
|
|
693
|
+
* contradicts the CLI's own error message is worse than no page.
|
|
694
|
+
*
|
|
695
|
+
* The rule for anything added here: `~` FIRST, because it is what the top-level help leads
|
|
696
|
+
* with, what the product uses, and what needs no extra scope. The raw VFS is documented as
|
|
697
|
+
* the second namespace, with its scope requirement stated rather than discovered.
|
|
698
|
+
*/
|
|
699
|
+
ls: {
|
|
700
|
+
synopsis: 'beehaven ls [path]',
|
|
701
|
+
description: `List a directory. Two namespaces answer, and the breadcrumb on
|
|
702
|
+
stderr says which — a "(notes)" suffix means the notes shell replied.
|
|
703
|
+
|
|
704
|
+
~ THE WORKSPACE (default, no extra scope)
|
|
705
|
+
Folders are PROJECTS, documents are .md files named "<KEY> <Title>.md".
|
|
706
|
+
beehaven ls ~ every project + unfiled document
|
|
707
|
+
beehaven ls '~/Q1' inside one project
|
|
708
|
+
⚠ Quote any path with a space — a document filename usually has one.
|
|
709
|
+
⚠ Folders NEST (since 2026-09-05) — \`ls '~/A/B'\` is a real path. Before
|
|
710
|
+
that, mkdir flattened, so older notes describing a flat workspace are stale.
|
|
711
|
+
|
|
712
|
+
/ THE RAW VFS (needs developer scope)
|
|
713
|
+
Data rows as files — /folders/<collection>/, /apps/, /proc/, /etc/, /var/,
|
|
714
|
+
/.workspace.json. Every path here goes through shell:exec, so a default
|
|
715
|
+
daemon refuses it with "requires developer scope"; start it as
|
|
716
|
+
HIVE_DEV_MODE=1 beehaven start --headless to reach it.`,
|
|
717
|
+
examples: [
|
|
718
|
+
{ cmd: 'beehaven ls ~', note: 'projects + unfiled documents' },
|
|
719
|
+
{ cmd: "beehaven ls '~/Q1'", note: 'inside one project — quote the path' },
|
|
720
|
+
{ cmd: 'beehaven ls /', note: 'the raw VFS — developer scope only' },
|
|
721
|
+
],
|
|
722
|
+
related: ['cat', 'tree', 'grep', 'find', 'workspace'],
|
|
723
|
+
},
|
|
724
|
+
cat: {
|
|
725
|
+
synopsis: 'beehaven cat <path>',
|
|
726
|
+
description: `Read a document. Works on anything ls shows.
|
|
727
|
+
|
|
728
|
+
Three spellings resolve, and they do NOT behave alike:
|
|
729
|
+
|
|
730
|
+
beehaven cat '~/CH-1.md' the KEY — from ANYWHERE
|
|
731
|
+
beehaven cat '~/CRUD Hunt/CH-1 CRUD Hunt Report.md' the full name ls prints
|
|
732
|
+
beehaven cat '~/CRUD Hunt/CRUD Hunt Report.md' the title alone
|
|
733
|
+
|
|
734
|
+
⚠⚠ THE KEY IGNORES THE FOLDER; THE OTHER TWO DO NOT. A key names exactly one
|
|
735
|
+
document in the whole workspace, so \`cat '~/CH-1.md'\` works even though CH-1
|
|
736
|
+
is filed under "CRUD Hunt". Give the NAME or TITLE with the wrong folder and
|
|
737
|
+
you get "No such file or directory" for a document that is really there —
|
|
738
|
+
which reads as missing rather than as mis-addressed. When in doubt use the key.
|
|
739
|
+
|
|
740
|
+
⚠ Two documents may share a title, and then the title form is refused as
|
|
741
|
+
ambiguous. A key never is.
|
|
742
|
+
|
|
743
|
+
A raw-VFS path (/folders/…, /.workspace.json) also works but needs developer
|
|
744
|
+
scope — see \`beehaven help ls\`.`,
|
|
745
|
+
examples: [
|
|
746
|
+
{ cmd: "beehaven cat '~/CH-1.md'", note: 'by key — resolves from anywhere' },
|
|
747
|
+
{ cmd: "beehaven cat '~/CRUD Hunt/CH-1 CRUD Hunt Report.md'", note: 'the name ls prints' },
|
|
748
|
+
{ cmd: "beehaven cat '~/Q1/Board.board.json'", note: 'a board, with its cards' },
|
|
749
|
+
],
|
|
750
|
+
related: ['ls', 'tree', 'grep', 'head', 'search'],
|
|
751
|
+
},
|
|
752
|
+
grep: {
|
|
753
|
+
synopsis: 'beehaven grep [flags] <pattern> <path>',
|
|
754
|
+
description: `Search document BODIES for a pattern. A directory target
|
|
755
|
+
auto-recurses (no -r needed).
|
|
756
|
+
|
|
757
|
+
Takes the usual flags: -i (ignore case), -l (names only), -r, and they
|
|
758
|
+
combine — \`grep -ril pricing ~\` is the everyday call.
|
|
759
|
+
|
|
760
|
+
⚠ grep MATCHES SUBSTRINGS; \`search\` RANKS. Reach for grep when you know the
|
|
761
|
+
literal string (an identifier, a URL, an error message) and for \`search\` when
|
|
762
|
+
you know the idea — it is BM25 over the same bodies and it stems, so it finds
|
|
763
|
+
"crediting" from "credits" where grep cannot.
|
|
764
|
+
|
|
765
|
+
On the raw VFS (/compositions/, developer scope) it pushes the search into each
|
|
766
|
+
composition's blocks, decompressing the canvas blob, so it finds text \`sql\`
|
|
767
|
+
cannot — that column is gzip-compressed.`,
|
|
768
|
+
examples: [
|
|
769
|
+
{ cmd: 'beehaven grep -ril pricing ~', note: 'which documents mention it' },
|
|
770
|
+
{ cmd: "beehaven grep TODO '~/Q1'", note: 'scoped to one project' },
|
|
771
|
+
{ cmd: 'beehaven grep checkout /compositions/', note: 'raw VFS — developer scope only' },
|
|
772
|
+
],
|
|
773
|
+
related: ['search', 'ls', 'cat', 'find', 'sql'],
|
|
774
|
+
},
|
|
775
|
+
tree: {
|
|
776
|
+
synopsis: 'beehaven tree [path]',
|
|
777
|
+
description: `Recursive view under a path. On \`~\` this is the fastest way to
|
|
778
|
+
see the whole workspace at once: every project, and what is filed in each.
|
|
779
|
+
|
|
780
|
+
⚠ It prints the WHOLE tree — on a workspace with hundreds of documents, pipe it
|
|
781
|
+
(\`| head -40\`) or point it at one project.
|
|
782
|
+
|
|
783
|
+
A raw-VFS path needs developer scope — see \`beehaven help ls\`.`,
|
|
784
|
+
examples: [
|
|
785
|
+
{ cmd: 'beehaven tree ~', note: 'the whole workspace' },
|
|
786
|
+
{ cmd: "beehaven tree '~/Q1'", note: 'one project' },
|
|
787
|
+
{ cmd: 'beehaven tree /', note: 'raw VFS — developer scope only' },
|
|
788
|
+
],
|
|
789
|
+
related: ['ls', 'cat', 'find'],
|
|
790
|
+
},
|
|
791
|
+
write: {
|
|
792
|
+
synopsis: 'beehaven write <path> <content>',
|
|
793
|
+
description: `Create or overwrite a document. Content is ONE argument — quote it.
|
|
794
|
+
|
|
795
|
+
⚠⚠ THE BASENAME YOU TYPE IS THE NAME (fixed 2026-09-05, CBH2-8).
|
|
796
|
+
beehaven write '~/HelpProbe/probe-write.md' '# Written Title'
|
|
797
|
+
→ wrote ~/HelpProbe/HEL-1 probe-write.md
|
|
798
|
+
It used to DISCARD the basename and name the note from line one of the
|
|
799
|
+
content, so \`cat\` of the path you had just written answered "no such file".
|
|
800
|
+
The heading in the body is now just a heading.
|
|
801
|
+
|
|
802
|
+
⚠ THE FILENAME STILL LEADS WITH A KEY (\`HEL-1\`), which is minted at create
|
|
803
|
+
time and cannot be known in advance — so the path it echoes is still the one
|
|
804
|
+
to trust. Both \`~/HelpProbe/probe-write.md\` and \`~/HEL-1.md\` resolve.
|
|
805
|
+
|
|
806
|
+
⚠ TWO PATHS NAME NOTHING, and for those line one is still the title: a bare
|
|
807
|
+
key (\`~/CLR-42.md\` — that is an address, not a name) and an empty basename.
|
|
808
|
+
|
|
809
|
+
⚠⚠ FOR A MULTI-LINE BODY USE $'...', NOT '...\\n...'. A plain single-quoted
|
|
810
|
+
string passes the backslash-n through literally, so the body arrives as one
|
|
811
|
+
line containing "-n-n". No error, just a document that reads as garbage.
|
|
812
|
+
$'…' is bash/zsh ANSI-C quoting and interprets the \\n.
|
|
813
|
+
|
|
814
|
+
⚠ It OVERWRITES the whole body. To change one passage use \`edit\`, which
|
|
815
|
+
leaves the rest alone and cannot lose what you did not retype.
|
|
816
|
+
|
|
817
|
+
On a raw-VFS /compositions block file (developer scope) the JSON is spliced
|
|
818
|
+
into the canvas blob, so the edit shows on the user's canvas. Single quotes
|
|
819
|
+
inside the content are not supported there — use \`call composition-patch\`.`,
|
|
820
|
+
examples: [
|
|
821
|
+
{
|
|
822
|
+
cmd: `beehaven write '~/Q1/notes.md' $'# Kickoff notes\\n\\nfirst line'`,
|
|
823
|
+
note: 'names it "notes" — the basename wins; the heading is just a heading',
|
|
824
|
+
},
|
|
825
|
+
{
|
|
826
|
+
cmd: `beehaven write /compositions/<id>/blocks/<bid>.json '{"id":"<bid>","type":"text","data":{"type":"text","text":"hi"}}'`,
|
|
827
|
+
note: 'raw VFS — developer scope only',
|
|
828
|
+
},
|
|
829
|
+
],
|
|
830
|
+
related: ['cat', 'edit', 'rm', 'ls'],
|
|
831
|
+
},
|
|
832
|
+
edit: {
|
|
833
|
+
synopsis: 'beehaven edit <path> <old> <new>',
|
|
834
|
+
description: `Find/replace inside a document: read → replace every <old> with
|
|
835
|
+
<new> → write back. Reports "edited <path>" naming what it touched.
|
|
836
|
+
|
|
837
|
+
⚠ PREFER THIS OVER \`write\` FOR AN EXISTING DOCUMENT. \`write\` replaces the
|
|
838
|
+
whole body, so anything you do not retype is gone with no error; \`edit\`
|
|
839
|
+
changes the passage and leaves the rest untouched.
|
|
840
|
+
|
|
841
|
+
⚠ It replaces EVERY occurrence, not the first. If <old> appears more than once
|
|
842
|
+
and you meant one of them, make the string long enough to be unique.
|
|
843
|
+
|
|
844
|
+
⚠ A <old> that is not in the body is REFUSED ("find text not present"), never
|
|
845
|
+
silently applied — so a failed edit costs you nothing. Re-read with \`cat\`
|
|
846
|
+
and retry with the passage as it now reads.
|
|
847
|
+
|
|
848
|
+
On a raw-VFS /compositions block (developer scope) this updates the canvas.`,
|
|
849
|
+
examples: [
|
|
850
|
+
{ cmd: `beehaven edit '~/HEL-3.md' 'first line' 'second line'`, note: 'by key' },
|
|
851
|
+
{ cmd: `beehaven edit '~/Q1/Kickoff notes.md' 'TODO' 'DONE'` },
|
|
852
|
+
],
|
|
853
|
+
related: ['cat', 'write', 'grep', 'rm'],
|
|
854
|
+
},
|
|
855
|
+
rm: {
|
|
856
|
+
synopsis: 'beehaven rm <path>',
|
|
857
|
+
description: `Remove a document from the workspace listing.
|
|
858
|
+
|
|
859
|
+
⚠⚠ IT ARCHIVES, IT DOES NOT DESTROY — and the KEY KEEPS RESOLVING. The row is
|
|
860
|
+
flagged archived and drops out of \`ls\`, but \`cat '~/HEL-1.md'\` still
|
|
861
|
+
returns the body afterwards. So this is "put it in the trash", not "shred it".
|
|
862
|
+
Treat a successful rm as reversible, and never as proof something is gone.
|
|
863
|
+
|
|
864
|
+
⚠⚠ THE UNDO IS \`document-archive\`, NOT \`document-restore\`. This page said
|
|
865
|
+
\`document-restore\` and that is a DIFFERENT verb: it restores an earlier
|
|
866
|
+
VERSION of a document's body and answers \`versionId is required\`, so
|
|
867
|
+
following the old advice got you an error about a field you were never told
|
|
868
|
+
about, on a document that was never rolled back. Un-archive with:
|
|
869
|
+
|
|
870
|
+
call document-archive '{"id":"HEL-1","archived":false}'
|
|
871
|
+
|
|
872
|
+
⚠ A FOLDER'S UNDO IS A DIFFERENT SHAPE AGAIN. \`rm -r <folder>\` routes to
|
|
873
|
+
\`project-delete\`, and a project is un-archived through its updates bag with
|
|
874
|
+
\`is_archived\` — the underscored column name, not \`archived\`:
|
|
875
|
+
|
|
876
|
+
call project-update '{"id":"<folder-id>","updates":{"is_archived":false}}'
|
|
877
|
+
|
|
878
|
+
You do not have to remember either: rm PRINTS the exact call for what it just
|
|
879
|
+
archived, with the id already filled in. Read the line it prints — it also
|
|
880
|
+
reports what it did ("moved to Trash …"), so older notes telling you to
|
|
881
|
+
confirm with \`ls\` describe a CLI that no longer exists.
|
|
882
|
+
|
|
883
|
+
On a raw-VFS /compositions block (developer scope) it removes the block from
|
|
884
|
+
the canvas. The sibling mutation verbs \`mv\`, \`cp\` and \`mkdir\` pass through
|
|
885
|
+
to the same shell.`,
|
|
886
|
+
examples: [
|
|
887
|
+
{ cmd: `beehaven rm '~/HelpProbe/HEL-1 Written Title.md'`, note: 'prints the undo call' },
|
|
888
|
+
{ cmd: `beehaven restore HEL-1`, note: 'undo — the verb form' },
|
|
889
|
+
{ cmd: `beehaven call document-archive '{"id":"HEL-1","archived":false}'`, note: 'undo — the raw call' },
|
|
890
|
+
],
|
|
891
|
+
related: ['ls', 'write', 'edit', 'mv', 'trash', 'restore'],
|
|
892
|
+
},
|
|
893
|
+
/**
|
|
894
|
+
* ⚠⚠ THESE TWO EXIST BECAUSE `rm` HAD NO WAY BACK FROM THE EVERYDAY SURFACE (CBH2-34).
|
|
895
|
+
*
|
|
896
|
+
* `rm` archives rather than destroys and its page has said so for a while — but the only undo it
|
|
897
|
+
* could offer was a raw `beehaven call document-archive '{"archived":false}'`, and the ticket's
|
|
898
|
+
* own reproduction was `beehaven help | grep -iE 'restore|trash|undelete|unarchive'` returning
|
|
899
|
+
* NOTHING. A reversible delete whose reversal is undiscoverable is, for anyone who does not read
|
|
900
|
+
* the worker, an irreversible one.
|
|
901
|
+
*
|
|
902
|
+
* ⚠ Adding the pages is what puts the verbs in the top-level grid — it is `Object.keys(PAGES)`.
|
|
903
|
+
* So a page here is not documentation ABOUT the verb; it is how the verb becomes findable.
|
|
904
|
+
*/
|
|
905
|
+
trash: {
|
|
906
|
+
synopsis: 'beehaven trash',
|
|
907
|
+
description: `Documents \`rm\` put away. It archives rather than destroys, so this is the
|
|
908
|
+
list of things you can still get back.
|
|
909
|
+
|
|
910
|
+
⚠ THE COUNT IS A PAGE, NOT A TOTAL. It says so when the page is full; raise it
|
|
911
|
+
with \`--limit\` (max 500). A list that stops at its own default and looks
|
|
912
|
+
complete is the failure this workspace keeps finding.
|
|
913
|
+
|
|
914
|
+
Nothing is destroyed by archiving and nothing here expires. Put one back with
|
|
915
|
+
\`beehaven restore <key>\`.`,
|
|
916
|
+
examples: [
|
|
917
|
+
{ cmd: 'beehaven trash' },
|
|
918
|
+
{ cmd: 'beehaven trash --limit 200', note: 'more than the default page' },
|
|
919
|
+
],
|
|
920
|
+
related: ['rm', 'restore', 'ls'],
|
|
921
|
+
},
|
|
922
|
+
restore: {
|
|
923
|
+
synopsis: 'beehaven restore <key|title|id>',
|
|
924
|
+
description: `Un-archive a document and return it to \`ls\`.
|
|
925
|
+
|
|
926
|
+
Takes the same references everything else does — the KEY is the one to use
|
|
927
|
+
(\`beehaven trash\` prints it), because two documents may share a title.
|
|
928
|
+
|
|
929
|
+
⚠ IT REPORTS A NO-OP AS A NO-OP. Restoring something that was never archived
|
|
930
|
+
answers "was not archived — nothing to do" rather than "restored". Claiming
|
|
931
|
+
work that did not happen is the defect class this whole sprint was about.
|
|
932
|
+
|
|
933
|
+
⚠ THIS IS NOT \`document-restore\`. That verb rolls a document's BODY back to
|
|
934
|
+
an earlier VERSION and needs a \`versionId\`. This one only flips the archived
|
|
935
|
+
flag, and leaves the body exactly as it was.
|
|
936
|
+
|
|
937
|
+
⚠ A FOLDER IS A DIFFERENT SHAPE. \`rm -r <folder>\` routes to \`project-delete\`;
|
|
938
|
+
un-archive it through its updates bag with the underscored column name:
|
|
939
|
+
|
|
940
|
+
call project-update '{"id":"<folder-id>","updates":{"is_archived":false}}'`,
|
|
941
|
+
examples: [
|
|
942
|
+
{ cmd: 'beehaven restore HEL-1' },
|
|
943
|
+
{ cmd: 'beehaven trash', note: 'see the keys first' },
|
|
944
|
+
],
|
|
945
|
+
related: ['trash', 'rm', 'ls'],
|
|
946
|
+
},
|
|
947
|
+
/**
|
|
948
|
+
* ⚠⚠ THE ORGANISE VERBS — `mkdir`, `mv`, `cp`. All three shipped in the top-level help under a
|
|
949
|
+
* heading called "Organise", were named BY `help rm`, and had no page of their own: the CLI told
|
|
950
|
+
* you they existed, told you to run `beehaven help <command>` before anything unfamiliar, and
|
|
951
|
+
* then had nothing to show.
|
|
952
|
+
*
|
|
953
|
+
* ⚠ They are also the three that most need a page, because ALL THREE PRINT NOTHING ON SUCCESS —
|
|
954
|
+
* so their failure mode and their success mode are byte-identical on screen. Every page below
|
|
955
|
+
* says what silence means and how to confirm.
|
|
956
|
+
*/
|
|
957
|
+
mkdir: {
|
|
958
|
+
synopsis: 'beehaven mkdir [-p] <path>',
|
|
959
|
+
description: `Create a project. A folder in \`~\` IS a project — there is no
|
|
960
|
+
separate "make a project" step.
|
|
961
|
+
|
|
962
|
+
⚠⚠ NESTING IS REAL NOW (fixed 2026-09-05, CBH2-7). \`mkdir '~/A/B'\` creates
|
|
963
|
+
B INSIDE A. It used to FLATTEN — creating a root project called "B" beside A
|
|
964
|
+
— and then echo back \`~/A/B\`, a path that would never resolve.
|
|
965
|
+
|
|
966
|
+
⚠ WITHOUT -p A MISSING INTERMEDIATE IS REFUSED, as in any shell. \`mkdir
|
|
967
|
+
'~/A/B/C'\` when A/B does not exist answers "No such file or directory" and
|
|
968
|
+
creates nothing; \`mkdir -p '~/A/B/C'\` creates the whole chain. -p used to
|
|
969
|
+
be accepted and ignored.
|
|
970
|
+
|
|
971
|
+
⚠ An existing folder is still SUCCESS, not a collision (find-or-create), so
|
|
972
|
+
re-running is safe. A bare name (\`mkdir '~/Prepress'\`) still matches a
|
|
973
|
+
folder of that name ANYWHERE in the tree rather than minting a second one.
|
|
974
|
+
|
|
975
|
+
⚠ It prints the path it actually created — read that, because a name that
|
|
976
|
+
collides with a sibling is suffixed with a short id.
|
|
977
|
+
|
|
978
|
+
A new project is not empty: it arrives with a \`clearly.md\` and its own
|
|
979
|
+
\`<Name> board.board.json\`.`,
|
|
980
|
+
examples: [
|
|
981
|
+
{ cmd: "beehaven mkdir '~/Q2 Planning'", note: 'creates the project' },
|
|
982
|
+
{ cmd: "beehaven mkdir -p '~/Q2 Planning/Research/Interviews'", note: 'creates the whole chain' },
|
|
983
|
+
{ cmd: "beehaven ls '~/Q2 Planning'", note: 'confirm the nesting landed' },
|
|
984
|
+
],
|
|
985
|
+
related: ['ls', 'mv', 'cp', 'tree'],
|
|
986
|
+
},
|
|
987
|
+
mv: {
|
|
988
|
+
synopsis: 'beehaven mv <src> <dest>',
|
|
989
|
+
description: `Move a document into a project, or rename it. Two jobs, told
|
|
990
|
+
apart by whether <dest> is a folder or a filename.
|
|
991
|
+
|
|
992
|
+
beehaven mv '~/PLA-3584.md' '~/HelpProbe'
|
|
993
|
+
→ files it under HelpProbe
|
|
994
|
+
beehaven mv '~/HelpProbe/PLA-3584 Old.md' '~/HelpProbe/PLA-3584 New.md'
|
|
995
|
+
→ renames it to "New"
|
|
996
|
+
|
|
997
|
+
⚠ THE KEY IS NOT PART OF THE NAME YOU ARE SETTING. Renaming to
|
|
998
|
+
"PLA-3584 New.md" sets the title to "New", not "PLA-3584 New" — the key prefix
|
|
999
|
+
is stripped. Leave it on: a bare key as the destination is refused outright,
|
|
1000
|
+
because a caller never chooses a key.
|
|
1001
|
+
|
|
1002
|
+
⚠ A MOVE DOES NOT RE-KEY. The prefix records where a document was BORN, not
|
|
1003
|
+
where it lives now, so a document moved into another project keeps its
|
|
1004
|
+
original prefix. That is deliberate — a key that came back pointing at
|
|
1005
|
+
different work would turn every past mention of it into a quiet lie.
|
|
1006
|
+
|
|
1007
|
+
It reports the move ("id … · movedTo HP2"). ⚠ It used to print nothing, so
|
|
1008
|
+
older notes describing a silent \`mv\` are stale.`,
|
|
1009
|
+
examples: [
|
|
1010
|
+
{ cmd: "beehaven mv '~/PLA-3584.md' '~/HelpProbe'", note: 'file it into a project' },
|
|
1011
|
+
{
|
|
1012
|
+
cmd: "beehaven mv '~/HelpProbe/PLA-3584 Old.md' '~/HelpProbe/PLA-3584 New.md'",
|
|
1013
|
+
note: 'rename — the title becomes "New"',
|
|
1014
|
+
},
|
|
1015
|
+
{ cmd: "beehaven ls '~/HelpProbe'", note: 'mv is silent — this is how you confirm' },
|
|
1016
|
+
],
|
|
1017
|
+
related: ['ls', 'cp', 'mkdir', 'rm'],
|
|
1018
|
+
},
|
|
1019
|
+
cp: {
|
|
1020
|
+
synopsis: 'beehaven cp <src> <dest> · beehaven cp -r <folder> <dest>',
|
|
1021
|
+
description: `Copy a document into a project.
|
|
1022
|
+
|
|
1023
|
+
⚠⚠ THE COPY GETS A NEW KEY, DERIVED FROM WHERE IT LANDS. Measured: copying
|
|
1024
|
+
"PLA-3790 HP2 Doc.md" into ~/Q1 reported
|
|
1025
|
+
\`key Q1-4 · copiedTo ~/Q1 · title HP2 Doc (copy)\` — a NEW key taking the
|
|
1026
|
+
destination's prefix, and "(copy)" appended to the title. So the copy is a
|
|
1027
|
+
genuinely separate document with its own address; anything that referenced the
|
|
1028
|
+
old key still means the ORIGINAL. Read the reported key rather than guessing it.
|
|
1029
|
+
|
|
1030
|
+
⚠⚠ \`cp -r\` ON A FOLDER REPORTS A DESTINATION IT DID NOT CREATE — VERIFIED
|
|
1031
|
+
2026-09-05. \`cp -r '~/HP2' '~/HP2Copy'\` prints
|
|
1032
|
+
\`copiedFolder {"from":"~/HP2","to":"~/HP2Copy"}\` and then
|
|
1033
|
+
\`ls '~/HP2Copy'\` answers "No such file or directory", because the project it
|
|
1034
|
+
actually made is called **"HP2 (copy)"**. The copy is real; only the name in
|
|
1035
|
+
the report is wrong. **Do not trust the \`to\` field — \`ls ~\` and use the
|
|
1036
|
+
name you find.** To choose the name, use the RPC, which honours \`title\`:
|
|
1037
|
+
beehaven call project-copy '{"projectId":"<id>","title":"Q2 Planning"}'
|
|
1038
|
+
|
|
1039
|
+
Both forms report what they did. ⚠ They used to print nothing, so older notes
|
|
1040
|
+
describing a silent \`cp\` are stale.`,
|
|
1041
|
+
examples: [
|
|
1042
|
+
{
|
|
1043
|
+
cmd: "beehaven cp '~/HP2/PLA-3790 HP2 Doc.md' '~/Q1'",
|
|
1044
|
+
note: 'reports the NEW key it minted',
|
|
1045
|
+
},
|
|
1046
|
+
{ cmd: 'beehaven ls ~', note: "after cp -r — the report's name is not the real one" },
|
|
1047
|
+
{
|
|
1048
|
+
cmd: `beehaven call project-copy '{"projectId":"<id>","title":"Q2 Planning"}'`,
|
|
1049
|
+
note: 'copy a whole project with the title honoured',
|
|
1050
|
+
},
|
|
1051
|
+
],
|
|
1052
|
+
related: ['mv', 'ls', 'mkdir', 'call'],
|
|
1053
|
+
},
|
|
1054
|
+
/**
|
|
1055
|
+
* ⚠ THE THREE READ VERBS — `head`, `tail`, `wc`. Documented in the top-level help as
|
|
1056
|
+
* "beehaven head|tail|wc <path> The usual three" and undocumented anywhere deeper. They are
|
|
1057
|
+
* what an agent reaches for immediately after `ls` and `cat`, on exactly the documents too long
|
|
1058
|
+
* to `cat` whole.
|
|
1059
|
+
*/
|
|
1060
|
+
head: {
|
|
1061
|
+
synopsis: 'beehaven head [-n <lines>] <path>',
|
|
1062
|
+
description: `First lines of a document. Defaults to 10.
|
|
1063
|
+
|
|
1064
|
+
This is the cheap way to identify a long document without pulling the whole
|
|
1065
|
+
body through your context — and \`~\` documents lead with their heading, so
|
|
1066
|
+
\`head -n 3\` is usually enough to know what one is.
|
|
1067
|
+
|
|
1068
|
+
Addressing is the same as \`cat\`: the KEY resolves from anywhere, a name or
|
|
1069
|
+
title needs the right folder.`,
|
|
1070
|
+
examples: [
|
|
1071
|
+
{ cmd: "beehaven head -n 3 '~/CH-1.md'" },
|
|
1072
|
+
{ cmd: "beehaven head '~/CRUD Hunt/CH-1 CRUD Hunt Report.md'" },
|
|
1073
|
+
],
|
|
1074
|
+
related: ['tail', 'wc', 'cat', 'ls'],
|
|
1075
|
+
},
|
|
1076
|
+
tail: {
|
|
1077
|
+
synopsis: 'beehaven tail [-n <lines>] <path>',
|
|
1078
|
+
description: `Last lines of a document. Defaults to 10.
|
|
1079
|
+
|
|
1080
|
+
Useful on the documents that GROW — a running log, a report an agent keeps
|
|
1081
|
+
appending to with \`document-append\` — where the newest material is at the
|
|
1082
|
+
bottom and \`head\` shows you the oldest.
|
|
1083
|
+
|
|
1084
|
+
Addressing is the same as \`cat\`.`,
|
|
1085
|
+
examples: [
|
|
1086
|
+
{ cmd: "beehaven tail -n 2 '~/CH-1.md'" },
|
|
1087
|
+
{ cmd: "beehaven tail '~/Q1/Kickoff notes.md'" },
|
|
1088
|
+
],
|
|
1089
|
+
related: ['head', 'wc', 'cat'],
|
|
1090
|
+
},
|
|
1091
|
+
wc: {
|
|
1092
|
+
synopsis: 'beehaven wc <path>',
|
|
1093
|
+
description: `Lines, words and characters — the three, in that order.
|
|
1094
|
+
|
|
1095
|
+
$ beehaven wc '~/CH-1.md'
|
|
1096
|
+
6 18 101 /home/CH-1.md
|
|
1097
|
+
|
|
1098
|
+
Reach for it before reading something you are not sure you can afford, and to
|
|
1099
|
+
check an append landed. For a richer answer on a document — headings, reading
|
|
1100
|
+
time, what it contains — \`call document-stats\` is the workspace's own version.`,
|
|
1101
|
+
examples: [
|
|
1102
|
+
{ cmd: "beehaven wc '~/CH-1.md'" },
|
|
1103
|
+
{ cmd: `beehaven call document-stats '{"id":"CH-1"}'`, note: 'the richer version' },
|
|
1104
|
+
],
|
|
1105
|
+
related: ['head', 'tail', 'cat', 'call'],
|
|
1106
|
+
},
|
|
1107
|
+
jq: {
|
|
1108
|
+
synopsis: 'beehaven jq <filter> <path>',
|
|
1109
|
+
description: `Run a jq filter over a JSON file in the workspace. The workspace
|
|
1110
|
+
is full of them: \`<Board>.board.json\`, \`<name>.scene.json\`, and anything
|
|
1111
|
+
under the raw VFS.
|
|
1112
|
+
|
|
1113
|
+
⚠ It needs REAL JSON. Pointed at a markdown document it answers
|
|
1114
|
+
"jq: invalid JSON" — which is a type error, not a missing file.`,
|
|
1115
|
+
examples: [
|
|
1116
|
+
{ cmd: `beehaven jq '.title' '~/Q1/Board.board.json'` },
|
|
1117
|
+
{ cmd: `beehaven jq '.' '~/Q1/Board.board.json'`, note: 'pretty-print the whole thing' },
|
|
1118
|
+
],
|
|
1119
|
+
related: ['cat', 'sql', 'ls'],
|
|
1120
|
+
},
|
|
1121
|
+
/**
|
|
1122
|
+
* ⚠⚠ `find` IS NOT AN ALIAS OF `search`, THOUGH `help` CLAIMED IT WAS.
|
|
1123
|
+
*
|
|
1124
|
+
* The ALIASES table carried `find: 'search'`, so `beehaven help find` rendered the SEARCH page
|
|
1125
|
+
* while dispatch sent the word to the shell's POSIX find. `find HunterProbe` answered
|
|
1126
|
+
* "No such file or directory" — which reads as "that note does not exist", not "you used the
|
|
1127
|
+
* wrong verb". A silent false negative produced by the CLI's own documented alias.
|
|
1128
|
+
*
|
|
1129
|
+
* ⚠ THE ALIAS WAS REMOVED RATHER THAN HONOURED, DELIBERATELY. Making `find` mean `search` would
|
|
1130
|
+
* have deleted a working, useful capability: POSIX find matches on NAME and PATH
|
|
1131
|
+
* (`find ~ -name '*.board.json'` enumerates every board in the workspace), where `search` is
|
|
1132
|
+
* BM25 over CONTENT. They answer different questions, so one cannot be the other's alias — and
|
|
1133
|
+
* this CLI has a public installer, so silently changing what a working verb does has a real
|
|
1134
|
+
* cost. The bug was the documentation claiming a synonym; the fix is to document the difference
|
|
1135
|
+
* and signpost the other verb by name.
|
|
1136
|
+
*/
|
|
1137
|
+
find: {
|
|
1138
|
+
synopsis: 'beehaven find <path> [-name <glob>]',
|
|
1139
|
+
description: `POSIX find over the workspace — matches on NAME and PATH.
|
|
1140
|
+
|
|
1141
|
+
⚠⚠ THIS IS NOT \`search\`, AND ITS FAILURE LOOKS LIKE AN EMPTY WORKSPACE.
|
|
1142
|
+
\`beehaven find HunterProbe\` treats the word as a PATH and answers
|
|
1143
|
+
"find: /home/HunterProbe: No such file or directory" — which reads as "no such
|
|
1144
|
+
note". It is not: it is the wrong verb. To search CONTENT use \`search\`
|
|
1145
|
+
(ranked, BM25, stems) or \`grep\` (literal substring).
|
|
1146
|
+
|
|
1147
|
+
find → what is this thing CALLED / where does it live
|
|
1148
|
+
grep → which documents CONTAIN this exact string
|
|
1149
|
+
search → which documents are ABOUT this
|
|
1150
|
+
|
|
1151
|
+
⚠ The first argument is a path, so it always starts with \`~\` or a folder.`,
|
|
1152
|
+
examples: [
|
|
1153
|
+
{ cmd: "beehaven find '~/Q1'", note: 'everything under one project' },
|
|
1154
|
+
{ cmd: `beehaven find ~ -name '*.board.json'`, note: 'every board in the workspace' },
|
|
1155
|
+
{ cmd: 'beehaven search "revenue attribution"', note: 'searching CONTENT is a different verb' },
|
|
1156
|
+
],
|
|
1157
|
+
related: ['search', 'grep', 'ls', 'tree'],
|
|
1158
|
+
},
|
|
1159
|
+
// `claude` was a documented verb with no page — the exact gap this file's
|
|
1160
|
+
// test exists to catch, surfaced when `omni` tried to link to it.
|
|
1161
|
+
claude: {
|
|
1162
|
+
synopsis: 'beehaven claude "<task>" · beehaven claude login | status | logout',
|
|
1163
|
+
description: `ONE local Claude Code turn, on YOUR own subscription, in THIS process.
|
|
1164
|
+
|
|
1165
|
+
Runs the Claude Agent SDK's \`query()\` in the CLI itself, authenticated by the
|
|
1166
|
+
OAuth credential \`beehaven claude login\` writes (a \`claude setup-token\` browser
|
|
1167
|
+
flow). Nothing syncs a token to the cloud and nothing remote can drive it —
|
|
1168
|
+
cloud→daemon Claude orchestration is disabled for Anthropic credential-use
|
|
1169
|
+
compliance.
|
|
1170
|
+
|
|
1171
|
+
It is a one-shot: the session lives and dies with the command, carries no
|
|
1172
|
+
beehaven tools, and nothing else on the machine can see it. When you want the
|
|
1173
|
+
shared, daemon-hosted session with the beehaven surface mounted — the one the
|
|
1174
|
+
avatar's chat panel also talks to — use \`beehaven omni\`.
|
|
1175
|
+
|
|
1176
|
+
--composition runs the turn in a per-composition workspace
|
|
1177
|
+
(~/.clearly/compositions/<id>, with a seeded CLAUDE.md) so Claude opens
|
|
1178
|
+
knowing where it is.`,
|
|
1179
|
+
flags: [
|
|
1180
|
+
{ name: '--composition <id>', desc: 'Run in that composition\'s workspace dir.' },
|
|
1181
|
+
{ name: '--cwd <dir>', desc: 'Working directory for the turn.' },
|
|
1182
|
+
{ name: '--model <m>', desc: 'Model for this turn.' },
|
|
1183
|
+
{ name: '--continue / --resume <sid>', desc: 'Pick up the previous conversation at this cwd.' },
|
|
1184
|
+
],
|
|
1185
|
+
examples: [
|
|
1186
|
+
{ cmd: 'beehaven claude login', note: 'authorize once (opens a browser)' },
|
|
1187
|
+
{ cmd: 'beehaven claude "refactor auth.ts"', note: 'one turn in the current directory' },
|
|
1188
|
+
{ cmd: 'beehaven claude status', note: 'which credential is active' },
|
|
1189
|
+
],
|
|
1190
|
+
related: ['omni', 'treehouse'],
|
|
1191
|
+
},
|
|
1192
|
+
omni: {
|
|
1193
|
+
synopsis: 'beehaven omni "<task>" · beehaven omni sessions | end',
|
|
1194
|
+
description: `DAEMON OMNI — Claude Code hosted in the daemon, with the beehaven
|
|
1195
|
+
surface as first-party tools.
|
|
1196
|
+
|
|
1197
|
+
Same Claude Agent SDK runtime as \`beehaven claude\`, one important difference:
|
|
1198
|
+
\`claude\` runs it in THIS process (one Claude per invocation, dying with the
|
|
1199
|
+
command, no beehaven tools, invisible to anything else). \`omni\` drives the
|
|
1200
|
+
session living in the DAEMON — the same one the avatar's chat panel talks to.
|
|
1201
|
+
One warm session, one conversation, one set of tools, shared by every client.
|
|
1202
|
+
|
|
1203
|
+
That matters because the daemon is the only process holding the relay socket
|
|
1204
|
+
and the local buildings, which is what lets the beehaven surface be ~32 real
|
|
1205
|
+
in-process MCP tools (mcp__clearly__canvas_add_text, avatar_say,
|
|
1206
|
+
composition_create, …) instead of Claude shelling out to \`beehaven call\`.
|
|
1207
|
+
|
|
1208
|
+
Everything else is Claude Code as you know it: the full built-in tool set,
|
|
1209
|
+
your skills and slash commands, your MCP servers, subagents, session resume.
|
|
1210
|
+
|
|
1211
|
+
LOCAL ONLY. This rides the IPC socket (chmod 0600 — the kernel proving the
|
|
1212
|
+
caller is you, driving your own subscription). Cloud→daemon Claude
|
|
1213
|
+
orchestration stays disabled for Anthropic credential-use compliance; nothing
|
|
1214
|
+
here opens that path.
|
|
1215
|
+
|
|
1216
|
+
A turn returns as soon as it is ACCEPTED — text, tool calls and the result
|
|
1217
|
+
stream back as they happen, so a long coding turn prints as it works.
|
|
1218
|
+
|
|
1219
|
+
Every step renders INLINE: the tool name, each argument, then a ✓/✗ with a
|
|
1220
|
+
preview of what came back. Omni's own working text streams in dim as it is
|
|
1221
|
+
produced — that is its thinking, not its answer; the answer is the undimmed
|
|
1222
|
+
prose. Use --quiet to keep only the answers.`,
|
|
1223
|
+
flags: [
|
|
1224
|
+
{ name: '--session <id>', desc: 'Name the thread. Defaults to "default" — one shared conversation.' },
|
|
1225
|
+
{ name: '--cwd <dir>', desc: 'Where the turn runs. Defaults to the current directory.' },
|
|
1226
|
+
{ name: '--quiet, -q', desc: 'Replies only — drop the streamed working text and the step log. For scripts. Failed steps still print.' },
|
|
1227
|
+
],
|
|
1228
|
+
examples: [
|
|
1229
|
+
{ cmd: 'beehaven omni "add a red rectangle to my canvas"', note: 'uses the first-party canvas tools' },
|
|
1230
|
+
{ cmd: 'beehaven omni --session build "run the tests and fix what fails"', note: 'a named thread' },
|
|
1231
|
+
{ cmd: 'beehaven omni -q "summarise the open tickets"', note: 'just the answer, for piping' },
|
|
1232
|
+
{ cmd: 'beehaven omni sessions', note: 'what is live, and whether the beehaven tools are mounted' },
|
|
1233
|
+
{ cmd: 'beehaven omni end --session build', note: 'end a thread' },
|
|
1234
|
+
],
|
|
1235
|
+
related: ['claude', 'treehouse', 'status'],
|
|
1236
|
+
},
|
|
1237
|
+
treehouse: {
|
|
1238
|
+
synopsis: 'beehaven treehouse <claude|codex|gemini|pi> "<message>"',
|
|
1239
|
+
description: `Send ONE turn to a BYOK room in the Clearly desktop app and print its
|
|
1240
|
+
reply. The rooms run the user's OWN coding agents (Claude Code / Codex CLI /
|
|
1241
|
+
Gemini CLI / pi) on their own login — nothing bills Clearly's AI pool.
|
|
1242
|
+
|
|
1243
|
+
DEVELOPER MODE ONLY. A turn spends the user's own subscription and runs with
|
|
1244
|
+
their ~/Clearly filesystem, so the desktop app mounts this route only when
|
|
1245
|
+
developer mode is on; otherwise it 404s. Enable with HIVE_DEV_MODE=1 (or the
|
|
1246
|
+
tray's Settings entry) and relaunch.
|
|
1247
|
+
|
|
1248
|
+
Talks to the desktop app over loopback HTTP (127.0.0.1:3456), authorised with
|
|
1249
|
+
~/.beehaven/browser-token — NOT the daemon, which holds no rooms. The app must
|
|
1250
|
+
be running.
|
|
1251
|
+
|
|
1252
|
+
Synchronous: it waits for the whole turn (which can take minutes for a real
|
|
1253
|
+
build) and returns the final text. --verbose also prints each tool call.`,
|
|
1254
|
+
flags: [
|
|
1255
|
+
{ name: '--verbose', desc: 'print every tool call/result, not just the final text' },
|
|
1256
|
+
{ name: '--model <id>', desc: "the room's model (see `beehaven treehouse` in the app's settings for the catalog)" },
|
|
1257
|
+
{ name: '--session <id>', desc: 'continue a named thread instead of the default room session' },
|
|
1258
|
+
{ name: '--port <n>', desc: 'desktop RPC port (default 3456)' },
|
|
1259
|
+
],
|
|
1260
|
+
examples: [
|
|
1261
|
+
{ cmd: 'beehaven treehouse gemini "design a landing page for a hair salon"', note: 'the agent drives the canvas itself via the beehaven CLI' },
|
|
1262
|
+
{ cmd: 'beehaven treehouse claude "what did you build?" --session design-1', note: 'continue a named thread' },
|
|
1263
|
+
{ cmd: 'beehaven treehouse pi "list your skills" --verbose', note: 'watch the tool calls' },
|
|
1264
|
+
],
|
|
1265
|
+
related: ['call', 'actions', 'canvas'],
|
|
1266
|
+
},
|
|
1267
|
+
sql: {
|
|
1268
|
+
synopsis: 'beehaven sql "<query>"',
|
|
1269
|
+
description: `Run a SQL query against the target DO's SQLite tables — best for
|
|
1270
|
+
STRUCTURE: filter/sort/join/count on columns (title, type, project_id, dates).
|
|
1271
|
+
It CANNOT search composition content: the \`data\` blob is gzip-compressed, so
|
|
1272
|
+
\`WHERE data LIKE '%term%'\` silently misses everything compressed. For content,
|
|
1273
|
+
use \`grep\` (terminal) or the \`composition-search\` action (agent).
|
|
1274
|
+
Tables + columns: \`beehaven workspace\`.`,
|
|
1275
|
+
examples: [
|
|
1276
|
+
{ cmd: 'beehaven sql "SELECT COUNT(*) FROM notes"' },
|
|
1277
|
+
{
|
|
1278
|
+
cmd: 'beehaven sql "SELECT id, title FROM compositions ORDER BY updated_at DESC LIMIT 10"',
|
|
1279
|
+
},
|
|
1280
|
+
],
|
|
1281
|
+
related: ['workspace', 'grep', 'ls'],
|
|
1282
|
+
},
|
|
1283
|
+
d1: {
|
|
1284
|
+
synopsis: 'beehaven d1 <list|exec|dump|migrate> [args]',
|
|
1285
|
+
description: `Cloudflare D1 wrapper. Reads bindings from wrangler.toml/wrangler.jsonc
|
|
1286
|
+
so you don't have to pass --database-id. Defaults to --remote; pass --local
|
|
1287
|
+
to hit the wrangler emulator. Different layer from \`beehaven sql\` — that
|
|
1288
|
+
runs against a DO's SQLite, this runs against the account's D1 databases.
|
|
1289
|
+
|
|
1290
|
+
Subcommands:
|
|
1291
|
+
list Show D1 bindings declared in wrangler config
|
|
1292
|
+
exec <db> "<sql>" [--local] [--json] Execute SQL
|
|
1293
|
+
dump <db> <table> [--out file] Dump a table (JSON to stdout or file)
|
|
1294
|
+
migrate <db> apply [--local] Apply pending migrations
|
|
1295
|
+
migrate <db> list List applied/pending migrations
|
|
1296
|
+
migrate <db> create <name> Create a new migration file`,
|
|
1297
|
+
flags: [
|
|
1298
|
+
{ name: '--local', desc: 'Use local emulator instead of remote' },
|
|
1299
|
+
{ name: '--json', desc: 'Raw JSON output (exec)' },
|
|
1300
|
+
{ name: '--out <path>', desc: 'Write to file (dump)' },
|
|
1301
|
+
{ name: '--env <name>', desc: 'wrangler env (staging, etc.)' },
|
|
1302
|
+
],
|
|
1303
|
+
examples: [
|
|
1304
|
+
{ cmd: 'beehaven d1 list', note: 'show all configured D1 dbs' },
|
|
1305
|
+
{ cmd: 'beehaven d1 exec lumen-index "SELECT * FROM referrals LIMIT 5"' },
|
|
1306
|
+
{ cmd: 'beehaven d1 exec lumen-index --local "SELECT 1"', note: 'hit local emulator' },
|
|
1307
|
+
{ cmd: 'beehaven d1 dump lumen-index users --out users.json' },
|
|
1308
|
+
{ cmd: 'beehaven d1 migrate lumen-index apply' },
|
|
1309
|
+
],
|
|
1310
|
+
related: ['sql', 'workspace', 'status'],
|
|
1311
|
+
},
|
|
1312
|
+
secrets: {
|
|
1313
|
+
synopsis: 'beehaven secrets <list|set|delete|diff|check> [NAME] [--env <name>|all]',
|
|
1314
|
+
description: `Workers secrets wrapper. Defaults to operating on EVERY declared env
|
|
1315
|
+
(the parity-enforcement the root project CLAUDE.md flags as a recurring bug
|
|
1316
|
+
source — "when setting a secret on staging, ALWAYS set it on prod too").
|
|
1317
|
+
Detects envs from \`[env.<name>]\` blocks in wrangler.toml.
|
|
1318
|
+
|
|
1319
|
+
Subcommands:
|
|
1320
|
+
list [--env all|prod|...] Show secret names per env (matrix view)
|
|
1321
|
+
set <NAME> [--env all|...] Prompt for value, set on all envs by default
|
|
1322
|
+
delete <NAME> --yes Delete on all envs (requires --yes)
|
|
1323
|
+
diff Show secrets present on one env but not another
|
|
1324
|
+
check Verify required secrets (from beehaven.json
|
|
1325
|
+
"requiredSecrets") are set on every env`,
|
|
1326
|
+
flags: [
|
|
1327
|
+
{ name: '--env <name>|all', desc: 'Target a specific env or all (default: all)' },
|
|
1328
|
+
{ name: '--yes', desc: 'Skip confirmation (delete only)' },
|
|
1329
|
+
{ name: '--json', desc: 'Raw JSON output (list)' },
|
|
1330
|
+
],
|
|
1331
|
+
examples: [
|
|
1332
|
+
{ cmd: 'beehaven secrets list', note: 'matrix view across all envs' },
|
|
1333
|
+
{ cmd: 'beehaven secrets set GCP_SERVICE_ACCOUNT_JSON', note: 'sets on prod + staging' },
|
|
1334
|
+
{ cmd: 'beehaven secrets set FOO --env staging', note: 'one env only' },
|
|
1335
|
+
{ cmd: 'beehaven secrets diff', note: 'find parity gaps' },
|
|
1336
|
+
{ cmd: 'beehaven secrets check', note: 'verify against beehaven.json requiredSecrets' },
|
|
1337
|
+
],
|
|
1338
|
+
related: ['d1', 'workspace', 'status'],
|
|
1339
|
+
},
|
|
1340
|
+
user: {
|
|
1341
|
+
synopsis: 'beehaven user <userId> <inspect|dump|sql|export|wipe> [args]',
|
|
1342
|
+
description: `Per-user admin sugar over the DO admin surface. Resolves the user's
|
|
1343
|
+
DO class from --workspace, or \`userWorkspace\` in beehaven.json. Auth via
|
|
1344
|
+
--url + --secret flags (or BEEHAVEN_WORKER_URL / BEEHAVEN_ADMIN_SECRET env).
|
|
1345
|
+
Daemon-optional — works against any deployed worker.
|
|
1346
|
+
|
|
1347
|
+
Subcommands:
|
|
1348
|
+
inspect Storage breakdown + per-table row counts
|
|
1349
|
+
sql "<query>" Sugar over admin:sql for this user's DO
|
|
1350
|
+
dump <folder> [--out file] Dump one folder as JSON
|
|
1351
|
+
export [--out file] Dump all folders into one JSON file
|
|
1352
|
+
(uses cfg.user.exportAction if defined)
|
|
1353
|
+
wipe --yes Delete all data (uses cfg.user.wipeAction
|
|
1354
|
+
if defined; otherwise DELETE per-table)
|
|
1355
|
+
|
|
1356
|
+
beehaven.json hints:
|
|
1357
|
+
{ "userWorkspace": "User" }
|
|
1358
|
+
{ "user": { "workspace": "User", "wipeAction": "delete-account",
|
|
1359
|
+
"exportAction": "export-account" } }`,
|
|
1360
|
+
flags: [
|
|
1361
|
+
{ name: '--workspace <type>', desc: 'DO class for the user (default: from beehaven.json)' },
|
|
1362
|
+
{ name: '--url <url>', desc: 'Worker URL (default: BEEHAVEN_WORKER_URL env)' },
|
|
1363
|
+
{ name: '--secret <token>', desc: 'Admin bearer (default: BEEHAVEN_ADMIN_SECRET env)' },
|
|
1364
|
+
{ name: '--out <path>', desc: 'Write to file (dump/export)' },
|
|
1365
|
+
{ name: '--yes', desc: 'Skip confirm (wipe)' },
|
|
1366
|
+
{ name: '--json', desc: 'Raw JSON output (sql)' },
|
|
1367
|
+
],
|
|
1368
|
+
examples: [
|
|
1369
|
+
{ cmd: 'beehaven user abc123 inspect' },
|
|
1370
|
+
{ cmd: 'beehaven user abc123 sql "SELECT * FROM readings LIMIT 5"' },
|
|
1371
|
+
{ cmd: 'beehaven user abc123 dump journal --out journal.json' },
|
|
1372
|
+
{ cmd: 'beehaven user abc123 export --out user-abc.json', note: 'GDPR export' },
|
|
1373
|
+
{ cmd: 'beehaven user abc123 wipe --yes', note: 'GDPR delete' },
|
|
1374
|
+
],
|
|
1375
|
+
related: ['sql', 'workspace', 'd1'],
|
|
1376
|
+
},
|
|
1377
|
+
webhook: {
|
|
1378
|
+
synopsis: 'beehaven webhook <list|show|replay|dlq> <type>/<id> [args]',
|
|
1379
|
+
description: `Inspect + replay the outgoing webhook DLQ. Operates on the
|
|
1380
|
+
\`_bh_webhooks\` table that the SDK's \`this.webhooks()\` writes into.
|
|
1381
|
+
Different layer from incoming webhook receivers (those handle in your
|
|
1382
|
+
app code; the SDK doesn't queue failed inbound deliveries).
|
|
1383
|
+
|
|
1384
|
+
Subcommands:
|
|
1385
|
+
list <type>/<id> [--status dead|pending|delivered] [--limit N]
|
|
1386
|
+
dlq <type>/<id> Shortcut for list --status dead
|
|
1387
|
+
show <type>/<id> <id> Full row for one event (JSON)
|
|
1388
|
+
replay <type>/<id> <id> Re-arm: flips status to pending, resets attempts.
|
|
1389
|
+
The next alarm tick drains it. For immediate drain,
|
|
1390
|
+
expose a webhook-drain action on your workspace.
|
|
1391
|
+
|
|
1392
|
+
Auth: --url + --secret (or BEEHAVEN_WORKER_URL / BEEHAVEN_ADMIN_SECRET).`,
|
|
1393
|
+
flags: [
|
|
1394
|
+
{ name: '--status <s>', desc: 'Filter: pending | dead | delivered' },
|
|
1395
|
+
{ name: '--limit <N>', desc: 'Max rows (default 50)' },
|
|
1396
|
+
{ name: '--url <url>', desc: 'Worker URL' },
|
|
1397
|
+
{ name: '--secret <token>', desc: 'Admin bearer' },
|
|
1398
|
+
{ name: '--json', desc: 'Raw JSON output' },
|
|
1399
|
+
],
|
|
1400
|
+
examples: [
|
|
1401
|
+
{ cmd: 'beehaven webhook list User/abc123' },
|
|
1402
|
+
{ cmd: 'beehaven webhook dlq User/abc123', note: 'just the failures' },
|
|
1403
|
+
{ cmd: 'beehaven webhook show User/abc123 wh-789' },
|
|
1404
|
+
{ cmd: 'beehaven webhook replay User/abc123 wh-789' },
|
|
1405
|
+
],
|
|
1406
|
+
related: ['user', 'sql', 'workspace'],
|
|
1407
|
+
},
|
|
1408
|
+
workspace: {
|
|
1409
|
+
synopsis: 'beehaven workspace',
|
|
1410
|
+
description: `Overview of the target DO — tables (name + row count + top 5 columns) and actions (grouped by category). The fastest way to understand a DO's shape after \`cd\`.`,
|
|
1411
|
+
examples: [{ cmd: 'beehaven workspace' }],
|
|
1412
|
+
related: ['actions', 'sql', 'ls'],
|
|
1413
|
+
},
|
|
1414
|
+
watch: {
|
|
1415
|
+
synopsis: 'beehaven watch [--format <fmt>]',
|
|
1416
|
+
description: `Stream live events from the target DO (table mutations, deltas,
|
|
1417
|
+
broadcast events). One JSON event per line by default.`,
|
|
1418
|
+
flags: [
|
|
1419
|
+
{ name: '--format tool-use', desc: 'Structured {event, table, id, delta} shapes for agents' },
|
|
1420
|
+
],
|
|
1421
|
+
examples: [
|
|
1422
|
+
{ cmd: 'beehaven watch' },
|
|
1423
|
+
{ cmd: 'beehaven watch --format tool-use | grep row-changed' },
|
|
1424
|
+
],
|
|
1425
|
+
related: ['workspace', 'sql'],
|
|
1426
|
+
},
|
|
1427
|
+
shop: {
|
|
1428
|
+
synopsis: 'beehaven shop <find|at|search|get|checkout> [...]',
|
|
1429
|
+
description: `Shop via the shop@0 protocol. "find" searches Yellow Pages;
|
|
1430
|
+
"at <addr>" routes to a specific shop; bare "search/get/checkout" uses
|
|
1431
|
+
the active target.`,
|
|
1432
|
+
examples: [
|
|
1433
|
+
{ cmd: 'beehaven shop find "running shoes" --category footwear --geo US' },
|
|
1434
|
+
{ cmd: 'beehaven shop at shopifyStore/clearly-demo search "hoodie"' },
|
|
1435
|
+
{ cmd: 'beehaven shop checkout --items \'[{"variantId":"v1","quantity":1}]\'' },
|
|
1436
|
+
],
|
|
1437
|
+
related: ['cd', 'call', 'actions'],
|
|
1438
|
+
},
|
|
1439
|
+
status: {
|
|
1440
|
+
synopsis: 'beehaven status',
|
|
1441
|
+
description: `Daemon + account health + current target + "what to do next" hint.
|
|
1442
|
+
Use when something seems wrong and you're not sure if it's the daemon,
|
|
1443
|
+
auth, or the target.`,
|
|
1444
|
+
examples: [{ cmd: 'beehaven status' }],
|
|
1445
|
+
related: ['pwd', 'buildings'],
|
|
1446
|
+
},
|
|
1447
|
+
buildings: {
|
|
1448
|
+
synopsis: 'beehaven buildings',
|
|
1449
|
+
description: `List every DO you can reach — local apps (installed),
|
|
1450
|
+
common cloud DO types. Useful before \`cd\` when you don't know the address.`,
|
|
1451
|
+
examples: [{ cmd: 'beehaven buildings' }],
|
|
1452
|
+
related: ['cd', 'pwd'],
|
|
1453
|
+
},
|
|
1454
|
+
task: {
|
|
1455
|
+
synopsis: 'beehaven task "<title>" [--status active|idea|shipped]',
|
|
1456
|
+
description: `Create a task note on the active target. Shorthand for
|
|
1457
|
+
\`beehaven call note-create '{"title":"...","fileType":"board","status":"active"}'\`.
|
|
1458
|
+
|
|
1459
|
+
⚠⚠ --status IS APPLIED NOW (fixed 2026-09-05, CBH2-4). It used to be dropped
|
|
1460
|
+
on the way to note-create — every task stored "active" — while this command
|
|
1461
|
+
printed the status you ASKED for, so the terminal confirmed a write that had
|
|
1462
|
+
not happened. The line now echoes what the SERVER stored.
|
|
1463
|
+
|
|
1464
|
+
⚠ An unrecognised status is REFUSED rather than stored. Nothing renders a
|
|
1465
|
+
status outside active|idea|shipped, so it would file the task somewhere no
|
|
1466
|
+
view can show it.`,
|
|
1467
|
+
examples: [
|
|
1468
|
+
{ cmd: 'beehaven task "Fix the IPC auth bug"' },
|
|
1469
|
+
{ cmd: 'beehaven task "Voice CLI idea" --status idea' },
|
|
1470
|
+
],
|
|
1471
|
+
related: ['search', 'call'],
|
|
1472
|
+
},
|
|
1473
|
+
search: {
|
|
1474
|
+
synopsis: 'beehaven search "<query>" [--limit N]',
|
|
1475
|
+
description: `Ranked full-text search across documents on the active target
|
|
1476
|
+
(FTS5/BM25, stemmed — "credits" finds "crediting").
|
|
1477
|
+
|
|
1478
|
+
⚠⚠ --limit IS HONOURED NOW (fixed 2026-09-05, CBH2-29). It was accepted and
|
|
1479
|
+
ignored — every search returned 20 rows whatever you asked for — which reads
|
|
1480
|
+
as support, because this CLI rejects flags it does not know. 1-200; a
|
|
1481
|
+
non-number or 0 is refused, and above 200 it clamps and says so.
|
|
1482
|
+
|
|
1483
|
+
⚠ Each hit prints its KEY (\`CLR-42\`), so a result can be handed straight to
|
|
1484
|
+
\`cat ~/CLR-42.md\` or \`open\`. A title is not an address — two notes can
|
|
1485
|
+
share one.
|
|
1486
|
+
|
|
1487
|
+
⚠ THREE VERBS SEARCH, AND THEY ANSWER DIFFERENT QUESTIONS:
|
|
1488
|
+
search → which documents are ABOUT this (ranked, stems)
|
|
1489
|
+
grep → which documents CONTAIN this string (literal, substring)
|
|
1490
|
+
find → what is this CALLED / where is it (POSIX, name + path)
|
|
1491
|
+
|
|
1492
|
+
⚠ \`find\` IS NOT A SYNONYM FOR THIS, though \`help\` used to say so. It runs
|
|
1493
|
+
POSIX find and reports a missing PATH, which reads as an empty workspace.
|
|
1494
|
+
|
|
1495
|
+
⚠ It searches BODIES, so a document created with no body is invisible here
|
|
1496
|
+
however good its title.`,
|
|
1497
|
+
examples: [
|
|
1498
|
+
{ cmd: 'beehaven search "revenue attribution"' },
|
|
1499
|
+
{ cmd: 'beehaven search "pricing" --limit 5', note: 'bound the output' },
|
|
1500
|
+
{ cmd: 'beehaven grep -ril pricing ~', note: 'literal string instead' },
|
|
1501
|
+
],
|
|
1502
|
+
related: ['grep', 'find', 'cat', 'task', 'call'],
|
|
1503
|
+
},
|
|
1504
|
+
/**
|
|
1505
|
+
* ⚠ `workspaces` WAS INVISIBLE TWICE OVER — no help page AND not named in the top-level verb
|
|
1506
|
+
* list, yet it is the command that prints the connect string for every workspace you can reach.
|
|
1507
|
+
* A verb you can only find by already knowing it exists is not on the surface.
|
|
1508
|
+
*/
|
|
1509
|
+
workspaces: {
|
|
1510
|
+
synopsis: 'beehaven workspaces',
|
|
1511
|
+
description: `Every workspace this account can reach, with your role in each
|
|
1512
|
+
and the exact \`beehaven connect\` line for it.
|
|
1513
|
+
|
|
1514
|
+
This is the answer to "what else is there" and to "how do I address the other
|
|
1515
|
+
one" — the ids are 64-hex and nobody types them from memory, so copy the
|
|
1516
|
+
printed connect line.
|
|
1517
|
+
|
|
1518
|
+
⚠ ENUMERATING IS NOT SWITCHING. This lists them; \`beehaven connect
|
|
1519
|
+
workspace/<id>\` is what moves you. The one marked (default) is where a bare
|
|
1520
|
+
\`connect home\` lands.`,
|
|
1521
|
+
examples: [
|
|
1522
|
+
{ cmd: 'beehaven workspaces' },
|
|
1523
|
+
{ cmd: 'beehaven connect workspace/<id>', note: 'copy the printed line' },
|
|
1524
|
+
{ cmd: 'beehaven pwd', note: 'which one am I in now' },
|
|
1525
|
+
],
|
|
1526
|
+
related: ['cd', 'pwd', 'buildings', 'status'],
|
|
1527
|
+
},
|
|
1528
|
+
library: {
|
|
1529
|
+
synopsis: 'beehaven library <list|get|add|rm|search> [args]',
|
|
1530
|
+
description: `The reference library — saved images, components and sources the
|
|
1531
|
+
agent can look at again. Bare \`library\` lists.
|
|
1532
|
+
|
|
1533
|
+
Entries are addressed by the short id in the first column of \`library list\`.
|
|
1534
|
+
|
|
1535
|
+
⚠⚠ THAT SENTENCE WAS FALSE UNTIL 2026-09-05 (CBH2-30). \`list\` and \`search\`
|
|
1536
|
+
print \`id.slice(0,8)\` so the columns line up, and \`get\` / \`rm\` refused
|
|
1537
|
+
exactly that string with a bare "Not found" — which is what you print for a
|
|
1538
|
+
DELETED row, so it sent readers hunting for a data problem. There was no
|
|
1539
|
+
route from \`list\` to \`get\` inside the CLI at all; the full uuid was only
|
|
1540
|
+
reachable via \`beehaven call library-list\` — the actions door, which a
|
|
1541
|
+
person reading \`library list\` output has no reason to go looking for.
|
|
1542
|
+
|
|
1543
|
+
Both forms work now. A prefix of 6+ characters resolves; one that matches
|
|
1544
|
+
two entries is REFUSED with the candidates rather than guessed — which
|
|
1545
|
+
matters most for \`rm\`, where guessing destroys the wrong asset and its
|
|
1546
|
+
R2 object.`,
|
|
1547
|
+
examples: [
|
|
1548
|
+
{ cmd: 'beehaven library list' },
|
|
1549
|
+
{ cmd: 'beehaven library search "card"' },
|
|
1550
|
+
{ cmd: 'beehaven library get bbd9fd21', note: 'the short id from the list — a prefix is fine' },
|
|
1551
|
+
],
|
|
1552
|
+
related: ['teleport', 'doc', 'ls'],
|
|
1553
|
+
},
|
|
1554
|
+
/**
|
|
1555
|
+
* ⚠ `help` HAD NO PAGE FOR ITSELF — caught by the derived coverage guard, which is the point of
|
|
1556
|
+
* deriving it. The CLI's top-level help points every agent at `beehaven help <command>`, so the
|
|
1557
|
+
* one verb guaranteed to be tried is the one that answered "No help page for help".
|
|
1558
|
+
*/
|
|
1559
|
+
help: {
|
|
1560
|
+
synopsis: 'beehaven help [command]',
|
|
1561
|
+
description: `Deep help for one command. Bare \`beehaven help\` prints the
|
|
1562
|
+
index of every page and alias; \`beehaven --help\` prints the whole surface at
|
|
1563
|
+
once.
|
|
1564
|
+
|
|
1565
|
+
⚠ A page is a CLAIM, and its examples are meant to be runnable as printed. If
|
|
1566
|
+
one is not, that is a bug worth filing — four shell pages once documented a
|
|
1567
|
+
namespace that needed a scope the reader did not have, and every example on
|
|
1568
|
+
them failed.
|
|
1569
|
+
|
|
1570
|
+
An unknown name exits non-zero and suggests near matches.`,
|
|
1571
|
+
examples: [
|
|
1572
|
+
{ cmd: 'beehaven help', note: 'the index' },
|
|
1573
|
+
{ cmd: 'beehaven help ls' },
|
|
1574
|
+
{ cmd: 'beehaven --help', note: 'the whole surface' },
|
|
1575
|
+
],
|
|
1576
|
+
related: ['actions', 'explain', 'workspace'],
|
|
1577
|
+
},
|
|
1578
|
+
link: {
|
|
1579
|
+
synopsis: 'beehaven link [--project <id>] · beehaven unlink',
|
|
1580
|
+
description: `Bind THIS local folder to a Clearly project, so a coding agent
|
|
1581
|
+
working in it can be given the project's own notes. With no \`--project\` it
|
|
1582
|
+
offers the projects it can see.
|
|
1583
|
+
|
|
1584
|
+
⚠ THIS IS THE PREREQUISITE FOR \`context\`. Unlinked, \`beehaven context\`
|
|
1585
|
+
does nothing and says so — that is the whole failure mode, and it is not a
|
|
1586
|
+
workspace error.
|
|
1587
|
+
|
|
1588
|
+
⚠ Local, per-folder state. It changes nothing in the workspace.`,
|
|
1589
|
+
examples: [
|
|
1590
|
+
{ cmd: 'beehaven link --project <id>' },
|
|
1591
|
+
{ cmd: 'beehaven context', note: 'what the link is for' },
|
|
1592
|
+
{ cmd: 'beehaven unlink' },
|
|
1593
|
+
],
|
|
1594
|
+
related: ['context', 'pwd', 'workspace'],
|
|
1595
|
+
},
|
|
1596
|
+
'mcp-config': {
|
|
1597
|
+
synopsis: 'beehaven mcp-config [--name <server-name>]',
|
|
1598
|
+
description: `Print the MCP server block instead of writing it — for a client
|
|
1599
|
+
\`mcp install\` does not know about, or a config you keep in version control.
|
|
1600
|
+
|
|
1601
|
+
⚠⚠ IT MINTS A REAL TOKEN. The printed block contains a live \`ck_mcp_*\`
|
|
1602
|
+
credential, so this is not a dry run: treat the output as a secret, and
|
|
1603
|
+
revoke with \`beehaven mcp remove\` rather than just deleting the text.
|
|
1604
|
+
|
|
1605
|
+
⚠ The block is minted for the workspace you are CONNECTED to — \`beehaven
|
|
1606
|
+
pwd\` first.`,
|
|
1607
|
+
examples: [
|
|
1608
|
+
{ cmd: 'beehaven mcp-config --name clearly' },
|
|
1609
|
+
{ cmd: 'beehaven mcp install', note: 'write it for detected clients instead' },
|
|
1610
|
+
{ cmd: 'beehaven mcp remove', note: 'revoke the token' },
|
|
1611
|
+
],
|
|
1612
|
+
related: ['mcp', 'pwd', 'workspaces'],
|
|
1613
|
+
},
|
|
1614
|
+
mcp: {
|
|
1615
|
+
synopsis: 'beehaven mcp <install|status|remove>',
|
|
1616
|
+
description: `Connect the AI clients on THIS machine to the workspace you are
|
|
1617
|
+
connected to. \`install\` detects Claude Code, Claude Desktop, Cursor and Codex
|
|
1618
|
+
and writes the server entry into each; \`status\` shows which are configured;
|
|
1619
|
+
\`remove\` deletes the entries and revokes the token.
|
|
1620
|
+
|
|
1621
|
+
⚠ IT WRITES FOR THE WORKSPACE YOU ARE IN. \`beehaven pwd\` first — installing
|
|
1622
|
+
from the wrong target points every client at the wrong workspace.
|
|
1623
|
+
|
|
1624
|
+
⚠ For a client that is not on this machine (claude.ai, another laptop) there is
|
|
1625
|
+
nothing to install: point it at the endpoint and let it sign you in. Print the
|
|
1626
|
+
block instead of writing it with \`beehaven mcp-config\`.`,
|
|
1627
|
+
examples: [
|
|
1628
|
+
{ cmd: 'beehaven mcp status', note: 'which clients are configured' },
|
|
1629
|
+
{ cmd: 'beehaven mcp install' },
|
|
1630
|
+
{ cmd: 'beehaven mcp-config --name clearly', note: 'print, do not write' },
|
|
1631
|
+
],
|
|
1632
|
+
related: ['pwd', 'workspaces', 'agent', 'skills'],
|
|
1633
|
+
},
|
|
1634
|
+
context: {
|
|
1635
|
+
synopsis: 'beehaven context',
|
|
1636
|
+
description: `Refresh \`.clearly/CLAUDE.md\` in the CURRENT LOCAL FOLDER from
|
|
1637
|
+
the Clearly project it is linked to — so a coding agent opening this repo
|
|
1638
|
+
starts with the project's own notes in front of it.
|
|
1639
|
+
|
|
1640
|
+
⚠ IT NEEDS A LINK FIRST. In an unlinked folder it says so and does nothing:
|
|
1641
|
+
"This folder is not linked to a Clearly project. Run 'beehaven link'."
|
|
1642
|
+
That is the whole failure mode — it is not a workspace error.
|
|
1643
|
+
|
|
1644
|
+
⚠ This is the one verb here that writes to your LOCAL disk rather than to the
|
|
1645
|
+
workspace.`,
|
|
1646
|
+
examples: [
|
|
1647
|
+
{ cmd: 'beehaven context' },
|
|
1648
|
+
{ cmd: 'beehaven link --project <id>', note: 'required first, once per folder' },
|
|
1649
|
+
],
|
|
1650
|
+
related: ['workspace', 'pwd', 'doc'],
|
|
1651
|
+
},
|
|
1652
|
+
remember: {
|
|
1653
|
+
synopsis: 'beehaven remember <key> <value>',
|
|
1654
|
+
description: `Store an agent memory — key/value pair retrievable via recall.`,
|
|
1655
|
+
examples: [{ cmd: 'beehaven remember favorite-color blue' }],
|
|
1656
|
+
related: ['recall'],
|
|
1657
|
+
},
|
|
1658
|
+
recall: {
|
|
1659
|
+
synopsis: 'beehaven recall [query]',
|
|
1660
|
+
description: `Retrieve agent memories. With a query, semantic-matches.
|
|
1661
|
+
Without, lists recent.`,
|
|
1662
|
+
examples: [{ cmd: 'beehaven recall "favorite color"' }],
|
|
1663
|
+
related: ['remember'],
|
|
1664
|
+
},
|
|
1665
|
+
teleport: {
|
|
1666
|
+
synopsis: 'beehaven teleport <file> [--to <path>] [--composition <id>] [--no-document]',
|
|
1667
|
+
description: `Upload a file into workspace storage. This is the terminal
|
|
1668
|
+
equivalent of dragging a file onto the gallery, and it does the same four
|
|
1669
|
+
things:
|
|
1670
|
+
|
|
1671
|
+
1. put the bytes in R2 (under uploads/, or --to <dir>)
|
|
1672
|
+
2. insert the \`files\` row that /recents reads
|
|
1673
|
+
3. index it for search, when the format carries text
|
|
1674
|
+
4. hand back the file id
|
|
1675
|
+
|
|
1676
|
+
⚠⚠ STEP 4 DID NOT HAPPEN UNTIL 2026-09-05 (CBH2-38). The output was a VFS
|
|
1677
|
+
path and nothing else, so the two-step printed in \`beehaven help sheet\` —
|
|
1678
|
+
\`teleport ./data.csv && sheet import <fileId>\` — had no <fileId> to
|
|
1679
|
+
substitute, and the only way to get one was
|
|
1680
|
+
\`beehaven sql "SELECT id FROM files WHERE name LIKE …"\`. The id is printed
|
|
1681
|
+
on both upload paths now, with the \`sheet import\` line for a .csv/.tsv.
|
|
1682
|
+
|
|
1683
|
+
Step 3 is what most callers forget they need. \`document-search\` is
|
|
1684
|
+
full-text over the document BODY, so a file that is never projected into a
|
|
1685
|
+
document is stored, listed, and invisible to every search you will run
|
|
1686
|
+
afterwards. Pass --no-document only when you want an opaque blob.
|
|
1687
|
+
|
|
1688
|
+
HOW THE BYTES TRAVEL, and why you do not choose: under ~900KB the file
|
|
1689
|
+
rides inline over the relay; above it, teleport asks for a presigned URL and
|
|
1690
|
+
PUTs straight to R2, so large files never cross the WebSocket. The switch is
|
|
1691
|
+
automatic. The overall ceiling is 100MB.
|
|
1692
|
+
|
|
1693
|
+
PDFs are stored and openable but NOT searchable — text extraction for PDF
|
|
1694
|
+
runs in the browser, which a terminal has no equivalent of.
|
|
1695
|
+
|
|
1696
|
+
--composition <id> stores the file as that composition's own asset instead,
|
|
1697
|
+
so it does not appear in /recents and is not projected into a document.`,
|
|
1698
|
+
flags: [
|
|
1699
|
+
{ name: '--to <dir>', desc: 'Destination directory in workspace storage (default: uploads/)' },
|
|
1700
|
+
{ name: '--composition <id>', desc: 'Store as a composition asset instead of a workspace file' },
|
|
1701
|
+
{ name: '--no-document', desc: 'Skip the search-indexing step; store an opaque blob' },
|
|
1702
|
+
],
|
|
1703
|
+
examples: [
|
|
1704
|
+
{ cmd: 'beehaven teleport ./report.pdf' },
|
|
1705
|
+
{ cmd: 'beehaven teleport ./notes.md --to research/' },
|
|
1706
|
+
{ cmd: 'beehaven teleport ./photo.png --no-document' },
|
|
1707
|
+
],
|
|
1708
|
+
related: ['ls', 'cat', 'call'],
|
|
1709
|
+
},
|
|
1710
|
+
agent: {
|
|
1711
|
+
synopsis: 'beehaven agent [<identity-cmd>] | ["<msg>"] [-c] [-l] [-p <provider>] [-m <model>]',
|
|
1712
|
+
description: `Two surfaces under one verb:
|
|
1713
|
+
|
|
1714
|
+
IDENTITY — sign in as a per-agent principal so a runtime can drive its
|
|
1715
|
+
OWN avatar. Each terminal carries a different identity via the
|
|
1716
|
+
BEEHAVEN_AGENT env var (per-tty), so 4 windows = 4 avatars:
|
|
1717
|
+
agent login <name> [--label <work>] [--client <client>] — identity + ONE work session + brief
|
|
1718
|
+
agent use <name> — prints \`export BEEHAVEN_AGENT=<name>\`; eval it
|
|
1719
|
+
agent list — list stored identities, mark the active one
|
|
1720
|
+
agent whoami — show the active identity + TTL
|
|
1721
|
+
agent logout [<name>]— end its local session, keep the identity
|
|
1722
|
+
agent delete <name> — archive the current workspace projection + remove this device copy
|
|
1723
|
+
agent delete <name> --account --yes
|
|
1724
|
+
— delete the portable account identity across workspaces + this device copy
|
|
1725
|
+
agent rebind <name> --avatar <id> — re-bind to a different avatar
|
|
1726
|
+
|
|
1727
|
+
REPL — a bare \`agent\` (or \`agent "<msg>"\`) launches the Omni terminal
|
|
1728
|
+
REPL / one-shot message on the active target.
|
|
1729
|
+
|
|
1730
|
+
Canonical start: select the target first, then run
|
|
1731
|
+
\`beehaven agent login <name> --label "<work>" --client cli\`. Login already
|
|
1732
|
+
starts one workspace work session and prints its brief. Do not immediately
|
|
1733
|
+
call \`agent-login\`; that RPC aliases \`agent-session-start\` and starts another.
|
|
1734
|
+
|
|
1735
|
+
The active identity (BEEHAVEN_AGENT or --agent <name>) is attached to
|
|
1736
|
+
\`app call\` / \`say\` / \`speak\`, routing avatar calls to that agent's
|
|
1737
|
+
avatar instance.`,
|
|
1738
|
+
flags: [
|
|
1739
|
+
{ name: '--avatar <id>', desc: 'Avatar routing id (login/rebind)' },
|
|
1740
|
+
{ name: '--avatar-skin <skin>', desc: 'Mwah skin to wear; auto-assigned when omitted' },
|
|
1741
|
+
{ name: '--kind <k>', desc: 'claude-code | daemon-agent | clearly-ai (login)' },
|
|
1742
|
+
{ name: '--label <work>', desc: 'Label the workspace work session started by login' },
|
|
1743
|
+
{ name: '--client <client>', desc: 'Session client label (default: cli)' },
|
|
1744
|
+
{ name: '--agent <name>', desc: 'Per-call active-identity override (any command)' },
|
|
1745
|
+
{ name: '-c, --continue', desc: 'REPL: continue the last conversation' },
|
|
1746
|
+
{ name: '-l, --local', desc: 'REPL: use local LLM (Ollama)' },
|
|
1747
|
+
{ name: '-p <provider>', desc: 'REPL: openrouter, gemini, anthropic (default: platform)' },
|
|
1748
|
+
{ name: '-m <model>', desc: 'REPL: model name' },
|
|
1749
|
+
],
|
|
1750
|
+
examples: [
|
|
1751
|
+
{ cmd: 'beehaven connect home && beehaven agent login monet --label "audit launch" --client cli', note: 'identity + one labelled work session + brief' },
|
|
1752
|
+
{ cmd: 'eval "$(beehaven agent use monet)"', note: 'activate in this terminal' },
|
|
1753
|
+
{ cmd: 'beehaven say "hi from monet"', note: "speaks via monet's avatar" },
|
|
1754
|
+
{ cmd: 'beehaven agent rebind monet --avatar studio-2' },
|
|
1755
|
+
{ cmd: 'beehaven agent whoami' },
|
|
1756
|
+
{ cmd: 'beehaven agent "what can you do?"', note: 'REPL one-shot' },
|
|
1757
|
+
],
|
|
1758
|
+
related: ['app', 'pipe', 'pwd'],
|
|
1759
|
+
},
|
|
1760
|
+
swarm: {
|
|
1761
|
+
synopsis: 'beehaven swarm <list|queen|role|dispatch|bees|sample-honey|forge-omni> [args]',
|
|
1762
|
+
description: `The distributed HIVE MESH + its two AI bees. A "beehive" is a
|
|
1763
|
+
node running the daemon + hives (this Mac, a headless server via
|
|
1764
|
+
\`start --headless\`, or a Cloudflare container). A QUEEN hive orchestrates;
|
|
1765
|
+
WORKER hives execute the work the queen dispatches. This machine registers
|
|
1766
|
+
itself when the daemon connects — the Mac defaults to QUEEN, a
|
|
1767
|
+
headless/container node to WORKER.
|
|
1768
|
+
|
|
1769
|
+
Mesh subcommands:
|
|
1770
|
+
list Every beehive: role, kind, hives, online state
|
|
1771
|
+
queen Which NODE is orchestrating right now
|
|
1772
|
+
role <queen|worker> Make THIS machine the queen (or a worker)
|
|
1773
|
+
whoami This machine's beehive identity
|
|
1774
|
+
dispatch <cap> <action> [json] Route work to the best worker (--target pins one)
|
|
1775
|
+
forget <deviceId> Drop a stale OFFLINE node
|
|
1776
|
+
|
|
1777
|
+
The bees (AI):
|
|
1778
|
+
bees 👑 Queen + 🐝 Omni status
|
|
1779
|
+
sample-honey 👑 Queen ingests the WHOLE workspace corpus
|
|
1780
|
+
(memories, brain, prompts, brand voice) and gets fat
|
|
1781
|
+
forge-omni [--force] 👑 Queen distills a LEAN copy of you → 🐝 Omni,
|
|
1782
|
+
your personal-assistant AI TWIN (--force re-samples)
|
|
1783
|
+
|
|
1784
|
+
The Queen bee runs on the queen hive — same crown, two layers (the NODE vs.
|
|
1785
|
+
the AI). Omni is the owner's twin: log in as it with \`agent login omni-bee\`.
|
|
1786
|
+
Distinct from \`hives\` (local apps) — a beehive is a whole NODE.`,
|
|
1787
|
+
flags: [
|
|
1788
|
+
{
|
|
1789
|
+
name: '--target <deviceId>',
|
|
1790
|
+
desc: 'dispatch: pin to a specific beehive instead of auto-selecting',
|
|
1791
|
+
},
|
|
1792
|
+
{ name: '--force', desc: 'forge-omni: re-sample the honey before distilling' },
|
|
1793
|
+
],
|
|
1794
|
+
examples: [
|
|
1795
|
+
{ cmd: 'beehaven swarm list', note: 'see the whole swarm' },
|
|
1796
|
+
{ cmd: 'beehaven swarm role queen', note: 'make this machine the queen' },
|
|
1797
|
+
{ cmd: 'beehaven swarm sample-honey', note: 'Queen ingests everything' },
|
|
1798
|
+
{ cmd: 'beehaven swarm forge-omni', note: 'forge your AI twin' },
|
|
1799
|
+
{ cmd: 'beehaven agent login omni-bee', note: 'log in as your twin' },
|
|
1800
|
+
],
|
|
1801
|
+
related: ['hives', 'app', 'agent', 'status'],
|
|
1802
|
+
},
|
|
1803
|
+
pipe: {
|
|
1804
|
+
synopsis: 'beehaven pipe',
|
|
1805
|
+
description: `JSON-RPC 2.0 over stdin/stdout — for Claude Code and other
|
|
1806
|
+
agents that want structured interaction. Methods: actions.list,
|
|
1807
|
+
actions.describe, workspace.info, plus any action name as a method.`,
|
|
1808
|
+
examples: [
|
|
1809
|
+
{
|
|
1810
|
+
cmd: `echo '{"jsonrpc":"2.0","id":1,"method":"actions.list","params":{}}' | beehaven pipe`,
|
|
1811
|
+
note: 'one-shot action listing',
|
|
1812
|
+
},
|
|
1813
|
+
],
|
|
1814
|
+
related: ['actions', 'call'],
|
|
1815
|
+
},
|
|
1816
|
+
batch: {
|
|
1817
|
+
synopsis: 'beehaven batch <json|@file|-> [--json]',
|
|
1818
|
+
description: `Run the workspace's existing 'batch' action without hand-encoding
|
|
1819
|
+
the generic 'call' envelope. The payload is JSON (inline, from '@file', or
|
|
1820
|
+
from stdin with '-') and must contain the server action's 'steps' array.
|
|
1821
|
+
Steps execute sequentially and the operation is NOT transactional: earlier
|
|
1822
|
+
successful steps are not rolled back when a later step fails. The server
|
|
1823
|
+
enforces its action-count/payload limits and 'stopOnError' policy. This is
|
|
1824
|
+
a thin adapter, so the active target, agent identity, permission re-gating,
|
|
1825
|
+
spend guard and non-zero failure semantics are the same as 'beehaven call'.`,
|
|
1826
|
+
flags: [
|
|
1827
|
+
{ name: '--json', desc: 'Keep stdout machine-readable (suppresses the routing breadcrumb).' },
|
|
1828
|
+
],
|
|
1829
|
+
examples: [
|
|
1830
|
+
{ cmd: `beehaven batch '{"steps":[{"action":"ticket-list","input":{"limit":10}}]}' --json` },
|
|
1831
|
+
{ cmd: 'beehaven batch @steps.json --json', note: 'read a large payload from a file' },
|
|
1832
|
+
{ cmd: 'cat steps.json | beehaven batch - --json', note: 'read the payload from stdin' },
|
|
1833
|
+
],
|
|
1834
|
+
related: ['call', 'actions', 'code-run'],
|
|
1835
|
+
},
|
|
1836
|
+
'code-run': {
|
|
1837
|
+
synopsis: 'beehaven code-run <file|-> [--json]',
|
|
1838
|
+
description: `Run JavaScript inside the workspace's existing 'code-run'
|
|
1839
|
+
sandbox. Pass a source file as '@script.js', or use '-' to read source
|
|
1840
|
+
from stdin. A JSON object containing 'code' is also accepted when optional
|
|
1841
|
+
'maxCalls' or 'timeoutMs' limits need to be supplied. The sandbox can call
|
|
1842
|
+
workspace actions and return computed data; it is not a shell. This adapter
|
|
1843
|
+
delegates through 'beehaven call', so target routing, agent attribution,
|
|
1844
|
+
policy gates and failure exits stay identical.`,
|
|
1845
|
+
flags: [
|
|
1846
|
+
{ name: '--json', desc: 'Keep stdout machine-readable (suppresses the routing breadcrumb).' },
|
|
1847
|
+
],
|
|
1848
|
+
examples: [
|
|
1849
|
+
{ cmd: 'beehaven code-run @summarize.mjs --json', note: 'run a source file' },
|
|
1850
|
+
{ cmd: 'cat summarize.mjs | beehaven code-run - --json', note: 'run source from stdin' },
|
|
1851
|
+
{ cmd: `beehaven code-run '{"code":"return await clearly.call(\\"workspace-info\\", {})","maxCalls":4}' --json` },
|
|
1852
|
+
],
|
|
1853
|
+
related: ['batch', 'call', 'actions'],
|
|
1854
|
+
},
|
|
1855
|
+
hives: {
|
|
1856
|
+
synopsis: 'beehaven help hives',
|
|
1857
|
+
description: `Local hives — installable apps that run inside the daemon on
|
|
1858
|
+
this machine. Each hive contains one or more buildings (DO-shaped
|
|
1859
|
+
classes) plus optional tray settings + companion window. Examples:
|
|
1860
|
+
recorder (system audio), avatar (mwah desktop companion), memory-cloud
|
|
1861
|
+
(agent memory), elevenlabs (BYOK TTS).
|
|
1862
|
+
|
|
1863
|
+
Mental model:
|
|
1864
|
+
install → add an app to the daemon's tool palette
|
|
1865
|
+
connect → set the active target to that app
|
|
1866
|
+
call → invoke one of its actions
|
|
1867
|
+
uninstall → remove it (drops its tools from the agent surface)
|
|
1868
|
+
|
|
1869
|
+
Local-hive workflow (every install, same four steps):
|
|
1870
|
+
beehaven install <name> # add to ~/.beehaven/apps/
|
|
1871
|
+
beehaven restart # daemon picks up the new building
|
|
1872
|
+
beehaven connect <name> # set active target
|
|
1873
|
+
beehaven actions # see what it exposes
|
|
1874
|
+
beehaven call <action> '{"...":"..."}' # run one
|
|
1875
|
+
|
|
1876
|
+
Hives ship in three lanes:
|
|
1877
|
+
bundled — first-party hives included with the Hive Mac app
|
|
1878
|
+
catalog — published marketplace hives, install by name
|
|
1879
|
+
sideload — local dev .hive archives, install by path (signed) or
|
|
1880
|
+
--allow-unsigned (dev only)
|
|
1881
|
+
|
|
1882
|
+
The daemon is tray-coupled: hives only run while the Hive Mac app is
|
|
1883
|
+
open. Uninstalling makes a hive's actions vanish from the agent's tool
|
|
1884
|
+
palette on the next daemon start — there is no per-action toggle.
|
|
1885
|
+
|
|
1886
|
+
Paired Claude Code skills:
|
|
1887
|
+
A hive can declare \`agentDocs.claudeCode\` in its app.json pointing
|
|
1888
|
+
at a SKILL.md. On install the CLI offers to drop that file under
|
|
1889
|
+
~/.claude/skills/beehaven-<name>/ so Claude Code automatically loads
|
|
1890
|
+
the hive's verb surface as context. Flags: --with-skills (skip the
|
|
1891
|
+
prompt and install) / --no-skills (skip install entirely). Manage
|
|
1892
|
+
via \`beehaven skills <list|sync|remove>\`.
|
|
1893
|
+
|
|
1894
|
+
Reference: docs/LOCAL_HIVES.md (manifest schema, capabilities, dev
|
|
1895
|
+
workflow, sign + publish, agent docs).`,
|
|
1896
|
+
examples: [
|
|
1897
|
+
{ cmd: 'beehaven install memory-cloud', note: 'install by name from catalog' },
|
|
1898
|
+
{ cmd: 'beehaven install ./my-app.hive', note: 'install a signed local archive' },
|
|
1899
|
+
{ cmd: 'beehaven install ./my-app.hive --allow-unsigned', note: 'install a dev build' },
|
|
1900
|
+
{
|
|
1901
|
+
cmd: 'beehaven install ./my-app.hive --with-skills',
|
|
1902
|
+
note: 'install + paired SKILL.md, no prompt',
|
|
1903
|
+
},
|
|
1904
|
+
{ cmd: 'beehaven app list', note: 'see installed + available hives' },
|
|
1905
|
+
{ cmd: 'beehaven app pack .', note: 'build a .hive from cwd (app.json required)' },
|
|
1906
|
+
{ cmd: 'beehaven connect recorder && beehaven actions', note: "inspect a hive's actions" },
|
|
1907
|
+
{ cmd: 'beehaven call record \'{"source":"mic"}\'', note: 'invoke an action once connected' },
|
|
1908
|
+
{ cmd: 'beehaven skills sync', note: 'install paired skills for already-installed hives' },
|
|
1909
|
+
],
|
|
1910
|
+
related: ['app', 'install', 'pack', 'uninstall', 'skills', 'connect', 'call', 'buildings'],
|
|
1911
|
+
},
|
|
1912
|
+
app: {
|
|
1913
|
+
synopsis: 'beehaven app <list|install|pack|uninstall|call|actions|run|setup> [...]',
|
|
1914
|
+
description: `Manage installed hives (apps). All verbs route through the
|
|
1915
|
+
daemon when it's running so the Clearly account stays in sync; offline,
|
|
1916
|
+
list/uninstall fall back to filesystem-only operations under
|
|
1917
|
+
~/.beehaven/apps/.
|
|
1918
|
+
|
|
1919
|
+
Verbs:
|
|
1920
|
+
app list Installed + available from the catalog
|
|
1921
|
+
app install <name|path|url> Add a hive. Names hit the catalog; paths
|
|
1922
|
+
and URLs install local/remote .hive
|
|
1923
|
+
archives (signature required unless
|
|
1924
|
+
--allow-unsigned)
|
|
1925
|
+
app pack <dir> [-o out.hive] Zip <dir> into a .hive archive. Optional
|
|
1926
|
+
--key + --signer for signed releases
|
|
1927
|
+
app uninstall <name> Remove from ~/.beehaven/apps/. Daemon
|
|
1928
|
+
drops the building on next restart
|
|
1929
|
+
app call <building>[/<id>] <action> [json] One-shot action call
|
|
1930
|
+
(escape hatch — prefer connect + call)
|
|
1931
|
+
app actions [<building>] List actions on one building or all
|
|
1932
|
+
registered buildings
|
|
1933
|
+
app run <app>/<recipe> Execute a pipeline recipe an app ships
|
|
1934
|
+
app setup <name> Re-run an app's setup.sh (driver install,
|
|
1935
|
+
model download, etc.)
|
|
1936
|
+
|
|
1937
|
+
The canonical agent workflow is connect + call, not app call. app call
|
|
1938
|
+
exists for scripting and for cases where you don't want to change the
|
|
1939
|
+
active target.`,
|
|
1940
|
+
flags: [
|
|
1941
|
+
{
|
|
1942
|
+
name: '--allow-unsigned',
|
|
1943
|
+
desc: '(install) Accept archives without a .sig file. Dev only.',
|
|
1944
|
+
},
|
|
1945
|
+
{
|
|
1946
|
+
name: '--with-skills',
|
|
1947
|
+
desc: '(install) Install paired Claude Code SKILL.md without prompting.',
|
|
1948
|
+
},
|
|
1949
|
+
{ name: '--no-skills', desc: '(install) Never install paired SKILL.md.' },
|
|
1950
|
+
{ name: '-o, --output <path>', desc: '(pack) Output path. Default: ./<name>-<version>.hive' },
|
|
1951
|
+
{ name: '--key <pem>', desc: '(pack) Ed25519 private key for signing' },
|
|
1952
|
+
{ name: '--signer <id>', desc: '(pack) Signer identifier baked into the .sig envelope' },
|
|
1953
|
+
{ name: '--instance <id>', desc: '(call/actions) Building instance id. Default: live' },
|
|
1954
|
+
{ name: '--timeout <ms>', desc: '(call) Override the 30s default' },
|
|
1955
|
+
{ name: '--json', desc: '(actions) Raw JSON output' },
|
|
1956
|
+
],
|
|
1957
|
+
examples: [
|
|
1958
|
+
{ cmd: 'beehaven app list' },
|
|
1959
|
+
{ cmd: 'beehaven app install mwah', note: 'by name (catalog + cloud sync)' },
|
|
1960
|
+
{ cmd: 'beehaven app install ./build/recorder-0.1.0.hive' },
|
|
1961
|
+
{
|
|
1962
|
+
cmd: 'beehaven app install ./build/my-app.hive --with-skills',
|
|
1963
|
+
note: 'no prompt; install paired SKILL.md',
|
|
1964
|
+
},
|
|
1965
|
+
{ cmd: 'beehaven app pack . -o dist/my-app.hive --key ~/.keys/ed25519.pem --signer my-org' },
|
|
1966
|
+
{ cmd: 'beehaven app actions recorder', note: "see one building's action surface" },
|
|
1967
|
+
{
|
|
1968
|
+
cmd: 'beehaven app call avatar say \'{"text":"hello"}\'',
|
|
1969
|
+
note: 'one-shot, no connect needed',
|
|
1970
|
+
},
|
|
1971
|
+
{ cmd: 'beehaven app run nitepunk-piano/build', note: 'execute a shipped recipe' },
|
|
1972
|
+
{ cmd: 'beehaven app uninstall elevenlabs' },
|
|
1973
|
+
],
|
|
1974
|
+
related: ['hives', 'install', 'pack', 'uninstall', 'skills', 'connect', 'call', 'buildings'],
|
|
1975
|
+
},
|
|
1976
|
+
install: {
|
|
1977
|
+
synopsis: 'beehaven install <name|path|url> [--allow-unsigned] [--with-skills|--no-skills]',
|
|
1978
|
+
description: `Shorthand for \`beehaven app install\`. Three source shapes:
|
|
1979
|
+
|
|
1980
|
+
name — resolves through the catalog (e.g. mwah, ableton, recorder).
|
|
1981
|
+
Requires the daemon to be running (catalog lookup + account
|
|
1982
|
+
sync happen daemon-side). Installs to ~/.beehaven/apps/.
|
|
1983
|
+
path — a local .hive archive (e.g. ./build/my-app.hive). Looks for
|
|
1984
|
+
a sibling .sig file; without one, refuses unless
|
|
1985
|
+
--allow-unsigned is passed.
|
|
1986
|
+
url — http(s) URL to a .hive archive. Best-effort fetches <url>.sig
|
|
1987
|
+
alongside; same signature policy as path installs.
|
|
1988
|
+
|
|
1989
|
+
After install, the daemon needs a restart to pick up new building
|
|
1990
|
+
classes (\`beehaven restart\`, or quit + relaunch the Mac app).
|
|
1991
|
+
|
|
1992
|
+
Signature policy (default-deny): production CLI builds pin
|
|
1993
|
+
trusted-signer public keys. An archive with a missing or invalid
|
|
1994
|
+
signature is refused. Pass --allow-unsigned for local dev builds.
|
|
1995
|
+
|
|
1996
|
+
Paired Claude Code skills: if the hive's app.json declares
|
|
1997
|
+
\`agentDocs.claudeCode\`, the CLI offers to drop that SKILL.md under
|
|
1998
|
+
~/.claude/skills/beehaven-<name>/ for Claude Code to pick up. By
|
|
1999
|
+
default this is INTERACTIVE — you see a preview and confirm. In
|
|
2000
|
+
non-TTY runs (CI) the skill is skipped unless --with-skills is set.
|
|
2001
|
+
--no-skills always skips the prompt and install.`,
|
|
2002
|
+
flags: [
|
|
2003
|
+
{ name: '--allow-unsigned', desc: 'Accept archives without a .sig file. Dev only.' },
|
|
2004
|
+
{ name: '--with-skills', desc: 'Install paired Claude Code SKILL.md without prompting.' },
|
|
2005
|
+
{ name: '--no-skills', desc: 'Never install paired SKILL.md (skip the prompt entirely).' },
|
|
2006
|
+
],
|
|
2007
|
+
examples: [
|
|
2008
|
+
{ cmd: 'beehaven install memory-cloud', note: 'by name from catalog' },
|
|
2009
|
+
{ cmd: 'beehaven install ./build/recorder-0.1.0.hive' },
|
|
2010
|
+
{ cmd: 'beehaven install https://hives.example.com/cool-tool.hive' },
|
|
2011
|
+
{ cmd: 'beehaven install ./my-dev-build.hive --allow-unsigned' },
|
|
2012
|
+
{
|
|
2013
|
+
cmd: 'beehaven install memory-cloud --with-skills',
|
|
2014
|
+
note: 'no prompt; install paired SKILL.md',
|
|
2015
|
+
},
|
|
2016
|
+
{ cmd: 'beehaven install memory-cloud --no-skills', note: 'no prompt; skip SKILL.md' },
|
|
2017
|
+
],
|
|
2018
|
+
related: ['app', 'hives', 'pack', 'uninstall', 'skills', 'connect'],
|
|
2019
|
+
},
|
|
2020
|
+
skills: {
|
|
2021
|
+
synopsis: 'beehaven skills <list|sync|remove> [args]',
|
|
2022
|
+
description: `Manage Claude Code skills paired with installed hives.
|
|
2023
|
+
|
|
2024
|
+
A hive can ship a SKILL.md and reference it from app.json:
|
|
2025
|
+
{ "agentDocs": { "claudeCode": "skills/SKILL.md" } }
|
|
2026
|
+
|
|
2027
|
+
On install, the CLI prompts to drop that file under
|
|
2028
|
+
~/.claude/skills/beehaven-<hive-name>/ so Claude Code auto-loads the
|
|
2029
|
+
hive's verb surface as context. The \`beehaven-\` prefix namespaces
|
|
2030
|
+
these so they're visually identifiable and so this command can mass-
|
|
2031
|
+
manage them without touching your own skills.
|
|
2032
|
+
|
|
2033
|
+
Subcommands:
|
|
2034
|
+
list (default) Show paired skills installed under
|
|
2035
|
+
~/.claude/skills/beehaven-*/, with the
|
|
2036
|
+
owning hive name + version + install date.
|
|
2037
|
+
sync Re-scan ~/.beehaven/apps/ and install any
|
|
2038
|
+
missing paired skills. Honors --with-skills
|
|
2039
|
+
/ --no-skills for non-interactive runs.
|
|
2040
|
+
remove <hive-name> Remove the paired skill for one hive.
|
|
2041
|
+
remove all Remove every beehaven- prefixed skill.
|
|
2042
|
+
|
|
2043
|
+
Each installed skill dir carries a \`.beehaven-source\` marker so this
|
|
2044
|
+
command never deletes a directory it didn't write — your own skills
|
|
2045
|
+
are safe even if you name one \`beehaven-foo\`.
|
|
2046
|
+
|
|
2047
|
+
Trust note: a SKILL.md is essentially injected instructions for
|
|
2048
|
+
Claude. Defaulting to a prompt with preview keeps that explicit.`,
|
|
2049
|
+
flags: [
|
|
2050
|
+
{ name: '--with-skills', desc: '(sync) Install without per-hive prompt' },
|
|
2051
|
+
{ name: '--no-skills', desc: '(sync) Skip every install (effectively a dry-run)' },
|
|
2052
|
+
],
|
|
2053
|
+
examples: [
|
|
2054
|
+
{ cmd: 'beehaven skills', note: 'lists installed paired skills (default subcommand)' },
|
|
2055
|
+
{ cmd: 'beehaven skills sync', note: 'install missing skills for already-installed hives' },
|
|
2056
|
+
{ cmd: 'beehaven skills sync --with-skills', note: 'non-interactive: install everything' },
|
|
2057
|
+
{ cmd: 'beehaven skills remove memory-cloud' },
|
|
2058
|
+
{ cmd: 'beehaven skills remove all', note: 'nuke every beehaven-paired skill' },
|
|
2059
|
+
],
|
|
2060
|
+
related: ['hives', 'install', 'app', 'uninstall'],
|
|
2061
|
+
},
|
|
2062
|
+
pack: {
|
|
2063
|
+
synopsis: 'beehaven app pack <dir> [-o out.hive] [--key <pem>] [--signer <id>]',
|
|
2064
|
+
description: `Build a distributable .hive archive from <dir>. The directory
|
|
2065
|
+
must contain app.json at its root; the manifest is validated before
|
|
2066
|
+
packing — referenced building entries (\`buildings[].entry\`) and
|
|
2067
|
+
frontend dir must exist on disk.
|
|
2068
|
+
|
|
2069
|
+
The archive is a plain zip with app.json + dist/ + ui/ + scripts/ +
|
|
2070
|
+
bundled assets. The build skips node_modules, .git, .DS_Store, .turbo,
|
|
2071
|
+
.cache.
|
|
2072
|
+
|
|
2073
|
+
With --key, also writes <out>.sig — a JSON envelope containing the
|
|
2074
|
+
archive's SHA-256 + an Ed25519 signature by the given signer. The
|
|
2075
|
+
signer id is baked into the envelope; consumers verify against pinned
|
|
2076
|
+
trusted public keys (TRUSTED_SIGNERS in app-signing.ts).
|
|
2077
|
+
|
|
2078
|
+
Output defaults to ./<name>-<version>.hive (from the manifest).`,
|
|
2079
|
+
flags: [
|
|
2080
|
+
{ name: '-o, --output <path>', desc: 'Output path' },
|
|
2081
|
+
{ name: '--key <pem>', desc: 'Ed25519 private key for signing' },
|
|
2082
|
+
{ name: '--signer <id>', desc: 'Signer identifier (default: clearly-release)' },
|
|
2083
|
+
],
|
|
2084
|
+
examples: [
|
|
2085
|
+
{ cmd: 'beehaven app pack .' },
|
|
2086
|
+
{ cmd: 'beehaven app pack ./hives/recorder -o dist/recorder.hive' },
|
|
2087
|
+
{
|
|
2088
|
+
cmd: 'beehaven app pack . --key ~/.keys/ed25519.pem --signer my-org',
|
|
2089
|
+
note: 'signed release',
|
|
2090
|
+
},
|
|
2091
|
+
],
|
|
2092
|
+
related: ['install', 'app', 'hives', 'uninstall'],
|
|
2093
|
+
},
|
|
2094
|
+
uninstall: {
|
|
2095
|
+
synopsis: 'beehaven app uninstall <name>',
|
|
2096
|
+
description: `Remove an installed hive from ~/.beehaven/apps/. Routes
|
|
2097
|
+
through the daemon so the user's Clearly account sees the change;
|
|
2098
|
+
falls back to direct filesystem removal when the daemon is offline
|
|
2099
|
+
(no cloud sync in that case).
|
|
2100
|
+
|
|
2101
|
+
The strip is by name — version suffixes (\`name@1.2.3\`) are accepted
|
|
2102
|
+
but ignored; all matching versions are removed. The in-memory building
|
|
2103
|
+
instance lives until the daemon restarts; until then, calls that
|
|
2104
|
+
target the removed building will keep working against the cached
|
|
2105
|
+
class. Restart to fully drop it.`,
|
|
2106
|
+
examples: [
|
|
2107
|
+
{ cmd: 'beehaven app uninstall elevenlabs' },
|
|
2108
|
+
{
|
|
2109
|
+
cmd: 'beehaven app uninstall recorder@0.1.0',
|
|
2110
|
+
note: 'version suffix ignored — removes all versions',
|
|
2111
|
+
},
|
|
2112
|
+
],
|
|
2113
|
+
related: ['app', 'install', 'hives', 'pack'],
|
|
2114
|
+
},
|
|
2115
|
+
say: {
|
|
2116
|
+
synopsis: 'beehaven say "<text>"',
|
|
2117
|
+
description: `Put words on the character — a card in its transcript lane, readable after it
|
|
2118
|
+
has been said. No model, no Python venv, nothing to install.
|
|
2119
|
+
|
|
2120
|
+
⚠ THIS IS THE ONE THAT WORKS. \`speak\` is deprecated and exits 1; it walked a ladder of four
|
|
2121
|
+
TTS engines, so a failed rung SUBSTITUTED a different voice and the same command sounded like
|
|
2122
|
+
two different products depending on whether a daemon happened to be up. \`say\` has no ladder
|
|
2123
|
+
to fall down.
|
|
2124
|
+
|
|
2125
|
+
⚠ IT NEEDS AN AGENT IDENTITY, like every verb that reaches the workspace — the card is
|
|
2126
|
+
attributed to whoever said it. \`beehaven agent login <name>\` mints one if it is new.`,
|
|
2127
|
+
examples: [
|
|
2128
|
+
{ cmd: 'beehaven say "deploying now"', note: 'appears on the character' },
|
|
2129
|
+
{ cmd: 'beehaven agent login monet && beehaven say "hi"', note: "says it as monet" },
|
|
2130
|
+
],
|
|
2131
|
+
related: ['agent', 'voice', 'speak'],
|
|
2132
|
+
},
|
|
2133
|
+
avatar: {
|
|
2134
|
+
synopsis: 'beehaven [--mood <mood>] [--lifecycle <wake|sleep>] [--emote <reaction> [reason]]',
|
|
2135
|
+
description: 'Drive the active agent avatar from the CLI. Use --mood for a persistent mood, --lifecycle for wake/sleep, and '
|
|
2136
|
+
+ '--emote for a one-shot reaction. An agent identity routes the call to that '
|
|
2137
|
+
+ "agent's own on-screen avatar; without one, it targets the house avatar.\n\n"
|
|
2138
|
+
+ 'Moods: neutral, happy, sad, surprised, angry, confused, curious, flirty. Lifecycles: wake, sleep. '
|
|
2139
|
+
+ 'One-shot reactions: wave, cheer, hearts, laugh, dance, buzz, nod, shake, think, surprise, sleep.\n\n'
|
|
2140
|
+
+ 'An optional --emote reason is capped at 200 characters. MCP equivalents: '
|
|
2141
|
+
+ 'avatar_emote({ emotion }), avatar_react({ reaction, reason? }), and avatar_get_state({}) for the current sticky mood and dynamic PAD mood.',
|
|
2142
|
+
examples: [
|
|
2143
|
+
{ cmd: 'beehaven --mood curious' },
|
|
2144
|
+
{ cmd: 'beehaven --lifecycle sleep', note: 'holds the sleeping lifecycle' },
|
|
2145
|
+
{ cmd: 'beehaven --lifecycle wake', note: 'returns to the awake idle pose' },
|
|
2146
|
+
{ cmd: 'beehaven --emote cheer "tests passed"' },
|
|
2147
|
+
{ cmd: 'beehaven agent login codex && beehaven --emote wave', note: "play it on codex's avatar" },
|
|
2148
|
+
{ cmd: 'beehaven avatar react cheer', note: 'compatibility form' },
|
|
2149
|
+
],
|
|
2150
|
+
related: ['agent', 'say', 'app'],
|
|
2151
|
+
},
|
|
2152
|
+
/**
|
|
2153
|
+
* ⚠ A PAGE FOR `update` EXISTS BECAUSE THE VERB HAS A REFUSAL PATH, and a refusal nobody can
|
|
2154
|
+
* look up reads as the command being broken. Two of the three installs deliberately decline.
|
|
2155
|
+
*/
|
|
2156
|
+
update: {
|
|
2157
|
+
synopsis: 'beehaven update',
|
|
2158
|
+
description: `Update this CLI in place — but only when this CLI is one that updates itself.
|
|
2159
|
+
|
|
2160
|
+
THREE INSTALLS, and only one of them may:
|
|
2161
|
+
|
|
2162
|
+
curl install (~/.beehaven/cli) updates — re-runs the published installer
|
|
2163
|
+
the Mac app bundle REFUSES — the app ships this CLI and updates it
|
|
2164
|
+
Clearly Dev.app bundle REFUSES — rebuild and reinstall the development app
|
|
2165
|
+
a linked dev build REFUSES — that is your working tree
|
|
2166
|
+
|
|
2167
|
+
The Mac app owns its bundled CLI. Its managed wrapper chooses the newer version if a curl
|
|
2168
|
+
install also exists. Updating the bundled copy separately would bypass the app's release and
|
|
2169
|
+
signature checks. A curl install downloads the published manifest and verifies the tarball's
|
|
2170
|
+
sha256 before invoking the installer.
|
|
2171
|
+
|
|
2172
|
+
⚠ IT NEEDS NO AGENT LOGIN. Replacing this binary never opens a workspace, and requiring an
|
|
2173
|
+
identity would refuse the one command a stale install needs.`,
|
|
2174
|
+
examples: [
|
|
2175
|
+
{ cmd: 'beehaven update', note: 'self-update a curl install' },
|
|
2176
|
+
{ cmd: 'beehaven --version', note: 'what you are running, and from where' },
|
|
2177
|
+
],
|
|
2178
|
+
related: ['install', 'doctor', 'status'],
|
|
2179
|
+
},
|
|
2180
|
+
speak: {
|
|
2181
|
+
synopsis: 'beehaven speak "<text>" (deprecated — use `beehaven say`)',
|
|
2182
|
+
description: `⚠ DEPRECATED — this command no longer synthesizes speech. It exits 1
|
|
2183
|
+
and points here.
|
|
2184
|
+
|
|
2185
|
+
Use \`beehaven say "<text>"\` instead. It puts the words on the avatar as a card
|
|
2186
|
+
in its transcript lane: no model, no Python venv, nothing to install, and the
|
|
2187
|
+
text stays readable after it has been said.
|
|
2188
|
+
|
|
2189
|
+
WHY IT WENT. \`speak\` shipped four engines over its life — cloud Kokoro, the
|
|
2190
|
+
workspace's MiniMax clone, the Mac app's Kokoro and macOS \`say\` — walking a
|
|
2191
|
+
ladder between them, which meant a failed rung SUBSTITUTED a different voice and
|
|
2192
|
+
the same command sounded like two different products depending on whether a
|
|
2193
|
+
daemon happened to be up. Cutting it to one on-device engine (Qwen3-TTS under
|
|
2194
|
+
MLX) fixed the substitution and left the real problem:
|
|
2195
|
+
|
|
2196
|
+
• the voice still was not stable — with nothing pinned the model re-draws a
|
|
2197
|
+
speaker on EVERY utterance, so one agent sounded like a different person
|
|
2198
|
+
sentence to sentence;
|
|
2199
|
+
• pinning it meant deriving a speaker per identity from the THREE presets
|
|
2200
|
+
measured usable out of nine (the other six generate for minutes on a
|
|
2201
|
+
six-second sentence);
|
|
2202
|
+
• and it needed a ~2 minute install and a Python venv before it could say a
|
|
2203
|
+
single word, for a command whose job is a one-line status ping.
|
|
2204
|
+
|
|
2205
|
+
\`beehaven voice *\` still exists and still clones voices, but it configured this
|
|
2206
|
+
command and nothing else now calls it.`,
|
|
2207
|
+
flags: [],
|
|
2208
|
+
examples: [
|
|
2209
|
+
{ cmd: 'beehaven say "build is green"', note: 'the replacement' },
|
|
2210
|
+
],
|
|
2211
|
+
related: ['say', 'voice', 'agent'],
|
|
2212
|
+
},
|
|
2213
|
+
voice: {
|
|
2214
|
+
synopsis: 'beehaven voice [status|provider|setup|clone|list|use|remove|test]',
|
|
2215
|
+
description: `Choose how \`beehaven speak\` makes sound, and manage locally CLONED
|
|
2216
|
+
voices. A bare \`beehaven voice\` (no subcommand) is the push-to-talk REPL:
|
|
2217
|
+
record → transcribe → ask the connected DO → speak the reply.
|
|
2218
|
+
|
|
2219
|
+
status active provider + voice, runtime state
|
|
2220
|
+
provider [<name>] show or set the TTS provider (persisted)
|
|
2221
|
+
setup install the local Qwen3-TTS (MLX) runtime
|
|
2222
|
+
clone <name> <audio> clone a voice from a recording
|
|
2223
|
+
list cloned voices
|
|
2224
|
+
use <name> which cloned voice speak uses (\`none\` clears)
|
|
2225
|
+
remove <name> forget a cloned voice
|
|
2226
|
+
test ["text"] synthesize + play a sample
|
|
2227
|
+
|
|
2228
|
+
CLONING runs entirely on this machine (Apple Silicon only) via Qwen3-TTS
|
|
2229
|
+
under MLX — no relay, no API key, no audio leaves the box. 3-30 seconds of
|
|
2230
|
+
clean single-speaker reference is plenty. Qwen3 clones by in-context
|
|
2231
|
+
learning, so it needs the recording AND its transcript; \`clone\` transcribes
|
|
2232
|
+
once with whisper and stores the result, so synthesis never loads an STT
|
|
2233
|
+
model again. Pass \`--ref-text\` to skip transcription.
|
|
2234
|
+
|
|
2235
|
+
The provider + voice persist in ~/.beehaven/config.json (speak is one
|
|
2236
|
+
process per utterance, so an exported env var wouldn't survive).`,
|
|
2237
|
+
flags: [
|
|
2238
|
+
{ name: '--ref-text "<text>"', desc: 'clone: supply the transcript, skip whisper' },
|
|
2239
|
+
{ name: '--force', desc: 'clone: overwrite an existing voice of that name' },
|
|
2240
|
+
{ name: '--tts-voice <name>', desc: 'test: one-shot voice override' },
|
|
2241
|
+
{ name: 'BEEHAVEN_TTS_PROVIDER', desc: 'Env override for the provider flag' },
|
|
2242
|
+
{ name: 'BEEHAVEN_TTS_VOICE', desc: 'Env override for the cloned voice' },
|
|
2243
|
+
{ name: 'BEEHAVEN_QWEN3_TTS_MODEL', desc: 'Env: a different Qwen3-TTS -Base checkpoint' },
|
|
2244
|
+
],
|
|
2245
|
+
examples: [
|
|
2246
|
+
{ cmd: 'beehaven voice setup', note: 'one-time: install mlx-audio' },
|
|
2247
|
+
{ cmd: 'beehaven voice clone cove ~/Downloads/cove_export.mp3' },
|
|
2248
|
+
{ cmd: 'beehaven voice use cove && beehaven voice provider qwen3-mlx' },
|
|
2249
|
+
{ cmd: 'beehaven voice test "hello from the hive"' },
|
|
2250
|
+
{ cmd: 'beehaven voice status' },
|
|
2251
|
+
],
|
|
2252
|
+
related: ['speak', 'status', 'app'],
|
|
2253
|
+
},
|
|
2254
|
+
};
|
|
2255
|
+
// Aliases — same page, different lookup name.
|
|
2256
|
+
const ALIASES = {
|
|
2257
|
+
tts: 'voice',
|
|
2258
|
+
connect: 'cd',
|
|
2259
|
+
nav: 'cd',
|
|
2260
|
+
navigate: 'cd',
|
|
2261
|
+
where: 'pwd',
|
|
2262
|
+
// ⚠ `find` IS DELIBERATELY NOT AN ALIAS OF `search` — it has its own page.
|
|
2263
|
+
// It used to be listed here, so `help find` rendered the search page while
|
|
2264
|
+
// dispatch ran POSIX find; see the block above the `find` page for why the
|
|
2265
|
+
// claim was removed rather than the behaviour changed.
|
|
2266
|
+
ask: 'agent',
|
|
2267
|
+
get: 'cat',
|
|
2268
|
+
describe: 'explain',
|
|
2269
|
+
hive: 'hives',
|
|
2270
|
+
apps: 'app',
|
|
2271
|
+
comp: 'composition',
|
|
2272
|
+
// `unlink` is the same job as `link`, undone — one page covers both.
|
|
2273
|
+
unlink: 'link',
|
|
2274
|
+
// SS-41 — reading a thread is the other half of posting one; `mentions` is the plural people type.
|
|
2275
|
+
comments: 'comment',
|
|
2276
|
+
mentions: 'mention',
|
|
2277
|
+
};
|
|
2278
|
+
// ── Render ──────────────────────────────────────────────────────────────
|
|
2279
|
+
/**
|
|
2280
|
+
* Does this verb have a deep-help page? Exported so `cli.ts` can route `<verb> --help` here —
|
|
2281
|
+
* the pages already existed and were reachable only via `beehaven help <verb>`, i.e. not by the
|
|
2282
|
+
* flag every CLI trains you to type. Returns false for an unknown verb so the caller can fall
|
|
2283
|
+
* back to the global help rather than printing nothing.
|
|
2284
|
+
*/
|
|
2285
|
+
export function hasHelpPage(command) {
|
|
2286
|
+
if (!command)
|
|
2287
|
+
return false;
|
|
2288
|
+
const canonical = ALIASES[command] ?? command;
|
|
2289
|
+
return !HIDDEN_PUBLIC_COMMANDS.has(canonical) && !!PAGES[canonical];
|
|
2290
|
+
}
|
|
2291
|
+
/** Print one verb's deep-help page. Precondition: `hasHelpPage(command)`. */
|
|
2292
|
+
export function printHelpPage(command) {
|
|
2293
|
+
cmdHelp(command);
|
|
2294
|
+
}
|
|
2295
|
+
export function cmdHelp(command) {
|
|
2296
|
+
if (!command) {
|
|
2297
|
+
printHelpIndex();
|
|
2298
|
+
return;
|
|
2299
|
+
}
|
|
2300
|
+
const canonical = ALIASES[command] ?? command;
|
|
2301
|
+
if (HIDDEN_PUBLIC_COMMANDS.has(canonical)) {
|
|
2302
|
+
console.error(`beehaven ${canonical} is temporarily unavailable.`);
|
|
2303
|
+
process.exit(1);
|
|
2304
|
+
}
|
|
2305
|
+
const page = PAGES[canonical];
|
|
2306
|
+
if (!page) {
|
|
2307
|
+
/**
|
|
2308
|
+
* ⚠ A BUILDING ADDRESS IS NOT A MISTYPED VERB — CLR-1150. `cli.ts` implements a rich
|
|
2309
|
+
* `beehaven help shopifyStore/clearly-demo` that fetches the DO's live action list, and
|
|
2310
|
+
* it is UNREACHABLE: the intercept in `cli.ts` routes every `help <x>` here before the
|
|
2311
|
+
* switch can see it. Rather than duplicate that fetch, recognise the shape and name the
|
|
2312
|
+
* command that does the job.
|
|
2313
|
+
*/
|
|
2314
|
+
if (command.includes('/')) {
|
|
2315
|
+
console.error(`"${command}" looks like a building address, not a command.`);
|
|
2316
|
+
console.error('');
|
|
2317
|
+
console.error(' To see what a building exposes, connect and list its actions:');
|
|
2318
|
+
console.error(` beehaven connect ${command}`);
|
|
2319
|
+
console.error(' beehaven actions');
|
|
2320
|
+
console.error('');
|
|
2321
|
+
process.exit(1);
|
|
2322
|
+
}
|
|
2323
|
+
console.error(`No help page for "${command}".`);
|
|
2324
|
+
/**
|
|
2325
|
+
* ⚠ Suggest a NEAR MATCH before dumping 50 page names. The top-level unknown-command
|
|
2326
|
+
* handler guesses the wrong axis entirely — it treats an unrecognised word as a
|
|
2327
|
+
* building TYPE — so a plain typo has never been answered with the obvious correction.
|
|
2328
|
+
*/
|
|
2329
|
+
const near = Object.keys(PAGES)
|
|
2330
|
+
.map((n) => ({ n, d: editDistance(command, n) }))
|
|
2331
|
+
.filter((x) => x.d <= 3)
|
|
2332
|
+
.sort((a, b) => a.d - b.d)
|
|
2333
|
+
.slice(0, 3)
|
|
2334
|
+
.map((x) => x.n);
|
|
2335
|
+
if (near.length) {
|
|
2336
|
+
console.error('');
|
|
2337
|
+
console.error(`Did you mean: ${near.join(', ')}?`);
|
|
2338
|
+
}
|
|
2339
|
+
console.error('');
|
|
2340
|
+
console.error('Available pages:');
|
|
2341
|
+
const names = Object.keys(PAGES).filter((name) => !HIDDEN_PUBLIC_COMMANDS.has(name)).sort();
|
|
2342
|
+
const cols = 4;
|
|
2343
|
+
for (let i = 0; i < names.length; i += cols) {
|
|
2344
|
+
console.error(' ' +
|
|
2345
|
+
names
|
|
2346
|
+
.slice(i, i + cols)
|
|
2347
|
+
.map((n) => n.padEnd(14))
|
|
2348
|
+
.join(''));
|
|
2349
|
+
}
|
|
2350
|
+
console.error('');
|
|
2351
|
+
console.error('See also: beehaven --help (top-level overview)');
|
|
2352
|
+
process.exit(1);
|
|
2353
|
+
}
|
|
2354
|
+
console.log('');
|
|
2355
|
+
console.log(` ${bold(page.synopsis)}`);
|
|
2356
|
+
console.log('');
|
|
2357
|
+
console.log(indent(page.description));
|
|
2358
|
+
console.log('');
|
|
2359
|
+
if (page.flags && page.flags.length > 0) {
|
|
2360
|
+
console.log(` ${bold('Flags')}`);
|
|
2361
|
+
const maxW = Math.max(...page.flags.map((f) => f.name.length));
|
|
2362
|
+
for (const f of page.flags) {
|
|
2363
|
+
console.log(` ${f.name.padEnd(maxW + 2)} ${f.desc}`);
|
|
2364
|
+
}
|
|
2365
|
+
console.log('');
|
|
2366
|
+
}
|
|
2367
|
+
if (page.examples && page.examples.length > 0) {
|
|
2368
|
+
console.log(` ${bold('Examples')}`);
|
|
2369
|
+
for (const ex of page.examples) {
|
|
2370
|
+
console.log(` ${ex.cmd}`);
|
|
2371
|
+
if (ex.note)
|
|
2372
|
+
console.log(` ${dim('# ' + ex.note)}`);
|
|
2373
|
+
}
|
|
2374
|
+
console.log('');
|
|
2375
|
+
}
|
|
2376
|
+
console.log(` ${bold('Related')}`);
|
|
2377
|
+
console.log(` ${page.related.map((r) => `beehaven help ${r}`).join(' · ')}`);
|
|
2378
|
+
console.log('');
|
|
2379
|
+
}
|
|
2380
|
+
function printHelpIndex() {
|
|
2381
|
+
console.log('');
|
|
2382
|
+
console.log(` ${bold('beehaven help <command>')}`);
|
|
2383
|
+
console.log(` ${dim('Deep help for a single command. Agents: call this before running anything unfamiliar.')}`);
|
|
2384
|
+
console.log('');
|
|
2385
|
+
const names = Object.keys(PAGES).filter((name) => !HIDDEN_PUBLIC_COMMANDS.has(name)).sort();
|
|
2386
|
+
console.log(` ${bold('Pages')}`);
|
|
2387
|
+
const cols = 4;
|
|
2388
|
+
for (let i = 0; i < names.length; i += cols) {
|
|
2389
|
+
console.log(' ' +
|
|
2390
|
+
names
|
|
2391
|
+
.slice(i, i + cols)
|
|
2392
|
+
.map((n) => n.padEnd(14))
|
|
2393
|
+
.join(''));
|
|
2394
|
+
}
|
|
2395
|
+
console.log('');
|
|
2396
|
+
console.log(` ${bold('Aliases')}`);
|
|
2397
|
+
const aliasLines = Object.entries(ALIASES).map(([a, c]) => ` ${a.padEnd(10)} → ${c}`);
|
|
2398
|
+
for (const line of aliasLines)
|
|
2399
|
+
console.log(line);
|
|
2400
|
+
console.log('');
|
|
2401
|
+
console.log(` ${dim('See also: beehaven --help (top-level surface)')}`);
|
|
2402
|
+
console.log('');
|
|
2403
|
+
}
|
|
2404
|
+
// ── Format helpers ──────────────────────────────────────────────────────
|
|
2405
|
+
function bold(s) {
|
|
2406
|
+
return `\x1b[1m${s}\x1b[0m`;
|
|
2407
|
+
}
|
|
2408
|
+
function dim(s) {
|
|
2409
|
+
return `\x1b[2m${s}\x1b[0m`;
|
|
2410
|
+
}
|
|
2411
|
+
function indent(s) {
|
|
2412
|
+
return s
|
|
2413
|
+
.split('\n')
|
|
2414
|
+
.map((l) => ' ' + l.trim())
|
|
2415
|
+
.join('\n');
|
|
2416
|
+
}
|
|
2417
|
+
// Exposed for tests — avoids cross-file spelunking.
|
|
2418
|
+
export const __testing = { PAGES, ALIASES };
|