beehaven 0.8.29 → 0.8.33
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/dist/agents-md-text.js +64 -0
- package/dist/browser-login.js +14 -4
- package/dist/build-channel.js +2 -2
- package/dist/claude-bridge.js +12 -9
- package/dist/clearly.js +4 -3
- package/dist/cli.js +26 -7
- package/dist/commands/agents-md.js +118 -0
- package/dist/commands/daemon-cmd.js +2 -0
- package/dist/commands/help.js +21 -0
- package/dist/commands/self-update.js +32 -5
- package/dist/commands/workspace.js +3 -3
- package/dist/daemon-client.js +10 -6
- package/dist/daemon-entry.js +1 -0
- package/dist/daemon-process.js +125 -0
- package/dist/daemon.js +131 -62
- package/dist/dashboard.js +118 -6
- package/dist/ipc-auth.js +3 -1
- package/dist/ipc-client.js +7 -6
- package/dist/ipc-path.js +92 -0
- package/dist/ipc-server.js +33 -33
- package/dist/npm-update.js +138 -0
- package/dist/setup-service.js +9 -4
- package/dist/verb-surface.js +1 -0
- package/dist/watcher.js +9 -23
- package/dist/windows-hide.js +77 -0
- package/package.json +1 -1
- package/scripts/sync-skills.mjs +6 -0
- package/skills/agent-doodle-space/SKILL.md +1 -1
- package/skills/agent-home/SKILL.md +1 -1
- package/skills/brand-identity/SKILL.md +22 -5
- package/skills/clearly-agent/SKILL.md +11 -4
- package/skills/clearly-canvas/SKILL.md +31 -5
- package/skills/clearly-canvas/authoring.md +40 -12
- package/skills/clearly-canvas/example.mjs +72 -69
- package/skills/clearly-docs/SKILL.md +151 -0
- package/skills/clearly-init/SKILL.md +135 -0
- package/skills/clearly-workflows/SKILL.md +90 -0
- package/skills/clearly-workspace/SKILL.md +1 -1
- package/skills/codebase-map/SKILL.md +1 -1
- package/skills/design-craft/SKILL.md +9 -6
- package/skills/index.json +45 -10
- package/skills/layout-systems/SKILL.md +14 -11
- package/skills/pair-on-canvas/SKILL.md +1 -1
- package/skills/sticker-pack/SKILL.md +132 -0
- package/skills/visualize/SKILL.md +188 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: visualize
|
|
3
|
+
description: Needs a terminal with the beehaven CLI (Claude Code, Codex, Gemini CLI); in a chat with only the Clearly connector, say so and use the clearly_* tools instead. Turn any concept, answer, or described system into a clean DIAGRAM on a Clearly spatial canvas instead of a wall of text. Load this when the user asks to "diagram this", "draw it", "sketch it", "map it out", "visualize this",
|
|
4
|
+
"explain visually", "show me how X works", "flowchart this", "make a diagram" — AND proactively whenever YOUR OWN answer would be clearer as a picture than a paragraph (a flow with branches, who-calls-whom, a schema, an architecture, options on axes). Picks the right diagram type for the content and builds it with the canvas primitives.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
> **⚠ CANVAS WORK GOES THROUGH THE CLI, NOT AN MCP TOOL.** Anything written
|
|
8
|
+
> `canvas-act { … }` / `canvas-perceive { … }` below is an ACTION, run as
|
|
9
|
+
> `beehaven call canvas-act '<the JSON>'`. The payloads are exactly as shown. The MCP
|
|
10
|
+
> surface is seven tools split by operation, and a single tool that dispatches 230
|
|
11
|
+
> caller-named canvas actions spans reads, writes and deletes at once — which is why the
|
|
12
|
+
> generic door is the shell instead. `clearly_read { target, type: "composition" }` still
|
|
13
|
+
> reads a canvas as an artifact.
|
|
14
|
+
|
|
15
|
+
# Visualize — draw it, don't write it
|
|
16
|
+
|
|
17
|
+
Some answers are paragraphs. Many are **pictures pretending to be paragraphs**: a flow with branches, a request hopping between services, a schema, a tradeoff matrix. The moment relationships matter, prose makes the reader rebuild the shape in their head. A diagram hands them the shape — spatial layout *is* the explanation, it's glanceable, and it's screenshot-shareable in a way a wall of text never is.
|
|
18
|
+
|
|
19
|
+
So: when you catch yourself about to write three paragraphs explaining how something connects, **draw it on the canvas instead** (and you can still say the one-line version in chat).
|
|
20
|
+
|
|
21
|
+
Prereq: the `beehaven` CLI is installed, signed in as an agent, and connected to the intended
|
|
22
|
+
workspace (run `clearly-init` if not). **Read `clearly-canvas` for the tool contract** —
|
|
23
|
+
`canvas-perceive` / `canvas-act` / `canvas-catalog`, `frame.create`, `canvas.create-node`
|
|
24
|
+
(text/rect/ellipse/svg/line), first-class `arrow.create`, and nesting via `parentId` with
|
|
25
|
+
frame-relative coordinates. This skill is the *diagram cookbook* on top of those primitives.
|
|
26
|
+
|
|
27
|
+
## Pick the type (1-line heuristic each)
|
|
28
|
+
|
|
29
|
+
| If the content is… | Draw a… |
|
|
30
|
+
|---|---|
|
|
31
|
+
| an answer you'd write as multiple paragraphs | **Explain-an-answer** (boxes + arrows) |
|
|
32
|
+
| steps, especially with branches | **Flowchart** (boxes + decision diamonds) |
|
|
33
|
+
| who-talks-to-whom over time | **Sequence diagram** (lifelines + message arrows) |
|
|
34
|
+
| services / data stores and their calls | **Architecture** (frames + cylinders + arrows) |
|
|
35
|
+
| things and the relationships between them | **ER / schema** (entity boxes + cardinality lines) |
|
|
36
|
+
| one idea exploding outward into subtopics | **Mind-map** (central node + radial branches) |
|
|
37
|
+
| options scored on a few criteria | **Comparison matrix** (grid of cells) |
|
|
38
|
+
|
|
39
|
+
When unsure, ask: *is the story "then" (flowchart), "who" (sequence), "what's-related" (ER), or "which-is-better" (matrix)?*
|
|
40
|
+
|
|
41
|
+
## The build loop (every diagram)
|
|
42
|
+
|
|
43
|
+
1. **Get a canvas + perceive.** `canvas-perceive { compositionId, format:"text" }` → read `backgroundColor` (design WITH it — light ink on dark, dark ink on light) and `gaze.visibleWorldRect` (place work where the user is looking).
|
|
44
|
+
2. **Batch the skeleton.** One `canvas-act` with a `batch` of frames + boxes on a grid. Capture every returned `{ id }`.
|
|
45
|
+
3. **Wire the arrows** with `arrow.create {from, to}` — a first-class arrow that BINDS to the boxes (by returned id OR layer name) and FOLLOWS them when they move; `routing:"elbow"` for orthogonal flowcharts, `label` for the edge text (no separate label node needed). See clearly-canvas → Arrows / connectors.
|
|
46
|
+
4. **Label** edges/branches with small `text` nodes at arrow midpoints.
|
|
47
|
+
5. **Re-perceive** so the user can ink notes; read them back; revise with `canvas.update-nodes`.
|
|
48
|
+
|
|
49
|
+
Grid discipline matters more than anything: equal gutters (24–40px), aligned edges, generous whitespace. A diagram that breathes reads as designed.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Recipe: Explain-an-answer
|
|
54
|
+
|
|
55
|
+
Your default upgrade from prose. **Layout:** 3–6 labelled boxes left→right (or top→down) in the order you'd say them, one arrow per "and then / because / leads to", a title text on top.
|
|
56
|
+
|
|
57
|
+
```jsonc
|
|
58
|
+
canvas-act { "compositionId": "c_…", "batch": [
|
|
59
|
+
{ "action": "canvas.create-node", "args": { "type":"text", "name":"title", "text":"How a request gets billed", "x":0, "y":-40, "size":24, "fontWeight":700, "fill":"#fff" } },
|
|
60
|
+
{ "action": "canvas.create-node", "args": { "type":"rect", "name":"b1", "x":0, "y":0, "w":180, "h":72, "fill":"#1b2230", "stroke":"#3a465c", "radius":10 } },
|
|
61
|
+
{ "action": "canvas.create-node", "args": { "type":"text", "name":"b1t", "text":"Member acts", "x":16, "y":26, "size":15, "fontWeight":600, "fill":"#e8edf5" } },
|
|
62
|
+
{ "action": "canvas.create-node", "args": { "type":"rect", "name":"b2", "x":260, "y":0, "w":180, "h":72, "fill":"#1b2230", "stroke":"#3a465c", "radius":10 } },
|
|
63
|
+
{ "action": "canvas.create-node", "args": { "type":"text", "name":"b2t", "text":"Debit seat budget", "x":276, "y":26, "size":15, "fontWeight":600, "fill":"#e8edf5" } },
|
|
64
|
+
{ "action": "arrow.create", "args": { "from":"b1", "to":"b2", "routing":"elbow" } }
|
|
65
|
+
]}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Chain more boxes at `x += 260` per step. Branch (e.g. "budget exhausted → top-up") with a second arrow going down to an offset box.
|
|
69
|
+
|
|
70
|
+
## Recipe: Flowchart / process
|
|
71
|
+
|
|
72
|
+
**Layout:** boxes top→down (or left→right), **rounded rect = action**, **diamond = decision**. Draw a diamond natively as a closed `vector.create` rhombus (4 points: top, right, bottom, left); give it two outgoing arrows labelled **Yes / No**.
|
|
73
|
+
|
|
74
|
+
```jsonc
|
|
75
|
+
canvas-act { "compositionId":"c_…", "batch":[
|
|
76
|
+
{ "action":"canvas.create-node", "args":{ "type":"rect", "name":"start", "x":120, "y":0, "w":160, "h":56, "fill":"#173a2a", "stroke":"#2f6b4d", "radius":28 } },
|
|
77
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"startt", "text":"Invite sent", "x":156, "y":18, "size":14, "fontWeight":600, "fill":"#d6f5e4" } },
|
|
78
|
+
{ "action": "arrow.create", "args": { "from":"start", "to":"decide", "label":"yes", "routing":"elbow" } },
|
|
79
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"yesl", "text":"yes", "x":216, "y":74, "size":12, "fontWeight":600, "fill":"#7c8497" } }
|
|
80
|
+
]}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Rules: one entry, decisions are the only nodes with >1 exit, **every arrow labelled at branches**, keep the happy path straight and push error/No branches to the side.
|
|
84
|
+
|
|
85
|
+
## Recipe: Sequence diagram
|
|
86
|
+
|
|
87
|
+
**Layout:** each actor is a column — a header box at top + a vertical lifeline (`type:"line"`) running down. Messages are **horizontal arrows** between lifelines; **time flows down**, so each later message sits at a larger `y`.
|
|
88
|
+
|
|
89
|
+
```jsonc
|
|
90
|
+
canvas-act { "compositionId":"c_…", "batch":[
|
|
91
|
+
{ "action":"canvas.create-node", "args":{ "type":"rect", "name":"a1", "x":0, "y":0, "w":120, "h":40, "fill":"#1b2230", "stroke":"#3a465c", "radius":8 } },
|
|
92
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"a1t", "text":"Web", "x":48, "y":12, "size":14, "fontWeight":600, "fill":"#e8edf5" } },
|
|
93
|
+
{ "action":"canvas.create-node", "args":{ "type":"line", "name":"a1life", "x":60, "y":40, "w":0, "h":300, "stroke":"#3a465c" } },
|
|
94
|
+
{ "action":"canvas.create-node", "args":{ "type":"rect", "name":"a2", "x":280, "y":0, "w":120, "h":40, "fill":"#1b2230", "stroke":"#3a465c", "radius":8 } },
|
|
95
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"a2t", "text":"Home DO", "x":312, "y":12, "size":14, "fontWeight":600, "fill":"#e8edf5" } },
|
|
96
|
+
{ "action":"canvas.create-node", "args":{ "type":"line", "name":"a2life", "x":340, "y":40, "w":0, "h":300, "stroke":"#3a465c" } },
|
|
97
|
+
{ "action": "arrow.create", "args": { "from":"a1life", "to":"a2life", "label":"check-quota(userId)" } },
|
|
98
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"m1t", "text":"check-quota(userId)", "x":120, "y":52, "size":12, "fontWeight":500, "fill":"#aab3c2" } }
|
|
99
|
+
]}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Place the message text just above its arrow. A return/response arrow points back left (flip `x1`/`x2`). Keep columns evenly spaced (~280px) so long labels fit.
|
|
103
|
+
|
|
104
|
+
## Recipe: Architecture / system diagram
|
|
105
|
+
|
|
106
|
+
**Layout:** each service is a `frame` (so it can hold a label + sub-parts); **data stores are cylinders** drawn natively (a `rect` body with an `ellipse` cap on top and one behind at the bottom, grouped with `canvas.group`); arrows are calls. Cluster by tier — a row of frames per tier (client / edge / data), with a faint heading text per row.
|
|
107
|
+
|
|
108
|
+
```jsonc
|
|
109
|
+
canvas-act { "compositionId":"c_…", "batch":[
|
|
110
|
+
{ "action":"frame.create", "args":{ "name":"Worker", "x":0, "y":80, "w":200, "h":110, "fill":"#141a24" } },
|
|
111
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"wl", "text":"CF Worker", "x":14, "y":12, "size":14, "fontWeight":700, "fill":"#e8edf5", "parentId":"<WorkerFrameId>" } },
|
|
112
|
+
{ "action": "arrow.create", "args": { "from":"Worker", "to":"HomeDO", "routing":"elbow", "label":"rpc" } }
|
|
113
|
+
]}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Rules: one box per service (not per file), label every arrow with the call/protocol if non-obvious, keep tiers as aligned rows so dataflow reads in one direction.
|
|
117
|
+
|
|
118
|
+
## Recipe: ER / schema
|
|
119
|
+
|
|
120
|
+
**Layout:** each entity is a `frame` with a bold title row + a `text` node per field (stack fields at `y += 20`). Relationships are lines between frames with a **cardinality label** (`1`, `N`, `1..*`) near each end.
|
|
121
|
+
|
|
122
|
+
```jsonc
|
|
123
|
+
canvas-act { "compositionId":"c_…", "batch":[
|
|
124
|
+
{ "action":"frame.create", "args":{ "name":"User", "x":0, "y":0, "w":180, "h":120, "fill":"#141a24" } },
|
|
125
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"u-h", "text":"User", "x":12, "y":10, "size":15, "fontWeight":700, "fill":"#fff", "parentId":"<UserFrameId>" } },
|
|
126
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"u-f1", "text":"id PK", "x":12, "y":40, "size":13, "fontWeight":400, "fill":"#aab3c2", "parentId":"<UserFrameId>" } },
|
|
127
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"u-f2", "text":"email", "x":12, "y":60, "size":13, "fontWeight":400, "fill":"#aab3c2", "parentId":"<UserFrameId>" } },
|
|
128
|
+
{ "action":"frame.create", "args":{ "name":"Seat", "x":300, "y":0, "w":180, "h":120, "fill":"#141a24" } },
|
|
129
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"s-h", "text":"Seat", "x":12, "y":10, "size":15, "fontWeight":700, "fill":"#fff", "parentId":"<SeatFrameId>" } },
|
|
130
|
+
{ "action":"canvas.create-node", "args":{ "type":"line", "name":"u—s", "x":180, "y":40, "w":120, "h":0, "stroke":"#7c8497" } },
|
|
131
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"card1", "text":"1", "x":188, "y":24, "size":12, "fontWeight":700, "fill":"#7c8497" } },
|
|
132
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"cardN", "text":"N", "x":284, "y":24, "size":12, "fontWeight":700, "fill":"#7c8497" } }
|
|
133
|
+
]}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Rules: PK/FK noted in the field text, one relationship line per FK, cardinality at BOTH ends so the reader knows which side is the "many".
|
|
137
|
+
|
|
138
|
+
## Recipe: Mind-map
|
|
139
|
+
|
|
140
|
+
**Layout:** one central node (an `ellipse` or pill `rect`), child topics radiating out, each connected by a **curved** branch (an open `vector.create` pen path with `hIn`/`hOut` control points, not a straight line). Place children evenly around the center; second-level topics hang off their parent.
|
|
141
|
+
|
|
142
|
+
```jsonc
|
|
143
|
+
canvas-act { "compositionId":"c_…", "batch":[
|
|
144
|
+
{ "action":"canvas.create-node", "args":{ "type":"ellipse", "name":"core", "x":220, "y":160, "w":160, "h":80, "fill":"#2a1f3a", "stroke":"#7b5cc4" } },
|
|
145
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"coret", "text":"Company Brain", "x":250, "y":190, "size":15, "fontWeight":700, "fill":"#e9defb" } },
|
|
146
|
+
{ "action":"canvas.create-node", "args":{ "type":"rect", "name":"c1", "x":480, "y":60, "w":150, "h":48, "fill":"#1b2230", "stroke":"#3a465c", "radius":24 } },
|
|
147
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"c1t", "text":"Org context", "x":500, "y":76, "size":13, "fontWeight":600, "fill":"#e8edf5" } },
|
|
148
|
+
{ "action":"vector.create", "args":{ "name":"core→c1", "closed":false, "stroke":"#7b5cc4", "strokeWidth":2,
|
|
149
|
+
"points":[ { "x":382, "y":192, "hOut":{ "x":430, "y":192 } }, { "x":478, "y":92, "hIn":{ "x":430, "y":92 } } ] } }
|
|
150
|
+
]}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Rules: keep the center visually heaviest, ~4–7 first-level branches (more → it's really a tree, use a frame layout), curve the branches so it reads organic not boxy.
|
|
154
|
+
|
|
155
|
+
## Recipe: Comparison matrix
|
|
156
|
+
|
|
157
|
+
Perfect for **"X vs Y vs Z"**. **Layout:** a grid of `rect` cells — top row = options, left column = criteria, body cells = the values. Tint the header row/column so the axes pop; fill body cells (green/amber/red) to make the winner obvious at a glance.
|
|
158
|
+
|
|
159
|
+
```jsonc
|
|
160
|
+
canvas-act { "compositionId":"c_…", "batch":[
|
|
161
|
+
{ "action":"canvas.create-node", "args":{ "type":"rect", "name":"h-free", "x":160, "y":0, "w":120, "h":40, "fill":"#222b3a", "stroke":"#3a465c" } },
|
|
162
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"h-freet", "text":"Free", "x":196, "y":12, "size":14, "fontWeight":700, "fill":"#fff" } },
|
|
163
|
+
{ "action":"canvas.create-node", "args":{ "type":"rect", "name":"h-pro", "x":280, "y":0, "w":120, "h":40, "fill":"#222b3a", "stroke":"#3a465c" } },
|
|
164
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"h-prot", "text":"Pro", "x":322, "y":12, "size":14, "fontWeight":700, "fill":"#fff" } },
|
|
165
|
+
{ "action":"canvas.create-node", "args":{ "type":"rect", "name":"r-agents", "x":0, "y":40, "w":160, "h":40, "fill":"#222b3a", "stroke":"#3a465c" } },
|
|
166
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"r-agentst", "text":"Agents", "x":14, "y":52, "size":13, "fontWeight":600, "fill":"#cfd6e2" } },
|
|
167
|
+
{ "action":"canvas.create-node", "args":{ "type":"rect", "name":"cell-free-agents", "x":160, "y":40, "w":120, "h":40, "fill":"#3a2417", "stroke":"#3a465c" } },
|
|
168
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"cell-free-agentst", "text":"1", "x":214, "y":52, "size":13, "fontWeight":600, "fill":"#f0c9a8" } },
|
|
169
|
+
{ "action":"canvas.create-node", "args":{ "type":"rect", "name":"cell-pro-agents", "x":280, "y":40, "w":120, "h":40, "fill":"#173a2a", "stroke":"#3a465c" } },
|
|
170
|
+
{ "action":"canvas.create-node", "args":{ "type":"text", "name":"cell-pro-agentst", "text":"10", "x":332, "y":52, "size":13, "fontWeight":600, "fill":"#a8f0c9" } }
|
|
171
|
+
]}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Keep cells a uniform `w`/`h` and snap every cell to the grid (column `x`, row `y`); the alignment is what makes it read as a table, not scattered boxes.
|
|
175
|
+
|
|
176
|
+
## The viral bit
|
|
177
|
+
|
|
178
|
+
A clean diagram is **instantly screenshot-shareable** in a way a paragraph never is. Every text answer you convert into a tidy flowchart or architecture map is a tiny ad for the canvas — someone drops it in Slack and the reply is "wait, the AI just *drew* that?". So make each one frame-worthy: aligned grid, honest arrows, one clear read direction, a title. The diagram sells the next person on the surface.
|
|
179
|
+
|
|
180
|
+
## Rules of thumb
|
|
181
|
+
|
|
182
|
+
- **Prose smell test:** about to write 3+ paragraphs about how things connect? Draw it instead.
|
|
183
|
+
- **Pick by the question:** "then" → flowchart, "who/when" → sequence, "what's related" → ER, "which is better" → matrix, "one idea outward" → mind-map.
|
|
184
|
+
- **Skeleton in one `batch`**, then arrows, then labels — capture every returned `id`.
|
|
185
|
+
- **Arrows = `arrow.create {from,to}`** — a first-class arrow that BINDS to the boxes and follows them (`routing:"elbow"` for flowcharts, `label` for edge text). Never hand-draw one as `type:"svg"` with a `marker-end`: that is a static path that does not move with its nodes; always pass `compositionId`; `name` on every create.
|
|
186
|
+
- **Grid or it's a dump:** equal gutters, aligned edges, one read direction, generous whitespace.
|
|
187
|
+
- **Perceive first** (design with `backgroundColor`, place in `gaze`); **re-perceive after** to read the human's ink and revise.
|
|
188
|
+
- **Need an action not in clearly-canvas?** `canvas-catalog { surface:"all" }` — don't invent action names.
|