@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.
Files changed (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +201 -0
  3. package/dist/__tests__/_cli-switch.js +105 -0
  4. package/dist/__tests__/agent-wrap-probe.js +136 -0
  5. package/dist/agent-attribution.js +192 -0
  6. package/dist/agent-identity-daemon.js +135 -0
  7. package/dist/agent-onboard.js +156 -0
  8. package/dist/agent-scope.js +79 -0
  9. package/dist/agent-sessions.js +370 -0
  10. package/dist/agent-state.js +482 -0
  11. package/dist/app-manifest.js +221 -0
  12. package/dist/app-signer.js +54 -0
  13. package/dist/app-signing.js +127 -0
  14. package/dist/audio-play.js +98 -0
  15. package/dist/avatar-protocol.js +25 -0
  16. package/dist/avatar-route.js +79 -0
  17. package/dist/bee/cloud-proxy.js +130 -0
  18. package/dist/blocked-actions.js +120 -0
  19. package/dist/build-channel.js +101 -0
  20. package/dist/buildings/daemon-workspace.js +475 -0
  21. package/dist/claude-bridge.js +310 -0
  22. package/dist/claude-credential-store.js +633 -0
  23. package/dist/clearly-sync.js +518 -0
  24. package/dist/clearly.js +616 -0
  25. package/dist/cli-state.js +334 -0
  26. package/dist/cli.js +6973 -0
  27. package/dist/commands/agent-skills.js +302 -0
  28. package/dist/commands/agent.js +1310 -0
  29. package/dist/commands/app.js +1123 -0
  30. package/dist/commands/auth.js +171 -0
  31. package/dist/commands/building-shell.js +392 -0
  32. package/dist/commands/canvas.js +932 -0
  33. package/dist/commands/claude.js +218 -0
  34. package/dist/commands/compliance.js +387 -0
  35. package/dist/commands/compose.js +507 -0
  36. package/dist/commands/composition.js +95 -0
  37. package/dist/commands/connect-session.js +409 -0
  38. package/dist/commands/conversations.js +160 -0
  39. package/dist/commands/costs.js +443 -0
  40. package/dist/commands/d1.js +253 -0
  41. package/dist/commands/daemon-cmd.js +162 -0
  42. package/dist/commands/deploy.js +164 -0
  43. package/dist/commands/design.js +617 -0
  44. package/dist/commands/dev-generate.js +125 -0
  45. package/dist/commands/dev.js +109 -0
  46. package/dist/commands/devices.js +135 -0
  47. package/dist/commands/explain-router.js +24 -0
  48. package/dist/commands/explain.js +882 -0
  49. package/dist/commands/explore.js +264 -0
  50. package/dist/commands/help.js +2418 -0
  51. package/dist/commands/init.js +408 -0
  52. package/dist/commands/install.js +129 -0
  53. package/dist/commands/library.js +229 -0
  54. package/dist/commands/marketplace.js +138 -0
  55. package/dist/commands/mcp-install.js +476 -0
  56. package/dist/commands/mention.js +257 -0
  57. package/dist/commands/omni.js +529 -0
  58. package/dist/commands/secrets.js +323 -0
  59. package/dist/commands/self-update.js +206 -0
  60. package/dist/commands/sheet.js +264 -0
  61. package/dist/commands/shell-output.js +309 -0
  62. package/dist/commands/shell.js +1048 -0
  63. package/dist/commands/shop.js +368 -0
  64. package/dist/commands/skills.js +311 -0
  65. package/dist/commands/slides.js +418 -0
  66. package/dist/commands/swarm.js +341 -0
  67. package/dist/commands/ticket.js +1301 -0
  68. package/dist/commands/tool.js +312 -0
  69. package/dist/commands/trash.js +106 -0
  70. package/dist/commands/treehouse.js +120 -0
  71. package/dist/commands/user.js +240 -0
  72. package/dist/commands/voice-tts.js +319 -0
  73. package/dist/commands/voice.js +166 -0
  74. package/dist/commands/watch-git.js +401 -0
  75. package/dist/commands/webhook.js +159 -0
  76. package/dist/commands/workspace.js +3354 -0
  77. package/dist/composition-repos.js +91 -0
  78. package/dist/daemon-avatar.js +130 -0
  79. package/dist/daemon-claude-code-auto-install.js +52 -0
  80. package/dist/daemon-client.js +363 -0
  81. package/dist/daemon-codex.js +349 -0
  82. package/dist/daemon-entry.js +101 -0
  83. package/dist/daemon-fetch-allowlist.js +194 -0
  84. package/dist/daemon-gemini.js +224 -0
  85. package/dist/daemon-mcp-clearly.js +353 -0
  86. package/dist/daemon-mcp-sandbox.js +127 -0
  87. package/dist/daemon-omni-company.js +338 -0
  88. package/dist/daemon-omni-hooks.js +375 -0
  89. package/dist/daemon-omni-identity.js +229 -0
  90. package/dist/daemon-omni-pipeline.js +251 -0
  91. package/dist/daemon-omni-policies.js +346 -0
  92. package/dist/daemon-omni-principal.js +580 -0
  93. package/dist/daemon-omni-tool-gate.js +116 -0
  94. package/dist/daemon-omni.js +1442 -0
  95. package/dist/daemon-path-transform.js +120 -0
  96. package/dist/daemon-write-sandbox.js +191 -0
  97. package/dist/daemon.js +4471 -0
  98. package/dist/dashboard.js +846 -0
  99. package/dist/dep-installer.js +286 -0
  100. package/dist/dev-mode.js +67 -0
  101. package/dist/doc-indexer.js +169 -0
  102. package/dist/e2e-crypto.js +94 -0
  103. package/dist/feature-flags.js +154 -0
  104. package/dist/file-browser.js +88 -0
  105. package/dist/first-party-hives.js +211 -0
  106. package/dist/folder-sync.js +226 -0
  107. package/dist/health.js +56 -0
  108. package/dist/ipc-auth.js +299 -0
  109. package/dist/ipc-client.js +495 -0
  110. package/dist/ipc-server.js +684 -0
  111. package/dist/keychain.js +224 -0
  112. package/dist/lib/admin-client.js +73 -0
  113. package/dist/lib/mobile-build-parser.js +156 -0
  114. package/dist/local-app-manager.js +660 -0
  115. package/dist/log-redaction.js +89 -0
  116. package/dist/logger.js +108 -0
  117. package/dist/manifest.js +143 -0
  118. package/dist/marketplace.js +793 -0
  119. package/dist/min-version-copy.js +51 -0
  120. package/dist/min-version.js +214 -0
  121. package/dist/public-surface.js +23 -0
  122. package/dist/relay-presets.js +89 -0
  123. package/dist/relay.js +2723 -0
  124. package/dist/repl.js +619 -0
  125. package/dist/setup-relay.js +363 -0
  126. package/dist/setup-service.js +536 -0
  127. package/dist/shared/bee-memory/index.js +6 -0
  128. package/dist/shared/bee-memory/types.js +682 -0
  129. package/dist/shared/claude-code/daemon-types.js +112 -0
  130. package/dist/shared/claude-code/index.js +2 -0
  131. package/dist/shared/claude-code/types.js +1 -0
  132. package/dist/shared/status/schema.js +133 -0
  133. package/dist/shell-session.js +198 -0
  134. package/dist/speak-lock.js +97 -0
  135. package/dist/spinner.js +57 -0
  136. package/dist/telemetry.js +166 -0
  137. package/dist/terminal/block-parser.js +207 -0
  138. package/dist/terminal/shell-integration.js +108 -0
  139. package/dist/transcript-tailer.js +215 -0
  140. package/dist/tts-qwen3.js +547 -0
  141. package/dist/types.js +4 -0
  142. package/dist/utm.js +38 -0
  143. package/dist/verb-surface.js +331 -0
  144. package/dist/version-utils.js +85 -0
  145. package/dist/watcher.js +207 -0
  146. package/package.json +88 -0
  147. package/python/qwen3_tts.py +230 -0
  148. package/scripts/stamp-build-channel.mjs +115 -0
  149. package/scripts/sync-installed.mjs +159 -0
  150. package/scripts/sync-skills.mjs +112 -0
  151. package/skills/README.md +24 -0
  152. package/skills/agent-doodle-space/SKILL.md +118 -0
  153. package/skills/agent-home/SKILL.md +98 -0
  154. package/skills/beehaven-cli/SKILL.md +144 -0
  155. package/skills/claude-shopper/README.md +90 -0
  156. package/skills/claude-shopper/SKILL.md +151 -0
  157. package/skills/clearly-agent/SKILL.md +183 -0
  158. package/skills/clearly-canvas/SKILL.md +222 -0
  159. package/skills/clearly-canvas/authoring.md +160 -0
  160. package/skills/clearly-canvas/communications.md +32 -0
  161. package/skills/clearly-canvas/composition-patterns.md +84 -0
  162. package/skills/clearly-canvas/example.mjs +78 -0
  163. package/skills/clearly-canvas/project-plans.md +156 -0
  164. package/skills/clearly-canvas/review.mjs +68 -0
  165. package/skills/clearly-workspace/SKILL.md +79 -0
  166. package/skills/clearly-workspace/survey.mjs +101 -0
  167. package/skills/codebase-map/SKILL.md +142 -0
  168. package/skills/design-craft/SKILL.md +300 -0
  169. package/skills/index.json +79 -0
  170. package/skills/layout-systems/SKILL.md +184 -0
  171. package/skills/pair-on-canvas/SKILL.md +92 -0
@@ -0,0 +1,302 @@
1
+ /**
2
+ * agent-skills — install the shipped Clearly SKILL.md files into every agent's home.
3
+ *
4
+ * ⚠⚠ THIS IS THE OTHER HALF OF "just install the CLI". `mcp install` gives an agent the TOOLS;
5
+ * this gives it the instructions for using them well. The Mac app has installed both on every
6
+ * launch for a while; the CLI installed neither, so a headless or Linux user got a bare tool list
7
+ * and no guidance.
8
+ *
9
+ * ⚠ NOT THE SAME AS `beehaven skills` (hive-paired skills). That command manages SKILL.md files
10
+ * that ship WITH an installed hive, and writes only to `~/.claude/skills`. These five are the
11
+ * product's own, they ship in this package, and they go to every agent home.
12
+ *
13
+ * ⚠ A SYMLINKED SKILL IS LEFT ALONE, IN BOTH DIRECTIONS. A developer who links a skill to iterate
14
+ * on it has made a deliberate statement — the repo owns that file. Writing through the symlink
15
+ * would silently EDIT THEIR CHECKOUT (`writeFileSync` follows links), and removing it would break
16
+ * the loop it was created for. Same rule the Mac app's installer follows.
17
+ */
18
+ import fs from 'fs';
19
+ import os from 'os';
20
+ import path from 'path';
21
+ import crypto from 'crypto';
22
+ import { fileURLToPath } from 'url';
23
+ /**
24
+ * Where each agent looks for skills.
25
+ *
26
+ * ⚠ `~/.agents/skills` is the SHARED, cross-agent location and takes precedence over the per-agent
27
+ * directories for the agents that read it. The per-agent homes are kept because not every agent
28
+ * does.
29
+ */
30
+ export const AGENT_SKILL_DIRS = [
31
+ { agent: 'shared', dir: path.join(os.homedir(), '.agents', 'skills') },
32
+ { agent: 'claude', dir: path.join(os.homedir(), '.claude', 'skills') },
33
+ { agent: 'codex', dir: path.join(os.homedir(), '.codex', 'skills') },
34
+ { agent: 'gemini', dir: path.join(os.homedir(), '.gemini', 'skills') },
35
+ { agent: 'pi', dir: path.join(os.homedir(), '.pi', 'agent', 'skills') },
36
+ ];
37
+ /** Where this package's copies live — written by `scripts/sync-skills.mjs` at build time. */
38
+ function skillSourceDir() {
39
+ // dist/commands/agent-skills.js → ../../skills
40
+ return path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', 'skills');
41
+ }
42
+ /**
43
+ * The shipped manifest.
44
+ *
45
+ * ⚠⚠ ACCEPTS BOTH SHAPES, IN BOTH DIRECTIONS. `index.json` was a bare `string[]` and is now
46
+ * `{name, files, sha}[]`. A CLI and its bundled skills travel together in one tarball, but a
47
+ * DEVELOPER checkout mixes them constantly — a rebuilt `dist/` against an unsynced `skills/`, or
48
+ * the reverse — and a manifest reader that handles only one shape turns that into a failed install
49
+ * with no skills at all. Reading both costs one `typeof`.
50
+ */
51
+ export function shippedManifest() {
52
+ try {
53
+ const raw = JSON.parse(fs.readFileSync(path.join(skillSourceDir(), 'index.json'), 'utf8'));
54
+ if (!Array.isArray(raw))
55
+ return [];
56
+ return raw.map((e) => (typeof e === 'string' ? { name: e } : e)).filter((e) => e?.name);
57
+ }
58
+ catch {
59
+ return [];
60
+ }
61
+ }
62
+ /** Names only — the old signature, kept so existing callers do not move. */
63
+ export function shippedSkills() {
64
+ return shippedManifest().map((s) => s.name);
65
+ }
66
+ /**
67
+ * Has the user edited this installed skill?
68
+ *
69
+ * ⚠⚠ THE POINT IS TO STOP OVERWRITING SOMEBODY'S WORK IN SILENCE. The installer compared content
70
+ * and wrote whenever it differed, which cannot tell "stale, update it" from "the user changed it,
71
+ * leave it alone" — those are opposite instructions and both look like `existing !== desired`.
72
+ *
73
+ * The `.beehaven-skill` stamp records the sha that was INSTALLED. On the next run:
74
+ * · on-disk matches the stamp ⇒ untouched, safe to update
75
+ * · on-disk differs from the stamp ⇒ the user edited it, skip and say so
76
+ * · no stamp (hand-placed, or older) ⇒ treated as untouched, because assuming an edit would
77
+ * freeze every skill installed before stamping existed and updates would never land again
78
+ */
79
+ function localSha(destDir, files) {
80
+ const h = crypto.createHash('sha256');
81
+ for (const f of files.slice().sort()) {
82
+ h.update(f);
83
+ try {
84
+ h.update(fs.readFileSync(path.join(destDir, f)));
85
+ }
86
+ catch {
87
+ h.update('\0missing');
88
+ }
89
+ }
90
+ return h.digest('hex').slice(0, 16);
91
+ }
92
+ /**
93
+ * Install a skill's SIBLING FILES — the scripts and data that make it more than prose.
94
+ *
95
+ * ⚠⚠ THE INSTALLER CARRIED EXACTLY ONE FILE PER SKILL, so a skill could only ever BE prose. That
96
+ * is a ceiling, not an oversight to route around: the two most reliable skills in this product
97
+ * (`growth-report`, `rank-report`) work because they ship `.mjs` files which collapse a dozen
98
+ * fragile commands into one, and neither could be distributed through this path. A prose skill
99
+ * tells the model to run twelve commands and it drifts on all twelve.
100
+ *
101
+ * ⚠ EXECUTABLE BIT ON `.mjs`/`.sh`, because a skill that documents `node x.mjs` still works
102
+ * without it but one that documents `./x.sh` does not — and the failure is a permission error the
103
+ * model cannot diagnose.
104
+ *
105
+ * ⚠ NEVER FATAL. A skill whose script fails to copy is a degraded skill; a throw here would abort
106
+ * the install of every remaining skill for every remaining agent home.
107
+ */
108
+ /**
109
+ * Copies a skill's non-SKILL.md files (scripts, data) and RETURNS HOW MANY IT WROTE.
110
+ *
111
+ * ⚠⚠ THE COUNT IS NOT BOOKKEEPING — WITHOUT IT A SCRIPT-ONLY UPDATE REPORTED `current`. The caller
112
+ * decides `current` vs `updated` by comparing SKILL.md alone, so a skill whose SKILL.md is
113
+ * byte-identical and whose `survey.mjs` was rewritten landed the new script and told the operator
114
+ * nothing happened. Verified live before the fix: probe appended to `survey.mjs` → the installed
115
+ * copy contained it → every step still said `current`. Silent success is the same shape as silent
116
+ * failure to anyone reading the output, and a scripted skill is exactly where that matters.
117
+ */
118
+ function installExtras(srcDir, name, destDir, warnings) {
119
+ const from = path.join(srcDir, name);
120
+ let wrote = 0;
121
+ let files = [];
122
+ try {
123
+ files = fs.readdirSync(from);
124
+ }
125
+ catch {
126
+ return 0;
127
+ }
128
+ for (const f of files) {
129
+ if (f === 'SKILL.md')
130
+ continue;
131
+ try {
132
+ const s = path.join(from, f);
133
+ if (!fs.statSync(s).isFile())
134
+ continue;
135
+ const d = path.join(destDir, f);
136
+ // ⚠ A symlinked extra is left alone, exactly as a symlinked SKILL.md is — same reasoning.
137
+ try {
138
+ if (fs.lstatSync(d).isSymbolicLink())
139
+ continue;
140
+ }
141
+ catch { /* absent */ }
142
+ const body = fs.readFileSync(s);
143
+ let existing = null;
144
+ try {
145
+ existing = fs.readFileSync(d);
146
+ }
147
+ catch { /* not installed */ }
148
+ if (existing && existing.equals(body))
149
+ continue;
150
+ fs.mkdirSync(destDir, { recursive: true, mode: 0o755 });
151
+ fs.writeFileSync(d, body, { mode: /\.(mjs|js|sh)$/.test(f) ? 0o755 : 0o644 });
152
+ wrote++;
153
+ }
154
+ catch (e) {
155
+ warnings.push(`${name}/${f}: ${e?.message ?? String(e)}`);
156
+ }
157
+ }
158
+ return wrote;
159
+ }
160
+ /** Filename of the install stamp. ⚠ Dot-prefixed so it never reads as part of the skill. */
161
+ const STAMP = '.beehaven-skill';
162
+ /**
163
+ * Record what was installed, so the NEXT run can tell a stale copy from an edited one.
164
+ *
165
+ * ⚠ WRITTEN AFTER THE FILES, ALWAYS. Stamped first, a failed copy leaves a stamp claiming content
166
+ * that is not there — and the next run then reads the mismatch as a user edit and refuses to fix
167
+ * it. That is a self-inflicted permanent freeze.
168
+ *
169
+ * ⚠ NON-FATAL. An unstampable skill degrades to the old always-overwrite behaviour, which is what
170
+ * every skill did until now.
171
+ */
172
+ function stamp(destDir, files, warnings) {
173
+ try {
174
+ fs.writeFileSync(path.join(destDir, STAMP), JSON.stringify({ sha: localSha(destDir, files), files, at: new Date().toISOString() }, null, 2), { mode: 0o644 });
175
+ }
176
+ catch (e) {
177
+ warnings.push(`stamp ${destDir}: ${e?.message ?? String(e)}`);
178
+ }
179
+ }
180
+ export function installAgentSkills() {
181
+ const steps = [];
182
+ const warnings = [];
183
+ const srcDir = skillSourceDir();
184
+ const names = shippedSkills();
185
+ if (!names.length) {
186
+ warnings.push(`no skills bundled in this build (${srcDir}) — run scripts/sync-skills.mjs before packing`);
187
+ return { steps, warnings };
188
+ }
189
+ const manifest = shippedManifest();
190
+ for (const name of names) {
191
+ const entry = manifest.find((m) => m.name === name);
192
+ /** Every file this skill ships — used for the stamp, so a script change counts as a change. */
193
+ const skillFiles = entry?.files?.length ? entry.files : ['SKILL.md'];
194
+ const src = path.join(srcDir, name, 'SKILL.md');
195
+ if (!fs.existsSync(src)) {
196
+ warnings.push(`source missing: ${name}`);
197
+ continue;
198
+ }
199
+ const desired = fs.readFileSync(src, 'utf8');
200
+ for (const { agent, dir } of AGENT_SKILL_DIRS) {
201
+ const destDir = path.join(dir, name);
202
+ const dest = path.join(destDir, 'SKILL.md');
203
+ try {
204
+ /**
205
+ * ⚠ ONLY INTO A HOME THAT EXISTS. Creating `~/.gemini/skills` on a machine with no Gemini
206
+ * scatters directories for software the user does not run.
207
+ */
208
+ if (!fs.existsSync(dir) && !fs.existsSync(path.dirname(dir))) {
209
+ continue;
210
+ }
211
+ let link = null;
212
+ try {
213
+ if (fs.lstatSync(dest).isSymbolicLink())
214
+ link = fs.readlinkSync(dest);
215
+ }
216
+ catch { /* absent */ }
217
+ if (link) {
218
+ warnings.push(`${agent}/${name}: symlink → ${link} (left alone)`);
219
+ steps.push(`${agent}/${name}=symlink-skipped`);
220
+ continue;
221
+ }
222
+ let existing = '';
223
+ try {
224
+ existing = fs.readFileSync(dest, 'utf8');
225
+ }
226
+ catch { /* not installed */ }
227
+ /**
228
+ * ⚠⚠ A LOCALLY EDITED SKILL IS LEFT ALONE AND REPORTED. Without this the installer could
229
+ * only ask "does it differ?" — which is true both when the shipped copy moved on and when
230
+ * the USER changed theirs, and those are opposite instructions. Someone who tuned a skill
231
+ * lost it on the next `beehaven skills install`, silently.
232
+ *
233
+ * ⚠ THE STAMP IS THE ARBITER, NOT THE SHIPPED SHA. Comparing on-disk against SHIPPED only
234
+ * says "different"; comparing against what was INSTALLED says WHO changed it.
235
+ *
236
+ * ⚠ NO STAMP ⇒ TREATED AS UNTOUCHED. Every skill installed before stamping existed has
237
+ * none, and assuming an edit there would freeze them permanently — updates would silently
238
+ * stop landing, which is the failure mode this whole change exists to remove.
239
+ */
240
+ if (existing) {
241
+ let stamped = '';
242
+ try {
243
+ stamped = JSON.parse(fs.readFileSync(path.join(destDir, STAMP), 'utf8')).sha ?? '';
244
+ }
245
+ catch { /* unstamped */ }
246
+ if (stamped && localSha(destDir, skillFiles) !== stamped) {
247
+ warnings.push(`${agent}/${name}: edited locally — left alone (delete it to take the shipped copy)`);
248
+ steps.push(`${agent}/${name}=locally-modified`);
249
+ continue;
250
+ }
251
+ }
252
+ if (existing === desired) {
253
+ // ⚠ THE EXTRAS DECIDE THE WORD. SKILL.md matching does not mean the skill is unchanged —
254
+ // see `installExtras`. A rewritten script is an update and must say so.
255
+ const wrote = installExtras(srcDir, name, destDir, warnings);
256
+ stamp(destDir, skillFiles, warnings);
257
+ steps.push(`${agent}/${name}=${wrote ? 'updated-scripts' : 'current'}`);
258
+ continue;
259
+ }
260
+ fs.mkdirSync(destDir, { recursive: true, mode: 0o755 });
261
+ fs.writeFileSync(dest, desired, { mode: 0o644 });
262
+ installExtras(srcDir, name, destDir, warnings);
263
+ stamp(destDir, skillFiles, warnings);
264
+ steps.push(`${agent}/${name}=${existing ? 'updated' : 'written'}`);
265
+ }
266
+ catch (e) {
267
+ warnings.push(`${agent}/${name}: ${e?.message ?? String(e)}`);
268
+ }
269
+ }
270
+ }
271
+ return { steps, warnings };
272
+ }
273
+ export function removeAgentSkills() {
274
+ const steps = [];
275
+ const warnings = [];
276
+ for (const name of shippedSkills()) {
277
+ for (const { agent, dir } of AGENT_SKILL_DIRS) {
278
+ const destDir = path.join(dir, name);
279
+ const dest = path.join(destDir, 'SKILL.md');
280
+ try {
281
+ if (!fs.existsSync(destDir))
282
+ continue;
283
+ let link = null;
284
+ try {
285
+ if (fs.lstatSync(dest).isSymbolicLink())
286
+ link = fs.readlinkSync(dest);
287
+ }
288
+ catch { /* absent */ }
289
+ if (link) {
290
+ steps.push(`${agent}/${name}=symlink-kept`);
291
+ continue;
292
+ }
293
+ fs.rmSync(destDir, { recursive: true, force: true });
294
+ steps.push(`${agent}/${name}=removed`);
295
+ }
296
+ catch (e) {
297
+ warnings.push(`${agent}/${name}: ${e?.message ?? String(e)}`);
298
+ }
299
+ }
300
+ }
301
+ return { steps, warnings };
302
+ }