@creator-notes/cli 0.2.20 → 0.2.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -19
- package/dist/commands/canvas.d.ts.map +1 -1
- package/dist/commands/canvas.js +84 -2
- package/dist/commands/canvas.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +132 -9
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/notes.d.ts.map +1 -1
- package/dist/commands/notes.js +73 -2
- package/dist/commands/notes.js.map +1 -1
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +39 -2
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/install-skill.d.ts +27 -0
- package/dist/lib/install-skill.d.ts.map +1 -0
- package/dist/lib/install-skill.js +55 -0
- package/dist/lib/install-skill.js.map +1 -0
- package/dist/mcp-server.js +7 -0
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
- package/skills/cn/SKILL.md +152 -78
package/skills/cn/SKILL.md
CHANGED
|
@@ -100,7 +100,13 @@ cn canvas add-richtext <canvasId> --content "<content>" [--size small|medium|lar
|
|
|
100
100
|
cn canvas add-list <canvasId> --name "<name>" --notes <id1,id2,...> [--view list|grid] [--x <n>] [--y <n>]
|
|
101
101
|
cn canvas add-link <canvasId> --target <otherCanvasId> [--x <n>] [--y <n>]
|
|
102
102
|
|
|
103
|
-
#
|
|
103
|
+
# Place items using a declarative layout (NO x/y math — server packs them)
|
|
104
|
+
# This is the PREFERRED way to add multiple items. See "Canvas Layout" below.
|
|
105
|
+
cn canvas place <canvasId> --spec ./layout.json
|
|
106
|
+
cn canvas place <canvasId> --spec-stdin # JSON from stdin
|
|
107
|
+
cn canvas place <canvasId> --spec-inline '<short JSON>' # for tiny specs only
|
|
108
|
+
|
|
109
|
+
# Bulk add with explicit positions (escape hatch — only for pixel-perfect templates)
|
|
104
110
|
cn canvas bulk-add <canvasId> --notes '[{"noteId":"NOTE-1","x":100,"y":100},{"noteId":"NOTE-2","x":400,"y":100}]'
|
|
105
111
|
|
|
106
112
|
# Move / remove nodes
|
|
@@ -230,109 +236,177 @@ cn config set-server <url>
|
|
|
230
236
|
|
|
231
237
|
### Canvas Layout
|
|
232
238
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
#### Grid Cell System (Note Units)
|
|
236
|
-
|
|
237
|
-
All canvas positioning uses a **note unit (1u)** as the base measurement. 1u = 400px wide × 180px tall. Every item type has a known width in note units — you must account for this when planning layouts.
|
|
238
|
-
|
|
239
|
-
| Item type | Width (px) | Width (u) | Height (px) | Height (u) |
|
|
240
|
-
|-----------|-----------|-----------|-------------|------------|
|
|
241
|
-
| Note node | 400 | 1.0 | 180 | 1.0 |
|
|
242
|
-
| Text node | ~280 | 0.7 | ~40 | 0.2 |
|
|
243
|
-
| Richtext small | 560 | 1.4 | varies | varies |
|
|
244
|
-
| Richtext medium | 1120 | 2.8 | varies | varies |
|
|
245
|
-
| Richtext large | 1680 | 4.2 | varies | varies |
|
|
246
|
-
| List node (grid) | 580 | 1.45 | 160+ | varies |
|
|
247
|
-
| Canvas link | 400 | 1.0 | 80 | 0.4 |
|
|
248
|
-
| Edge label | ~80 | 0.2 | ~14 | — |
|
|
249
|
-
|
|
250
|
-
Node center offset from top-left: `(+140, +50)`.
|
|
239
|
+
**Don't compute coordinates by hand. Use `cn canvas place` with a layout spec.**
|
|
251
240
|
|
|
252
|
-
|
|
241
|
+
The server measures every item, packs them into a no-overlap layout, and inserts them in a single batch. You describe **structure** (rows, columns, what's near what) — the server resolves pixels. This is what `cn canvas place` is for, and you should reach for it whenever you're adding more than one item.
|
|
253
242
|
|
|
254
|
-
|
|
243
|
+
The call is **best-effort, not transactional** — per-item failures are reported in the response (HTTP 207) but the items that succeeded stay on the canvas. Always inspect `items[].error` and `edges[].error` before assuming success.
|
|
255
244
|
|
|
256
|
-
|
|
257
|
-
|------|-----------|-----------|---------|
|
|
258
|
-
| `small` (default) | 560 | 1.4 | Annotations, callouts, small formatted notes |
|
|
259
|
-
| `medium` | 1120 | 2.8 | Section descriptions, formatted explanations |
|
|
260
|
-
| `large` | 1680 | 4.2 | Billboard-scale hero text, full-width banners |
|
|
245
|
+
Use `cn canvas bulk-add` with explicit `x/y` ONLY for pixel-perfect templates (e.g. demo recordings or tutorial walkthroughs that need to match a specific screenshot).
|
|
261
246
|
|
|
262
|
-
|
|
247
|
+
#### The layout DSL
|
|
263
248
|
|
|
264
|
-
|
|
249
|
+
A layout document is `{ root, edges?, origin? }` where `root` is one of four node kinds:
|
|
265
250
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
251
|
+
- **`stack`** — items flow along one axis (like CSS flexbox)
|
|
252
|
+
```json
|
|
253
|
+
{ "kind": "stack", "axis": "vertical", "gap": "medium",
|
|
254
|
+
"align": "start", "items": [ /* LayoutNode */ ] }
|
|
255
|
+
```
|
|
256
|
+
- **`grid`** — N columns, items wrap to new rows (like CSS grid auto-flow)
|
|
257
|
+
```json
|
|
258
|
+
{ "kind": "grid", "columns": 3, "gap": "medium",
|
|
259
|
+
"items": [ /* LayoutNode */ ] }
|
|
260
|
+
```
|
|
261
|
+
- **`anchor`** — place a sub-tree relative to an EXISTING canvas node
|
|
262
|
+
```json
|
|
263
|
+
{ "kind": "anchor", "to": "NOTE-12", "direction": "right",
|
|
264
|
+
"gap": "medium", "child": /* LayoutNode */ }
|
|
265
|
+
```
|
|
266
|
+
- **`item`** — a leaf node (no x/y!). One per visible thing on the canvas.
|
|
269
267
|
|
|
270
|
-
|
|
268
|
+
`gap` accepts a preset (`"tight"`, `"medium"`, `"spacious"`) or a raw pixel number. Defaults to `"medium"`.
|
|
271
269
|
|
|
272
|
-
|
|
273
|
-
|------|---------|-----------|
|
|
274
|
-
| small | 1.5u (270px) | 1u (180px) |
|
|
275
|
-
| medium | 2u (360px) | 1.5u (270px) |
|
|
276
|
-
| large | 2.5u (450px) | 2u (360px) |
|
|
270
|
+
#### Leaf item shapes
|
|
277
271
|
|
|
278
|
-
|
|
272
|
+
```json
|
|
273
|
+
{ "kind": "item", "type": "note", "noteId": "NOTE-3", "key": "a" }
|
|
274
|
+
{ "kind": "item", "type": "text", "content": "Hello", "fontSize": 32, "colorVariant": "muted" }
|
|
275
|
+
{ "kind": "item", "type": "richtext", "content": "# Markdown OK", "size": "medium", "colorHex": "#3B82F6" }
|
|
276
|
+
{ "kind": "item", "type": "list", "name": "Risks", "noteIds": ["A","B","C"], "viewMode": "list" }
|
|
277
|
+
{ "kind": "item", "type": "canvas", "linkedCanvasId": "abc..." }
|
|
278
|
+
```
|
|
279
279
|
|
|
280
|
-
|
|
280
|
+
The optional `key` lets edges and other items reference this leaf later (`@<key>`).
|
|
281
281
|
|
|
282
|
-
|
|
283
|
-
|------|---------|
|
|
284
|
-
| `heading` (default) | Section headers, zone titles, canvas labels |
|
|
285
|
-
| `paragraph` | Descriptions, annotations, supporting context |
|
|
282
|
+
`richtext.content` accepts markdown directly — the server converts to TipTap before measuring.
|
|
286
283
|
|
|
287
|
-
|
|
284
|
+
#### Edges
|
|
288
285
|
|
|
289
|
-
|
|
286
|
+
Edges live at the top level alongside `root`. Each endpoint is resolved in this priority order:
|
|
290
287
|
|
|
291
|
-
|
|
288
|
+
1. **`@<key>`** — any item placed in the same call that carries a matching `key`
|
|
289
|
+
2. **Original `noteId`** of a note placed in this call (e.g. `"NOTE-7"`) — no `key` needed
|
|
290
|
+
3. **Display id or convex id** of a node already on the canvas
|
|
292
291
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
292
|
+
```json
|
|
293
|
+
"edges": [
|
|
294
|
+
{ "from": "@a", "to": "@b", "label": "depends on" },
|
|
295
|
+
{ "from": "NOTE-7", "to": "@a" }
|
|
296
|
+
]
|
|
297
|
+
```
|
|
298
298
|
|
|
299
|
-
####
|
|
299
|
+
#### Examples
|
|
300
|
+
|
|
301
|
+
**Fan-out under a heading** (the failure case the agent kept getting wrong):
|
|
302
|
+
```json
|
|
303
|
+
{
|
|
304
|
+
"root": {
|
|
305
|
+
"kind": "stack", "axis": "vertical", "gap": "medium",
|
|
306
|
+
"items": [
|
|
307
|
+
{ "kind": "item", "type": "richtext",
|
|
308
|
+
"content": "# Goals\nWhat we're committing to this quarter.",
|
|
309
|
+
"size": "medium" },
|
|
310
|
+
{ "kind": "grid", "columns": 4,
|
|
311
|
+
"items": [
|
|
312
|
+
{ "kind": "item", "type": "note", "noteId": "GOAL-1" },
|
|
313
|
+
{ "kind": "item", "type": "note", "noteId": "GOAL-2" },
|
|
314
|
+
{ "kind": "item", "type": "note", "noteId": "GOAL-3" },
|
|
315
|
+
{ "kind": "item", "type": "note", "noteId": "GOAL-4" }
|
|
316
|
+
] }
|
|
317
|
+
]
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
300
321
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
322
|
+
**SWOT-style four-quadrant layout**:
|
|
323
|
+
```json
|
|
324
|
+
{
|
|
325
|
+
"root": {
|
|
326
|
+
"kind": "stack", "axis": "vertical", "gap": "spacious",
|
|
327
|
+
"items": [
|
|
328
|
+
{ "kind": "stack", "axis": "horizontal", "gap": "spacious", "items": [
|
|
329
|
+
{ "kind": "grid", "columns": 2, "items": [
|
|
330
|
+
{ "kind": "item", "type": "note", "noteId": "STR-1" },
|
|
331
|
+
{ "kind": "item", "type": "note", "noteId": "STR-2" }
|
|
332
|
+
] },
|
|
333
|
+
{ "kind": "grid", "columns": 2, "items": [
|
|
334
|
+
{ "kind": "item", "type": "note", "noteId": "WEAK-1" }
|
|
335
|
+
] }
|
|
336
|
+
] },
|
|
337
|
+
{ "kind": "stack", "axis": "horizontal", "gap": "spacious", "items": [
|
|
338
|
+
{ "kind": "grid", "columns": 2, "items": [
|
|
339
|
+
{ "kind": "item", "type": "note", "noteId": "OPP-1" }
|
|
340
|
+
] },
|
|
341
|
+
{ "kind": "grid", "columns": 2, "items": [
|
|
342
|
+
{ "kind": "item", "type": "note", "noteId": "THR-1" }
|
|
343
|
+
] }
|
|
344
|
+
] }
|
|
345
|
+
]
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
```
|
|
305
349
|
|
|
306
|
-
|
|
350
|
+
**Anchor a new column to the right of an existing note**:
|
|
351
|
+
```json
|
|
352
|
+
{
|
|
353
|
+
"root": {
|
|
354
|
+
"kind": "anchor", "to": "NOTE-12", "direction": "right", "gap": "medium",
|
|
355
|
+
"child": {
|
|
356
|
+
"kind": "stack", "axis": "vertical", "gap": "tight",
|
|
357
|
+
"items": [
|
|
358
|
+
{ "kind": "item", "type": "note", "noteId": "NEW-1" },
|
|
359
|
+
{ "kind": "item", "type": "note", "noteId": "NEW-2" }
|
|
360
|
+
]
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
```
|
|
307
365
|
|
|
308
|
-
|
|
366
|
+
**Diamond topology with edges**:
|
|
367
|
+
```json
|
|
368
|
+
{
|
|
369
|
+
"root": {
|
|
370
|
+
"kind": "stack", "axis": "vertical", "gap": "medium", "align": "center",
|
|
371
|
+
"items": [
|
|
372
|
+
{ "kind": "item", "type": "note", "noteId": "A", "key": "root" },
|
|
373
|
+
{ "kind": "stack", "axis": "horizontal", "gap": "medium", "items": [
|
|
374
|
+
{ "kind": "item", "type": "note", "noteId": "B", "key": "left" },
|
|
375
|
+
{ "kind": "item", "type": "note", "noteId": "C", "key": "right" }
|
|
376
|
+
] },
|
|
377
|
+
{ "kind": "item", "type": "note", "noteId": "D", "key": "tail" }
|
|
378
|
+
]
|
|
379
|
+
},
|
|
380
|
+
"edges": [
|
|
381
|
+
{ "from": "@root", "to": "@left" },
|
|
382
|
+
{ "from": "@root", "to": "@right" },
|
|
383
|
+
{ "from": "@left", "to": "@tail" },
|
|
384
|
+
{ "from": "@right", "to": "@tail" }
|
|
385
|
+
]
|
|
386
|
+
}
|
|
387
|
+
```
|
|
309
388
|
|
|
310
|
-
|
|
311
|
-
1. Create richtext/text nodes first (`add-richtext --json`) — capture `estimatedHeight` from response
|
|
312
|
-
2. Calculate note positions using actual richtext heights for Y offsets
|
|
313
|
-
3. `bulk-add` all notes with correctly calculated positions
|
|
314
|
-
4. `add-edge` for all connections
|
|
389
|
+
#### Workflow
|
|
315
390
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
Row 1 Y = Row0_Y + tallestItemInRow0 + vGap
|
|
320
|
-
Row 2 Y = Row1_Y + tallestItemInRow1 + vGap
|
|
321
|
-
```
|
|
391
|
+
1. Write the layout doc to a temp file (`/tmp/layout.json`).
|
|
392
|
+
2. Run `cn canvas place <canvasId> --spec /tmp/layout.json --json`.
|
|
393
|
+
3. The response includes `items[]` (with resolved `positionX/Y`, `width`, `height`, `id`, and your `key`), `edges[]` (with resolved edge ids), and `bbox` (the bounding box of the whole layout).
|
|
322
394
|
|
|
323
|
-
|
|
324
|
-
```
|
|
325
|
-
Item 1: x = 100, right edge = 100 + itemWidth
|
|
326
|
-
Item 2: x = rightEdge1 + hGap
|
|
327
|
-
```
|
|
395
|
+
#### Constraints
|
|
328
396
|
|
|
329
|
-
|
|
397
|
+
- **Anchors take zero space in their parent** — when nested inside a `stack` or `grid`, an anchor reserves no slot, so siblings collapse together. Anchors are best used at the root or as their own top-level branch.
|
|
398
|
+
- **Anchor `to:` must be a node already on the canvas** — local `@key` refs only work for edges, not for anchor targets in this version.
|
|
399
|
+
- **Never use ALL CAPS** for text node content. Use title case (e.g., "Key Tensions" not "KEY TENSIONS").
|
|
400
|
+
- **Multi-line richtext content** is best authored as markdown — the server converts it server-side.
|
|
330
401
|
|
|
331
|
-
|
|
402
|
+
#### When the layout engine isn't enough
|
|
332
403
|
|
|
333
|
-
|
|
404
|
+
A few cases still need explicit `x/y` via `bulk-add`:
|
|
405
|
+
- Reproducing a canvas pixel-for-pixel for a demo/screenshot
|
|
406
|
+
- Templates with intentional off-grid placement
|
|
407
|
+
- Adding a single item next to a known coordinate without invoking the solver
|
|
334
408
|
|
|
335
|
-
|
|
409
|
+
In all other cases — and especially when adding 3+ items at once — use `place`.
|
|
336
410
|
|
|
337
411
|
### Interlinking Notes
|
|
338
412
|
|