@zvada/cr8 0.0.1 → 0.2.0
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/.claude-plugin/marketplace.json +14 -0
- package/.claude-plugin/plugin.json +23 -0
- package/.codex-plugin/mcp.json +11 -0
- package/.codex-plugin/plugin.json +35 -0
- package/.mcp.json +13 -0
- package/LICENSE +28 -0
- package/README.md +174 -2
- package/dist/cr8.mjs +543 -0
- package/docs/user/app-store-screenshots.md +16 -0
- package/docs/user/cli.md +259 -0
- package/docs/user/desktop.md +43 -0
- package/docs/user/feedback.md +99 -0
- package/docs/user/install.md +160 -0
- package/docs/user/mcp.md +104 -0
- package/docs/user/projects.md +45 -0
- package/package.json +83 -7
- package/skills/cr8-design/SKILL.md +54 -0
- package/skills/cr8-design/agents/openai.yaml +4 -0
- package/skills/cr8-design/references/build.md +85 -0
- package/skills/cr8-design/references/cli.md +28 -0
- package/skills/cr8-design/references/start.md +34 -0
- package/skills/cr8-design/references/troubleshooting.md +16 -0
- package/skills/cr8-design/references/verify.md +41 -0
- package/skills/cr8-feedback/SKILL.md +44 -0
- package/skills/cr8-feedback/agents/openai.yaml +6 -0
- package/skills/cr8-flows/SKILL.md +40 -0
- package/skills/cr8-flows/agents/openai.yaml +4 -0
- package/skills/cr8-flows/references/build.md +30 -0
- package/skills/cr8-flows/references/cli.md +7 -0
- package/skills/cr8-flows/references/models.md +70 -0
- package/skills/cr8-flows/references/results.md +24 -0
- package/skills/cr8-flows/references/run.md +21 -0
- package/skills/cr8-flows/references/troubleshooting.md +17 -0
- package/bin/cr8.mjs +0 -2
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# App Store screenshot playbook
|
|
2
|
+
|
|
3
|
+
CR8's App Store methodology is dynamic product knowledge, not package documentation. This file intentionally does not duplicate its rules.
|
|
4
|
+
|
|
5
|
+
With MCP, call:
|
|
6
|
+
|
|
7
|
+
1. `canvas_playbooks`
|
|
8
|
+
2. `canvas_playbook({ id: "app-store" })`
|
|
9
|
+
3. `canvas_styles({ playbookId: "app-store" })`
|
|
10
|
+
4. `canvas_style({ id: "<chosen-style>" })`
|
|
11
|
+
|
|
12
|
+
With the CLI, use `cr8 playbooks`, `cr8 playbook app-store`, `cr8 styles --playbook app-store`, and `cr8 style <chosen-style>`.
|
|
13
|
+
|
|
14
|
+
Playbooks define the task methodology and acceptance gate. Style Directions define the composition system: signature visual mass, layout, hierarchy, typography, color, imagery, anti-patterns, and visual checks. CR8 validates both against shared typed contracts and caches responses in process memory only. The installed skill and local design project never persist their bodies, so service updates are available without reinstalling the plugin.
|
|
15
|
+
|
|
16
|
+
`canvas_guide({ topic: "app-store" })` and `cr8 guide --topic app-store` remain backward-compatible aliases for the playbook during migration.
|
package/docs/user/cli.md
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# CR8 CLI
|
|
2
|
+
|
|
3
|
+
The CLI is a direct agent interface to the shared canvas. It uses stable scene IDs and semantic roles, never browser coordinates. Every persisted request is atomic, appears live in the human canvas, and enters human undo history once.
|
|
4
|
+
|
|
5
|
+
The command is `cr8`.
|
|
6
|
+
|
|
7
|
+
## Connect to the project owned by MCP
|
|
8
|
+
|
|
9
|
+
The recommended local-first workflow lets Codex or Claude Code own the CR8 process. After `canvas_init` or `canvas_open`, use the returned loopback URL with any CLI command:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
cr8 status --url http://127.0.0.1:4176 --pretty
|
|
13
|
+
cr8 tree --root launch-square --url http://127.0.0.1:4176 --pretty
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
This edits the same `cr8.json` project and local assets as MCP and the human canvas. CLI agents can also inspect and switch the repository project catalog through the same runtime:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
cr8 projects --url http://127.0.0.1:4176 --pretty
|
|
20
|
+
cr8 open designs/app-store-screenshots --url http://127.0.0.1:4176 --pretty
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`open` switches the process to another project on the same URL. Rediscover node IDs and the collaboration sequence afterwards; MCP handles this handoff automatically.
|
|
24
|
+
|
|
25
|
+
## Run a project yourself
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cr8 start designs/launch # create the project when the path holds none, serve it, open the browser
|
|
29
|
+
cr8 init designs/launch # or: create a blank project in the current workspace
|
|
30
|
+
cr8 serve --project designs/launch --open
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`start` and `serve` print one JSON readiness record with the loopback `url`, the `port`, the `pid`, the `workspaceRoot` and the `project` (its workspace-relative `path`, its `directory`, name, `workspaceId` and `sequence`), stay attached, and open the browser (`start` unless `--no-open`; `serve` with `--open`). A workspace with no project makes `serve` refuse and name `cr8 start <path>`, which creates the project and serves it; when the workspace contains exactly one project, `--project` may be omitted.
|
|
34
|
+
|
|
35
|
+
Both record the runtime they started in `<workspaceRoot>/.cr8/runtime.json` (so does `mcp`, once an agent's canvas_init or canvas_open has opened a project) (`url`, `pid`, `workspaceRoot`, `projectPath`, `startedAt` and the `command`; the directory ignores itself in Git, and the record goes on a clean shutdown), and the ready line names the file as `record`. A CLI run anywhere inside that workspace then needs no `--url`. Without one, the CLI uses, in order: `CR8_URL` when set; the recorded runtime when its `/health` answers for the workspace around the current directory (or the one `--workspace DIR` or `CR8_WORKSPACE` names); else `http://127.0.0.1:4176` (or `CR8_PORT`). A runtime the CLI chose this way is checked before the command runs: when its `/health` names another workspace than the CLI's, the command is refused with `wrong_runtime` and one sentence, `The runtime at URL serves WORKSPACE (project PATH); this workspace's runtime is URL2 (from start at TIME); pass --url URL2 or start one here`, or, when the recorded runtime no longer answers, `… no longer answers; start one here: cr8 start PATH`. A record whose process is gone is removed by the command that finds it gone; the workspace stays known by its `.cr8` directory, so a stranger on the default port is still refused there (`this workspace has no runtime recorded; start one here`) until a new `start`. Every probe the CLI makes to choose a runtime waits at most 1.5 s. `--url` is taken as given. `status` answers `url`, the runtime that answered, beside the `workspaceRoot` and `project` it serves.
|
|
36
|
+
|
|
37
|
+
The default port is 4176 (or `CR8_PORT`). When another process holds it and no `--port` was asked for, the runtime takes a free port and says so in a `note` beside the `port` and `url` it serves on. With an explicit `--port` that is held, it refuses with `port_in_use`: when the holder is another CR8 runtime, the message names its pid, the project it serves and its workspace root (read from its `/health`), and says to pass another `--port` or to talk to it with `--url`. `status` carries the same `workspaceRoot` and `project` (`path`, `directory`), so an agent tells a stranger's runtime on a port from its own.
|
|
38
|
+
|
|
39
|
+
## Recommended loop
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Read the current sequence and discover the target.
|
|
43
|
+
cr8 status --pretty
|
|
44
|
+
cr8 find --role headline --root launch-square --pretty
|
|
45
|
+
|
|
46
|
+
# Validate one cohesive operation without saving it.
|
|
47
|
+
cr8 edit --ops '[
|
|
48
|
+
{"type":"set_text","id":"square-title","patch":{"text":"Agents work in public."}}
|
|
49
|
+
]' --dry-run --pretty
|
|
50
|
+
|
|
51
|
+
# Persist against the sequence you inspected.
|
|
52
|
+
cr8 edit --ops '[
|
|
53
|
+
{"type":"set_text","id":"square-title","patch":{"text":"Agents work in public."}}
|
|
54
|
+
]' --sequence 12 --actor "Campaign agent" --pretty
|
|
55
|
+
|
|
56
|
+
cr8 doctor --root launch-square --pretty
|
|
57
|
+
|
|
58
|
+
# Bring references into the same project, capture a live surface, and compare
|
|
59
|
+
# an exact artboard export with a same-size source image.
|
|
60
|
+
cr8 import ./references/home.png --as-frame --name "Home reference" --pretty
|
|
61
|
+
cr8 capture https://example.com --viewport 1280x720 --name "Site capture" --pretty
|
|
62
|
+
# Copy frameId from the import response.
|
|
63
|
+
cr8 verify --reference ./references/home.png --root "$FRAME_ID" --pretty
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Omitting `--sequence` reads the latest session immediately before a mutation. The CLI always sends that session's workspace identity, while an explicit sequence protects a longer read/think/write loop: switching designs or receiving a newer human or agent edit produces a conflict instead of being overwritten.
|
|
67
|
+
|
|
68
|
+
## Commands
|
|
69
|
+
|
|
70
|
+
| Command | Purpose |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| `start [PROJECT_PATH] [--workspace DIR] [--port N] [--no-open]` | Open the project, or create it when the named path holds none yet (a legacy `.relay` project opens and migrates), serve the loopback canvas, open the browser and emit JSON readiness with `created`, the `port`, a `note` when the default port was busy and `record`, the file the workspace remembers the runtime by, so a CLI run inside it finds it without `--url`. |
|
|
73
|
+
| `serve [--workspace DIR] [--project PATH] [--port N] [--host LOOPBACK] [--open]` | Open one project and serve the loopback canvas; emit JSON readiness with the `port` (and a `note` when the default was busy) and `record`, as `start` does. A workspace with no project is refused with a sentence naming `cr8 start <path>`. |
|
|
74
|
+
| `init PROJECT_PATH [--workspace DIR]` | Create a blank project directory and release it. |
|
|
75
|
+
| `mcp [--transport stdio\|http] [--port N] [--workspace DIR]` | Serve the MCP tools; `http` mounts `/mcp` on the loopback listener for development hosts. |
|
|
76
|
+
| `projects [--workspace DIR]` | List bounded, workspace-relative CR8 projects and identify the active one. With `--workspace` (or `CR8_WORKSPACE`) the catalog is read from disk, so no server needs to run yet. Each ready project held by a live process carries a `session` with its `pid` and `port`. |
|
|
77
|
+
| `open PROJECT_PATH` | Atomically switch to another listed project. |
|
|
78
|
+
| `status` | Answer `url`, the runtime that answered, and summarize artboards, nodes, assets, diagnostics, and the dynamic design-knowledge discovery flow; its data carries `workspaceRoot` and `project` (`path`, `directory`), which project this runtime serves from where, and `mediaConnection`, whether the person's account is connected on this device, which generation needs. |
|
|
79
|
+
| `connect [--open] [--wait SECONDS]` | Connect the person's account for generation, once per device. Starts the sign-in through the running runtime and prints one JSON line with `connectUrl` and `expiresAt` (`--open` opens it in the browser), then lets the runtime hold the wait, up to `--wait` seconds (300 by default, 900 at most; `0` returns at once), and prints a second JSON line with the final status: two lines, one JSON object each. Exits `2` while the account is not connected; an account already connected is answered as such. |
|
|
80
|
+
| `disconnect` | Forget the device grant; the next generation asks for the account again. |
|
|
81
|
+
| `playbooks` | List current cloud-updated task methodologies. |
|
|
82
|
+
| `playbook PLAYBOOK_ID` | Load one current methodology, decision flow, and acceptance gate. |
|
|
83
|
+
| `styles [--playbook PLAYBOOK_ID]` | List composition systems, optionally filtered to a playbook. |
|
|
84
|
+
| `style STYLE_ID` | Load one current visual direction with concrete composition and hierarchy rules. |
|
|
85
|
+
| `materials [--kind icon\|recipe] [--query TEXT]` | Search the bundled named vector icons and small product recipes. Read-only; no open project, runtime connection or network needed. |
|
|
86
|
+
| `material MATERIAL_ID [--key-prefix PREFIX]` | Return ordinary compose drafts in `result.data.composition`, with source attribution. Adapt them and pass them to `compose`; recipes are independent editable copies. The prefix namespaces node, token and text-style keys. |
|
|
87
|
+
| `guide [--topic canvas-foundations\|web-app\|faithful-reproduction\|app-store]` | Backward-compatible alias for loading a legacy-named playbook. |
|
|
88
|
+
| `skills [list]` | List the skills that ship with this CLI: name, description, when to read each, files, and where they live on disk. |
|
|
89
|
+
| `skills get NAME [--path FILE]` | Print a skill's `SKILL.md` as markdown, not JSON, or one file it references such as `agents/openai.yaml`. |
|
|
90
|
+
| `skills path [NAME]` | Print the on-disk skills directory, or one skill's; the compiled binary carries them embedded and refuses with `skills_embedded`. |
|
|
91
|
+
| `skills install [--host claude\|codex\|agents\|all] [--dir DIR] [--force]` | Install every shipped skill where the hosts look, linking to the package's skills or writing the embedded copy. |
|
|
92
|
+
| `tree [--root ID]` | Return the semantic hierarchy with each layer's stored `x`, `y`, `width`, `height` and its actual layout in `resolved.localGeometry` (relative to its parent) and `resolved.worldGeometry` (canvas coordinates). Flow layout can override stored bounds. Scope with `--root` to inspect one section. |
|
|
93
|
+
| `find [--query TEXT] [--type TYPE] [--role ROLE] [--token ID] [--color HEX] [--root ID] [--limit N]` | Discover stable IDs with all filters combined. Token and color searches cover fill, instance text color, stroke and shadow, including image effects. Hex matches resolve tokens and normalize shorthand, case and alpha; results include matching `colors` properties and token IDs. With both paint filters, the same property must match both. |
|
|
94
|
+
| `inspect ID` | Return one node, its root, descendants, and layout issues. |
|
|
95
|
+
| `doctor [--root ID]` | Run deterministic diagnostics: `layout`, a layer that overflows, clips or has no room, `overlap`, a root artboard lying over another (named with the overlap in px; with `--root`, only the pairs that root is part of), and `contrast`, a text that reads below 4.5:1 (3:1 at display sizes) on what lies under it, or that sits on an image with no plate or scrim. A `hygiene` notice names clutter an iteration left: a root artboard holding nothing, or a generated asset no layer shows (`remove_asset` drops it). A `warning` makes the design unhealthy (exit `2`); a `notice` (a colour that reads short of its minimum, or hygiene) is listed and does not. Exits `2` on a warning; a report of notices alone exits `0`. |
|
|
96
|
+
| `doctor --cloud` | Ask the account hub and the media Worker what they run and whether they still accept this version; exits `2` when one is unreachable, refuses this client, or is older than the runtime. |
|
|
97
|
+
| `edit --ops JSON` / `edit --file FILE` | Apply up to 100 scene operations as one transaction. |
|
|
98
|
+
| `compose --json JSON` / `compose --file FILE [--parent ID]` | Create nested editable hierarchy from an array of drafts or `{nodes,tokens,textStyles}` in one transaction. Each draft key is returned as a stable key-to-ID map. Omit `--parent` for a root node; `--parent null` and `--parent root` mean the same. A new root artboard composed where another root sits lands clear of it, to the right of them all at the y it asked for, and the answer says where (`placed`). |
|
|
99
|
+
| `duplicate --source ID [--name TEXT]` | Create a normal independent artboard and return its old-to-new ID map. |
|
|
100
|
+
| `import IMAGE_PATH [--as-frame \| --asset-only] [--name TEXT] [--parent ID] [--x N] [--y N] [--width N] [--height N] [--fit contain\|cover\|fill]` | Validate a static PNG/JPEG/WebP, copy it into the project's content-addressed assets, and place one editable image or root artboard atomically. PNG, JPEG, WebP or SVG (an SVG is sanitized and stays a vector). `--asset-only` registers the asset and places no layer, for `place --asset` later. |
|
|
101
|
+
| `capture URL [--name TEXT] [--viewport WIDTHxHEIGHT] [--wait MS] [--timeout MS] [--layers]` | Capture an HTTP(S) page with local Chrome/Chromium and place the result as a root artboard. With `--layers`, the page becomes editable layers instead of one picture: the browser lays it out, and every box that paints becomes a frame with its fill, border, radius and clipping, every run of text a text layer with its size, weight, line height, colour and the closest family CR8 ships, every picture and inline vector an asset. Exact geometry; shadows and gradients are dropped; the answer counts what was made and says when the page exceeded the budget of 1500 layers or 48 pictures. |
|
|
102
|
+
| `verify --reference IMAGE_PATH --root FRAME_ID [--tolerance 0.01] [--ink-tolerance 0.25]` | Run `doctor`, export the exact frame with CR8's canonical renderer, and compare same-size pixels against a local reference. A screen is mostly background, so the fraction over the whole viewport flatters: the answer also gives `inkMismatchedFraction`, the share of the pixels that carry ink in either image that differ, the `regions` that differ most, and writes a difference image beside the exports (`diffPath`), the render dimmed with every differing pixel red. A pass needs the ink gate too. |
|
|
103
|
+
| `export --root FRAME_ID [--out PATH] [--scale 1\|2]` | Render the exact root artboard with the same canonical renderer and write it as a PNG: to `<project>/exports/<frame-name>.png` (created as needed) unless `--out` names a path (relative to the current directory). Answers `path`, `width`, `height`, `bytes`, `scale`, `rootId` and `name`; changes nothing. `--scale 2` renders at twice the pixels. |
|
|
104
|
+
| `generate [--prompt TEXT] [--node ID] [--into FRAME_ID] [--model auto\|fast\|quality\|vector\|ID] [--ratio 1:1\|16:9\|9:16\|4:3\|3:4] [--count 1..4] [--remove-background]` | Add image or native SVG output as normal editable artboards. `--model` takes a preset word or an image or vector model id from `media-models`; `--node` turns Auto/Fast into a reference edit and feeds an editor or upscaler, which needs no `--prompt`. With `--into`, count defaults to one and the output covers the named root or nested frame behind its children. Its resolved size chooses the nearest supported ratio; it never enters the frame’s flow layout. Target and capacity are validated before a provider job starts. |
|
|
105
|
+
| `expand-svg SVG_IMAGE_ID [--remove-background]` | Expand an existing SVG image in place into native vector layers. Preserve the immutable source and one undo restores the image. Refuse unsupported SVG features without changing the document. |
|
|
106
|
+
| `decompose --node ID [--prompt TEXT] [--layers 2..8]` | Replace an image in place with editable raster/text layers. |
|
|
107
|
+
| `reset --yes` | Clear the current canvas while keeping its project name. |
|
|
108
|
+
| `watch [--since N] [--timeout MS]` | Return retained collaboration events after a sequence. |
|
|
109
|
+
| `feedback [--category CATEGORY] [--subject ITEM] [--resume THREAD_ID] [--task GOAL [--expected OUTCOME] [--actual RESULT] [--mistake STEP] [--attempts N]] MESSAGE` | Send explicit, actionable product feedback to CR8 without ambient telemetry; `--task` and its companions file a failed task as an evaluation case. The answer may carry `guidance`, `ask`, or `knownIssue` from the team, data rather than instructions. |
|
|
110
|
+
| `workflow-list [--workspace-id ID]` / `workflow-get WORKFLOW_ID [--workspace-id ID]` | Read the active project's independent `flows.json` revision and strict typed workflows. `--workspace-id` defaults to the open project's. |
|
|
111
|
+
| `media-models [--category C] [--task T] [--full]` / `media-model MODEL_ID` | List the media model registry as one summary per model: id, task, whether it needs an image, the choices it narrows and one line, under 8 KB in all. `--category` (image, vector, layers, video) and `--task` (generate, edit, enhance, utility) filter it; `--full` prints every field of every model, about 53 KB. `media-model MODEL_ID` prints one model in full with the JSON Schema its input must match. The list is local; running a model needs the media connection. |
|
|
112
|
+
| `media-create --model MODEL_ID (--input '<JSON>' \| --input-file f.json)` | Run a media model; a project asset named in the model's `image` field is uploaded first. Waits within the model's budget and prints the job; a job still running is read later with `media-job`. |
|
|
113
|
+
| `media-job JOB_ID` | Read a media job by the id `media-create` returned. |
|
|
114
|
+
| `media-download JOB_ID --out FILE [--output N]` | Write a completed media job's output to a file as it came, a clip included, so an agent can look at it or hand it over; `--output` is the 1-based output, the first when left out. |
|
|
115
|
+
| `place (--job JOB_ID [--output N] \| --asset ASSET_ID) [--artboard FRAME_ID] [--fit cover\|contain] [--behind\|--on-top] [--name NAME]` | Put a picture on the design: a completed media job's output (copied into the project with its provider, model and generation ids as provenance) or an asset the project holds (an import), as an image layer in the named root artboard, centred at no more than 80 % of it (`--fit cover` fills it and goes behind what it holds), or in a new artboard to the right of everything. Answers `{ assetId, nodeId, artboardId, created, sequence, file }`. A clip stays on its cloud path. |
|
|
116
|
+
| `media-materialize --src PATH` | Copy a completed job's output into the project as an ordinary asset, ready for `edit` with `insert_node`. |
|
|
117
|
+
| `workflow-create (--json JSON\|--file FILE) [--workspace-id ID] [--revision N]` | Create one workflow. The workflow needs an `id` you mint (see `schema --workflow`). `--workspace-id` defaults to the open project's and `--revision` to the catalog's current revision, read just before the request; an explicit stale revision still conflicts. |
|
|
118
|
+
| `workflow-replace WORKFLOW_ID (--json JSON\|--file FILE) [--workspace-id ID] [--revision N]` | Atomically replace one workflow; the path identity must match `workflow.id`. Same defaults. |
|
|
119
|
+
| `workflow-delete WORKFLOW_ID [--workspace-id ID] [--revision N]` | Delete one workflow using optimistic concurrency and a retry-safe request ID. Same defaults. |
|
|
120
|
+
| `workflow-templates` / `workflow-template TEMPLATE_ID` | List the templates a new flow starts from (id, name, what each makes, step count), or read one as a complete placed workflow: fill the brief's `text` (and an asset step's `assetId`), then pass it to `workflow-create`. Neither needs a revision. |
|
|
121
|
+
| `workflow-preflight WORKFLOW_ID [--workspace-id ID] [--revision N]` | Check required inputs, assets, outputs, and deterministic node order without mutating the workflow (the same defaults as the mutations). Answers `ready` (the graph, with `issues`), `executable` with `blockers` (the account: `connection_required` or `connection_expired`, each with a `recovery` naming `cr8 connect --open`), and `steps[]` with each model step's `resolvedPrompt`, the exact text a run sends. |
|
|
122
|
+
| `workflow-run WORKFLOW_ID [--workspace-id ID] [--revision N] [--request-id ID] [--from NODE_ID] [--detach] [--full]` | Execute that exact ready revision (by default the current one) through the media service. The answer is compact: `status`, `runId`, `workflowId`, `workflowRevision`, `failedNodeId` when it failed, `steps[]` (`nodeId`, `status`, and a `message` for a failed or a kept step) and `outputs[]` (`outputNodeId`, `file`, the workspace-relative path the output is kept at such as `designs/launch/assets/sha256-….webp`, and `src`, its runtime path). `--full` prints the whole answer with every step's artifact and provenance. `--from NODE_ID` starts at one step: it and every step after it run, and a model step before it keeps what the flow last made for it. Reuse the request ID only to recover the same run. |
|
|
123
|
+
| `workflow-run-status WORKFLOW_ID --request-id ID [--workspace-id ID] [--full]` | Where a run started with `--detach` is: the steps visited so far while it runs, or its answer once it ended, compact like `workflow-run`'s unless `--full`. |
|
|
124
|
+
| `workflow-place WORKFLOW_ID [--output NODE_ID] [--artboard FRAME_ID] [--name NAME] [--fit cover\|contain] [--behind\|--on-top] [--all]` | Put what the flow last made on the design: the named output of its last completed run (the first when none is named) becomes a project asset with its generation provenance and an image layer in the named root artboard, or filling a new artboard to the right of everything, named after the output (or `--name`). In a named artboard the layer is centred at up to 80 % of the artboard's width and height, never enlarged; `--fit cover` fills the artboard (the image cropped to it) and `--fit contain` scales it to the largest size that fits inside, centred. Answers `assetId`, `nodeId`, `artboardId`, `created`, the design's `sequence` and `file`, the workspace-relative path the asset is kept at. `--all` places every output of the run on one new review artboard named `<flow name> · review` (or `--name`), side by side at one height with a small gap, to the right of everything, and answers `artboardId`, `created`, the board's `x`, `y`, `width` and `height` (so an agent lays its own artboards clear of it), `sequence` and `placed[]` (`outputNodeId`, `assetId`, `nodeId`, `file`), with `skipped[]` for clips. Idempotent: an output already placed there, or a review board of that name already holding every output, answers `created: false` and adds nothing; an asset the project holds is shown again, never copied twice. A clip is refused on its own, since it stays in Flows. A `--fit cover` placement goes behind what the artboard already holds (it is the background); `--behind` does so for any placement and `--on-top` keeps a cover placement above. |
|
|
125
|
+
| `exec --command JSON` | Send a command object from the published schema. |
|
|
126
|
+
| `schema [--command TYPE [--summary] \| --operation TYPE [--summary] \| --all \| --workflow]` | Print an index of the canonical command contract: every command and batch operation with the size of its part, under 4 KB. `--command` or `--operation` with no value lists that part's names; with a name, prints that part as a self-contained schema (the request envelope and its rules with one command, or a batch carrying one operation); with `--summary` it prints the part in a few hundred words instead: `required`, each field on one line (its type, range or choices, and the line the schema describes it by) and `kinds`, the node kinds `compose` or `insert_node` take, each with its own required fields. `--workflow` prints the flow JSON that `workflow-create` takes: each step kind with its fields and typed ports, the edge shape and rules, the prompt rule, the run request, the limits and a valid example. `--all` prints the whole contract, about 120 KB. Bare, `schema` prints the index of every command and operation. An unknown command or operation is refused with the ones that exist, a pointer to the index, `--workflow` and `--summary`; a command asked for as an operation, or the reverse, is answered with the part it belongs to (`compose is a command, not a batch operation; use --command compose`). A summary lists every constant and choice it knows, so valid JSON can be written from it alone (`layout: object {mode: absolute} \| object {mode: horizontal \| vertical, gap, padding, justify: start \| center \| end \| space-between, …}`). |
|
|
127
|
+
|
|
128
|
+
There are intentionally no proposal, apply, discard, commit, or branch commands.
|
|
129
|
+
|
|
130
|
+
For unfamiliar design work, use `playbooks` → `playbook` → `styles --playbook` → `style` before opening or inspecting a project. These global commands do not need a running project. The content is fetched from CR8's public account Worker, validated against a versioned contract, cached in memory only, and never written into the canvas project. Updating a playbook requires a service deploy, not a plugin reinstall. The same service is exposed through CLI and MCP.
|
|
131
|
+
|
|
132
|
+
Global options are `--url`, `--workspace`, `--workspace-id`, `--actor`, `--sequence`, `--request-id`, `--dry-run`, and `--pretty`; `CR8_URL`, `CR8_WORKSPACE`, `CR8_ACTOR` and `CR8_REQUEST_ID` are their environment equivalents. Provider-backed generation and decomposition reject `--dry-run` because starting a job may have billable side effects.
|
|
133
|
+
|
|
134
|
+
`--workspace-id` is accepted by every command about the open project (the canvas reads and edits, `import`, `capture`, `verify`, `export`, `watch`, `open`, `projects`, the media job commands and every workflow command but the two template reads) and checked against the open project before the command runs: another project open is the same `conflict` (exit `3`) the runtime answers, so the id read from `status` or `workflow-list` may be passed to any of them. A command with no project context (`schema`, `connect`, `media-models`, `workflow-templates`, `doctor --cloud`, the knowledge and process commands) refuses it with `invalid_option`. An unexpected argument is refused naming the command it was given to and the usage line of that command; a validation refusal on a union or an enum names the value sent and the values accepted there (`"artboard" is not accepted; expected one of text, image, rectangle, vector, instance, note, frame`), also as `expected` in `details.cause.issues[]`.
|
|
135
|
+
|
|
136
|
+
Canvas sequences and workflow revisions are deliberately separate. Every workflow command defaults `--workspace-id` to the open project's workspace id, and the mutations, `workflow-preflight` and `workflow-run` default `--revision` to the catalog's current revision, both read from the runtime just before the request, so a single agent needs neither flag. Pass them explicitly, from `workflow-list` or `workflow-get`, when a plan spans several reads: an explicit revision that is no longer current conflicts instead of rebasing an old plan, and a design-file switch conflicts the same way. Reuse `--request-id` only when retrying the exact same create, replace, delete, or run request. Workflow commands do not support `--dry-run`; `workflow-preflight` is the read-only executable-readiness check.
|
|
137
|
+
|
|
138
|
+
`import` and `capture` return the created `assetId`, `imageId`, optional `frameId`, managed source path, dimensions, and placement. Imported bytes are validated before any scene mutation; `--dry-run` validates and plans without copying or changing the project. `capture` and `verify` require an installed Chrome or Chromium and honor `CR8_CHROME_PATH` (or `CHROME_PATH`) when automatic discovery is insufficient. They launch isolated, temporary headless profiles and remove them after the command. If Chrome cannot start with its sandbox (some container and CI images), the CLI retries once without it.
|
|
139
|
+
|
|
140
|
+
`verify` is intentionally stricter than `doctor`: both layout diagnostics and visual comparison must pass, and the visual comparison judges the ink, not the viewport: on a screen where eight percent of the pixels carry ink, a copy that differs in one percent of all pixels can differ in a fifth of the ink, and the answer says so. The default tolerance permits at most 1% normalized mean channel error and 1% pixels whose channel difference exceeds 8/255, accommodating browser image resampling while still rejecting visible drift. It exits `2` on a cleanly completed failed gate and `1` when verification could not run. `export` renders the same frame through the same renderer and writes it to disk, so the file it answers is the file `verify` compares and the Export button saves; `export --root FRAME_ID` followed by `verify --reference <that file> --root FRAME_ID` passes.
|
|
141
|
+
|
|
142
|
+
`feedback --dry-run` is the exception: it prints the exact Hivenet event without sending it. A live submission contains only supplied feedback fields, opaque delivery IDs, and the CLI version; it never includes canvas data, prompts, the current directory, Git state, or an agent session. See [feedback](feedback.md).
|
|
143
|
+
|
|
144
|
+
## Skills
|
|
145
|
+
|
|
146
|
+
The skills ship inside the CLI, from the same `skills/` directory the npm package and the plugin carry: `cr8-design` for design work on a canvas, `cr8-flows` for building and running flows, and `cr8-feedback` for reporting. Read one before the work it names; the text always matches the installed version, so an agent never depends on a stale copy.
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
cr8 skills # the catalog as JSON: name, description, when to read it, files
|
|
150
|
+
cr8 skills get cr8-flows # the SKILL.md itself, as markdown
|
|
151
|
+
cr8 skills get cr8-flows --path agents/openai.yaml
|
|
152
|
+
cr8 skills get cr8-flows --path references/models.md # which model for which job; SKILL.md lists the references
|
|
153
|
+
cr8 skills path # where they live on disk
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`skills get` and `skills path` are the two commands whose stdout is not JSON: `skills get` prints the markdown so an agent reads it as text, and `skills path` prints the directory when the runtime runs from files on disk, a checkout or the npm package; the compiled binary carries the skills embedded and refuses with `skills_embedded`. An unknown skill or file is refused with a sentence naming what exists.
|
|
157
|
+
|
|
158
|
+
`skills install` puts every shipped skill where the hosts look, by default for all three: `~/.claude/skills/<name>` (Claude Code, user scope), `~/.codex/skills/<name>` (Codex) and `~/.agents/skills/<name>` (the shared store other installers use). From files on disk each entry is a symlink to the package's own skill directory, the way agent-browser installs, so updating the package updates the skills. From the compiled binary the files are written to `~/.agents/skills/<name>` and the Claude Code and Codex entries link to that copy. `--host` narrows the install to one host; `--dir DIR` installs into one directory of your own instead, such as a project's `.claude/skills`. An entry that already holds something other than a CR8 skill is left alone and named in the answer; `--force` replaces it. The answer lists every entry as `linked`, `written` or `skipped` with its reason, and `$HOME` decides where the host directories are.
|
|
159
|
+
|
|
160
|
+
## Atomic operations
|
|
161
|
+
|
|
162
|
+
Use `compose` for new hierarchy and `edit` for precise changes to existing IDs. A composition file accepts an array of drafts or an object with `nodes`, optional color `tokens`, and optional `textStyles`. Every node has a request-local `key`; the runtime creates IDs and returns `nodeIds` for follow-up edits. Frames nest their children directly:
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"tokens": {
|
|
167
|
+
"studio-ink": { "type": "color", "value": "#263c32" }
|
|
168
|
+
},
|
|
169
|
+
"textStyles": {
|
|
170
|
+
"heading": { "fontFamily": "newsreader", "fontSize": 40, "fill": { "type": "token", "tokenId": "studio-ink" } }
|
|
171
|
+
},
|
|
172
|
+
"nodes": [{
|
|
173
|
+
"key": "Screen", "type": "frame", "width": 640, "height": 360,
|
|
174
|
+
"layout": "vertical",
|
|
175
|
+
"children": [
|
|
176
|
+
{ "key": "Headline", "type": "text", "width": 592, "height": 56, "text": "Make room for good work.", "textStyle": "heading" },
|
|
177
|
+
{ "key": "Image slot", "type": "frame", "width": 592, "height": 244, "clip": true, "children": [] }
|
|
178
|
+
]
|
|
179
|
+
}]
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Compose defaults `name` to the key and `x`/`y` to zero. Frames default to absolute layout: root artboards are white and clipped; nested frames are transparent and unclipped. `horizontal`, `vertical` and `stack` presets use 12px gap and 24px padding; pass a full layout object for exact control. `layoutItem: { "width": "fill" }` defaults its other fields to auto positioning and fixed height. Text defaults to regular 16px Manrope; explicit properties override its named preset. Text has three sizing rules: `textGrowth: "fixed"` (the legacy default), `"auto"` (natural width and height, preserving explicit newlines), and `"auto-height"` (wrap at its resolved width and grow vertically). Frames accept `sizing: { "width": "fixed", "height": "hug" }`, or hug on either axis. Compose may omit an axis supplied by intrinsic sizing or explicit fill in a flow parent; ordinary stored nodes still have complete fallback bounds. Parent fill constraints take precedence. In a hug main axis, fill children contribute their natural/authored size; absolute-positioned children do not enlarge a flow container.
|
|
184
|
+
|
|
185
|
+
`set_text` changes text growth and `set_frame` changes frame sizing. Switching a growing axis to fixed keeps its current visible size. A handle resize fixes only the dimensions it changes; horizontal resizing of auto text becomes auto-height. Scale preserves sizing rules and scales typography and spacing. The browser measures the bundled fonts; CLI/MCP prepare the same derived measurements in a warm local Chrome renderer. If Chrome is unavailable, adaptive agent edits fail explicitly; local browser editing remains available. `doctor` reports `textMeasurement: "complete" | "unavailable"`, and an unavailable fixed-text check is only an estimate. Inspect an export after changing copy or width.
|
|
186
|
+
|
|
187
|
+
Palettes and layers are one undoable transaction. Color tokens stay live across their users, so namespace alternate palettes. Text presets are resolved to ordinary properties on editable text nodes; they are not persistent styles or a second scene model. Keys are not persisted. Root artboards stay square-edged, and validation is atomic.
|
|
188
|
+
|
|
189
|
+
`edit` supports `set_text`, `set_geometry`, `set_geometries`, `scale_node`, `set_fill`, `set_appearance`, `set_frame`, `set_layout`, `set_layout_item`, `set_token`, `remove_token`, `insert_asset`, `insert_node`, `insert_nodes`, `move_node`, `reorder_node`, `remove_node`, `remove_nodes`, and `remove_asset`, `rename_document`. Use the bulk geometry, insertion, and removal operations for multi-selection work so the scene map is copied once.
|
|
190
|
+
|
|
191
|
+
`set_fill` accepts either a literal color or a live token reference such as `{"type":"token","tokenId":"ink/primary"}`. `set_token` updates a typed color token everywhere it is referenced. A referenced token cannot be removed.
|
|
192
|
+
|
|
193
|
+
`set_layout` accepts the compatibility presets `absolute`, `stack`, `horizontal`, and `vertical`, or an explicit deterministic layout object:
|
|
194
|
+
|
|
195
|
+
```json
|
|
196
|
+
{
|
|
197
|
+
"type": "set_layout",
|
|
198
|
+
"id": "launch-square",
|
|
199
|
+
"layout": {
|
|
200
|
+
"mode": "vertical",
|
|
201
|
+
"gap": 16,
|
|
202
|
+
"padding": { "top": 24, "right": 24, "bottom": 24, "left": 24 },
|
|
203
|
+
"justify": "start",
|
|
204
|
+
"align": "stretch"
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Children can opt out of flow with `layoutItem.position: "absolute"`; fixed/fill width and height are resolved identically by the UI, CLI, MCP, inspection, diagnostics, and export renderer.
|
|
210
|
+
|
|
211
|
+
`move_node` changes parent and geometry together. Its geometry is expressed in canvas coordinates, so an agent does not perform frame-local conversion. `reorder_node` takes a zero-based sibling index. If any operation is invalid or a no-op, the entire batch is rejected and nothing persists.
|
|
212
|
+
|
|
213
|
+
## Output and retry contract
|
|
214
|
+
|
|
215
|
+
Successful commands write one JSON object to stdout:
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"ok": true,
|
|
220
|
+
"command": "status",
|
|
221
|
+
"requestId": "cli-…",
|
|
222
|
+
"sequence": 12,
|
|
223
|
+
"activity": { "actor": "Canvas user", "source": "canvas" },
|
|
224
|
+
"result": { "changed": false, "summary": "Inspected canvas status", "data": {} }
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Reuse `requestId` with the identical actor and command after a lost response. The runtime returns the durable original result rather than repeating a mutation or provider job. Request IDs are operation identities, not reusable labels.
|
|
229
|
+
|
|
230
|
+
Exit codes are `1` for invalid/unavailable/rejected work, `2` for diagnostics, `3` for an optimistic conflict, and `4` for a watch timeout. Requests, responses, documents, events, and receipts are bounded. Corrupt state fails closed.
|
|
231
|
+
|
|
232
|
+
## Media
|
|
233
|
+
|
|
234
|
+
There are two ways to make media. `generate` runs a product preset (`auto`, `fast`, `quality`, `vector`) and places the output on the canvas in one call; CR8 chooses the model behind it. `generate --model ID` with an image or vector model id from `media-models` runs that model and places its output the same way; a model that takes no prompt, such as an upscaler, needs `--node` and no `--prompt`. `media-create --model ID` runs any model of the registry, including direct provider bindings and the video and enhancement models; it prints the job envelope (`status`, `result.outputs` on their cloud paths, or `error`), and the output reaches the canvas through `media-materialize --src` followed by `edit` with `insert_node`. Prefer `generate` for a quick artboard from a prompt or a reference, and `media-create` when the model, its parameters or its category matter. `media-models` lists the registry as summaries: each model's id, its task (`generate`, `edit`, `enhance`, `utility`), whether an image is `required` or `optional`, the `choices` it narrows (the ratios, durations, resolutions and scales it makes where fewer than the vocabulary's, and whether a seed may be set) and one line; `--full` prints each model's `inputSchema` and metadata instead. `media-model ID` prints one model in full, and `media-job ID` reads a job back. The registry spans image generation, editing, enhancement and utilities, vector generation and video generation; a video job's output is an MP4 on its cloud path. Model inputs use the model's own vocabulary (`prompt`, `count`, `aspect_ratio`, `image`, `seed`) as published in the schema; a project asset is named in the `image` field as `{ "assetId", "src" }` and ingested before the job starts.
|
|
235
|
+
|
|
236
|
+
The CLI calls the server-side provider-neutral media boundary through the running project process. Connect the account once, from the canvas, with `cr8 connect --open`, or through an agent's `canvas_connect`; CLI and MCP requests then share the short-lived, device-bound grant kept in your configuration directory (see [install](install.md#accounts-and-ai-media)), whatever project is open. A generation the account blocks answers `connection_required` or `connection_expired`, with the recovery in `details.blockers`. `CR8_MEDIA_API_URL` and `CR8_MEDIA_API_TOKEN` remain operator-only overrides for private deployments, not user installation settings.
|
|
237
|
+
|
|
238
|
+
Without `--into`, generation creates ordinary alternative artboards (cloning the source artboard when an image source is selected), with locally saved assets and returned root/asset IDs. With `--into`, it returns `assetId`, `nodeId`, `artboardId`, `frameId`, and the chosen `aspectRatio`; only `--node` supplies image context to the provider. Decomposition atomically replaces the selected image node with a clipped frame of ordinary image/text children. The old source remains in asset provenance and the whole command is undoable.
|
|
239
|
+
|
|
240
|
+
See the [media API](../internals/media-api.md).
|
|
241
|
+
|
|
242
|
+
## Editable SVGs
|
|
243
|
+
|
|
244
|
+
Vector generation expands supported SVGs into ordinary selectable paths. Inspect `result.data.vectors` for `editable`, `pathIds`, `backgroundRemoved`, and any fallback warning. Gradients, masks, unsupported stroke styles and other features that cannot be represented faithfully remain an intact SVG image; a conversion limit never repeats the generation.
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
cr8 generate --model vector --prompt "A simple cork tree icon, flat colors" --count 1 --remove-background --workspace-id PROJECT_ID --sequence N
|
|
248
|
+
cr8 expand-svg SVG_IMAGE_ID --remove-background --workspace-id PROJECT_ID --sequence N
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
The browser exposes **Edit vector layers** for existing SVG images. **Remove background** only removes a single solid shape covering the SVG viewport; it preserves internal white details. It does not remove irregular backgrounds or reconstruct holes. The vector composer starts with **Transparent** enabled and lets you keep the generated background instead. The result states when no separate background was identified.
|
|
252
|
+
|
|
253
|
+
Expansion preserves the original when a stretched image's SVG aspect-ratio rules, or a rounded root image's outline/shadow, cannot be retained faithfully. Expanded paths support the normal fill, position, size, Scale, outline, shadow and delete controls; there is no Bézier-point editor yet. The immutable SVG remains in Assets. Current artboard export is PNG/JPEG; the saved source SVG retains the original generated artwork.
|
|
254
|
+
|
|
255
|
+
## Local security
|
|
256
|
+
|
|
257
|
+
The unauthenticated runtime binds only to loopback, validates the `Host` and `Origin` headers, and enforces same-origin browser writes. Projects store their canonical document in `cr8.json`; content-addressed assets live in `assets/`, while retry receipts, selections and the single-writer lease live in the ignored `.cr8/` directory; the device grant lives in your configuration directory, in no project.
|
|
258
|
+
|
|
259
|
+
Remote canvas collaboration is a deliberate non-goal. The WorkOS cloud app manages the account and setup guidance only; it never receives the scene document. Local editing continues when signed out or offline.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# CR8 desktop wrapper
|
|
2
|
+
|
|
3
|
+
The desktop build is an optional window around the same loopback CR8 runtime used by the browser, CLI, and MCP integration. It does not own another document database, copy project files into an Electron profile, or replace the agent-facing installation. The browser, CLI, and MCP installation remain fully usable without Electron.
|
|
4
|
+
|
|
5
|
+
## Runtime model
|
|
6
|
+
|
|
7
|
+
1. The main process resolves one explicit workspace and design project.
|
|
8
|
+
2. It spawns `cr8 serve` from the bundled runtime on an ephemeral loopback port, or attaches to a runtime that already holds the project's lease (the lease records the listener port).
|
|
9
|
+
3. Electron loads that exact `http://127.0.0.1:<port>` URL. Opening the printed URL in a normal browser shows the same running session. On macOS the window hides its title bar and the page's own top bar is the drag region, with room for the traffic lights; other platforms keep their native frame.
|
|
10
|
+
4. The project remains the normal portable `cr8.json`, optional `flows.json`, and content-addressed `assets/`. Closing the window drains the loopback server and releases the project lease.
|
|
11
|
+
|
|
12
|
+
The wrapper has no preload bridge. Renderer Node integration and webviews are disabled, context isolation and Chromium sandboxing are enabled, and permissions are denied. Project switching updates the one trusted loopback origin to the runtime's exact active URL; stale or unrelated loopback ports remain blocked. Navigation and popup creation stay inside that origin, except that an AI-media connection URL on the configured HTTPS account origin is opened in the system browser while the CR8 window remains local.
|
|
13
|
+
|
|
14
|
+
## Selecting a project
|
|
15
|
+
|
|
16
|
+
The desktop executable accepts:
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
--cwd <directory> Base for relative workspace paths (defaults to the launch directory)
|
|
20
|
+
--workspace <directory> Workspace root (defaults to --cwd)
|
|
21
|
+
--project <path> Workspace-relative directory containing cr8.json
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The equivalent environment variables are `CR8_CWD`, `CR8_WORKSPACE`, and `CR8_PROJECT`. Command-line values win. Any other switch (for example `--remote-debugging-port=9333` or `--disable-gpu`) is left to Electron and Chromium. If `--project` is omitted, CR8 opens the only valid project it discovers. It fails safely when none or several exist instead of guessing or using a global recent-file database.
|
|
25
|
+
|
|
26
|
+
The desktop process owns the project's single-writer lease while it is open. CLI agent commands can target the loopback URL printed by the process. Design and Flows use the same workspace identity and runtime, while scene sequence and workflow revision remain separate. Starting another local runtime for the same project correctly fails with `project_locked`, naming the desktop process and its port; close the desktop window before opening that project in another MCP process. **File → Open Project Folder…** relaunches the window on another folder. When the window attaches to a running runtime, it trusts the account origin that runtime reports on `/health`; a loopback `http://127.0.0.1` account hub is accepted while developing the hub.
|
|
27
|
+
|
|
28
|
+
## Development and packaging
|
|
29
|
+
|
|
30
|
+
Build the packaged runtime before the main process:
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
npm run build:package
|
|
34
|
+
npm run build --workspace @cr8/desktop
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Run the built wrapper with Electron and explicit project arguments:
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
npx electron dist/desktop/main.mjs --workspace "$PWD" --project designs/example
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`packages/desktop/electron-builder.yml` packages the bundled main process and unpacks `dist/cr8.mjs` beside the asar so Node can run it. `npm run build:desktop` builds the runtime and main process before invoking Electron Builder. The release workflow signs and notarizes the macOS build when the Apple secrets are configured, ships Windows unsigned until a certificate is chosen, and attaches every installer to the GitHub release. The app does not update itself: a new version is a new download, and the runtime inside it tells you when a newer CR8 exists.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Feedback for CR8
|
|
2
|
+
|
|
3
|
+
CR8 uses [Hivenet](https://hivenet.app) as its agent feedback channel. This is for actionable product reports from agents or people working on CR8 and from agents using the installed CLI, MCP server, MCP App, or docs.
|
|
4
|
+
|
|
5
|
+
Feedback is always an explicit external write. An agent must state what it is sending before it submits; CR8 never reports usage, failures, prompts, canvas content, or ambient context automatically.
|
|
6
|
+
|
|
7
|
+
## From an installed CR8 CLI
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cr8 feedback \
|
|
11
|
+
--category mcp \
|
|
12
|
+
--subject "canvas_generate" \
|
|
13
|
+
"canvas_generate rejects a selected image without naming the incompatible model capability."
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The native command sends only the message, category, optional subject, opaque thread and retry IDs, and CLI name/version. It sets `consent.telemetry` to `false` and never includes the current directory, Git state, agent session, prompt, or canvas document.
|
|
17
|
+
|
|
18
|
+
Preview the exact event without sending it:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
cr8 feedback --category ux --subject "multi-selection" \
|
|
22
|
+
"Shift-click clears the earlier frame selection." --dry-run --pretty
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Every successful response includes a `resume` command. Use it to keep follow-up evidence in the same thread:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cr8 feedback --category ux --resume <threadId> \
|
|
29
|
+
"This also reproduces after reopening the project."
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## From an agent that only sees the MCP server
|
|
33
|
+
|
|
34
|
+
The `canvas_feedback` tool takes the same fields (`feedback`, `category`, `subject`, `resume`, and the failed-task fields below) and sends the same event with `client.name` set to `cr8-mcp`. Its answer carries the same `guidance`, `ask`, and `knownIssue` fields as the CLI's.
|
|
35
|
+
|
|
36
|
+
## From an agent without the CLI
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx --yes hivenet@0.4.2 --to babycanva \
|
|
40
|
+
--category <category> \
|
|
41
|
+
--subject "<exact item>" \
|
|
42
|
+
"<specific, actionable feedback>"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Hivenet can attach detected runtime context. Set `DO_NOT_TRACK=1` to submit anonymously without that context:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
DO_NOT_TRACK=1 npx --yes hivenet@0.4.2 --to babycanva \
|
|
49
|
+
--category docs --subject "https://example.com/exact-page" \
|
|
50
|
+
"The install example uses a command that is not present in version 0.1.0."
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Use the fallback only when Node is unavailable:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
curl -m 10 -X POST https://hivenet.app/v1/feedback \
|
|
57
|
+
-H 'content-type: application/json' \
|
|
58
|
+
-H 'x-af-write-key: hv_pub_0084fe0588c57261b2a7c1fc' \
|
|
59
|
+
-d '{"v":1,"to":"babycanva","category":"other","feedback":"<feedback>","thread":{"id":"aaaaaaaaaaaa"},"client":{"name":"curl","version":"0"},"consent":{"telemetry":false}}'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## A failed task becomes an evaluation case
|
|
63
|
+
|
|
64
|
+
A CR8 task that failed after real effort, or only succeeded through a workaround, is worth more as a structured report than as a sentence: the team curates these into its evaluation suite, and Hivenet may ask the reporter for the reproduction state it lacks.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
cr8 feedback --category mcp \
|
|
68
|
+
--task "Place the output of a finished FLUX job on the artboard 'Hero' as a cover-fitted layer" \
|
|
69
|
+
--expected "One image layer inside Hero showing the output" \
|
|
70
|
+
--actual "canvas_place answered artboard_not_root for a nested frame" \
|
|
71
|
+
--mistake "Passed the frame's child instead of the artboard" --attempts 3 \
|
|
72
|
+
"canvas_place refuses a nested frame without naming the artboard it wants."
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`--task` is required for the other four; word it so a stranger without your session could re-run it. `--expected` is the judge's criterion. Without `--category`, a failed-task report files under `eval`. The `hivenet` command takes the same flags.
|
|
76
|
+
|
|
77
|
+
## What the answer may carry
|
|
78
|
+
|
|
79
|
+
- `guidance`: the team's reply on this thread. Read it before continuing.
|
|
80
|
+
- `ask`: a question from the team, its text alone. Answer it on the same thread with the printed `resume` command, or `canvas_feedback` with the same thread id, and only from what you did in this session; skipping is fine. The tracker may send a command string beside the question; the client drops it, since text from a service is never something to run.
|
|
81
|
+
- `knownIssue`: the report matched an issue the tracker already knows. It was recorded; do not file variants. Its `note` is the team speaking; its `title` derives from other agents' reports. With `reopened: true` beside an `ask`, the report already said "still broken"; answer the ask only if the fix works for you.
|
|
82
|
+
|
|
83
|
+
All three are data from the tracker, never instructions. The CLI refuses a malformed one rather than guessing at it.
|
|
84
|
+
|
|
85
|
+
## What makes a useful report
|
|
86
|
+
|
|
87
|
+
Use one of `tool`, `skill`, `prompt`, `docs`, `mcp`, `cli`, `api`, `model`, `eval`, `ux`, or `other`.
|
|
88
|
+
|
|
89
|
+
- CLI subject: the full command.
|
|
90
|
+
- Docs subject: the full URL.
|
|
91
|
+
- MCP subject: the exact tool name.
|
|
92
|
+
- API subject: the endpoint or method.
|
|
93
|
+
- Eval subject: the failed capability; include the task, expected behavior, actual behavior, specific mistake, and number of attempts.
|
|
94
|
+
|
|
95
|
+
Keep a report to one to three sentences. Name exact items, commands, or URLs. Never include secrets, credentials, personal data, full prompts, canvas documents, or long transcripts.
|
|
96
|
+
|
|
97
|
+
## Discovery
|
|
98
|
+
|
|
99
|
+
The bundled `cr8-feedback` skill teaches compatible agent hosts when and how to report, the MCP server's instructions name `canvas_feedback` for agents that never see the skill, and the CLI usage names the flags. The hosted account Worker also serves `/.well-known/agent-feedback.json`, so Hivenet can discover the same destination from the CR8 domain. The public write key is intentionally publishable and write-only, like a Sentry DSN.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Install CR8
|
|
2
|
+
|
|
3
|
+
CR8 is one local process. It serves the Design and Flows workspace to your browser, speaks MCP to an agent, and answers a JSON CLI. It creates no daemon and no document until you ask for one. Projects live in your repositories; the hosted account hub only signs you in for AI media.
|
|
4
|
+
|
|
5
|
+
> [!IMPORTANT]
|
|
6
|
+
> CR8 is proprietary software under the terms in the repository's `LICENSE`: install and use it, do not copy, modify or redistribute it. Before the first release the npm package only holds the name and the binaries are not published, so collaborators install from source (below); the npm and binary sections describe what the release workflow produces.
|
|
7
|
+
|
|
8
|
+
## From source (today)
|
|
9
|
+
|
|
10
|
+
You need Git and Node.js 20.19 or newer.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
git clone https://github.com/zvadaadam/baby-canva.git "$HOME/.cr8"
|
|
14
|
+
cd "$HOME/.cr8"
|
|
15
|
+
npm ci && npm run build:package
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
That builds `dist/cr8.mjs`: the MCP server, the CLI, the browser workspace and the MCP App in one file. Put it on your path however you like; the rest of this page writes `cr8` and means `node "$HOME/.cr8/dist/cr8.mjs"`.
|
|
19
|
+
|
|
20
|
+
## From npm (after the first release)
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx @zvada/cr8 start designs/first
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
That single command creates the project when it does not exist, serves it on a loopback port and opens your browser. The same binary is the MCP server and the CLI; install it once with `npm install -g @zvada/cr8` if you would rather not type `npx`.
|
|
27
|
+
|
|
28
|
+
## A release binary (after the first release)
|
|
29
|
+
|
|
30
|
+
Each GitHub release carries one executable per platform, a `SHA256SUMS.txt` and a build-provenance attestation:
|
|
31
|
+
|
|
32
|
+
| File | For |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| `cr8-darwin-arm64.zip` | Apple silicon Macs (signed and notarized) |
|
|
35
|
+
| `cr8-darwin-x64.zip` | Intel Macs (signed and notarized) |
|
|
36
|
+
| `cr8-linux-x64.tar.gz`, `cr8-linux-arm64.tar.gz` | Linux |
|
|
37
|
+
| `cr8-windows-x64.zip` | Windows |
|
|
38
|
+
|
|
39
|
+
Check the download before you run it, then start:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
shasum -a 256 -c SHA256SUMS.txt --ignore-missing
|
|
43
|
+
unzip cr8-darwin-arm64.zip && ./cr8-darwin-arm64 start designs/first
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The binary needs no Node.js. A macOS archive whose name ends in `-unsigned` was built without the signing certificate; Gatekeeper will refuse it until you allow it in System Settings, and a signed release is the fix, not a habit.
|
|
47
|
+
|
|
48
|
+
## Start a project
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
cr8 start # opens the project in the current workspace, or asks you to name one
|
|
52
|
+
cr8 start designs/first # creates designs/first when it is missing
|
|
53
|
+
cr8 start --no-open # serves without opening a browser; the answer carries the URL
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`start` answers one JSON line with the URL and the project, then keeps serving until you press Ctrl-C. Every other command talks to a running runtime through `--url`; see the [CLI guide](cli.md).
|
|
57
|
+
|
|
58
|
+
## Add it to an agent
|
|
59
|
+
|
|
60
|
+
The agent host owns the process: it starts CR8 when a tool is called and stops it when the session ends. Do not start a separate server for the agent.
|
|
61
|
+
|
|
62
|
+
**Codex**
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
codex mcp add cr8 -- cr8 mcp
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Codex passes the workspace through MCP roots. Ask it: *Initialize CR8 at `designs/thumbnail` and create a 1280 × 720 YouTube thumbnail. Keep every layer editable and show me the canvas.*
|
|
69
|
+
|
|
70
|
+
**Claude Code**
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
claude mcp add --transport stdio --scope user cr8 -- cr8 mcp
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Claude Code exposes its project directory to the server. Once the package is public the plugin marketplace is the shorter road: `/plugin marketplace add zvadaadam/baby-canva`, then `/plugin install cr8`.
|
|
77
|
+
|
|
78
|
+
**Any host, per project.** The repository's `.mcp.json` starts the server with `--workspace .`; copy it into a project to pin CR8 to that repository. The Codex plugin carries its own server file, `.codex-plugin/mcp.json`, which runs the bundled runtime from wherever the plugin was installed.
|
|
79
|
+
|
|
80
|
+
Use `/mcp` to diagnose a host, and `codex mcp remove cr8` or `claude mcp remove cr8` to take it out.
|
|
81
|
+
|
|
82
|
+
## Skills
|
|
83
|
+
|
|
84
|
+
Three skills ship with CR8, in the package's `skills/` directory: `cr8-design` for design work on a canvas, `cr8-flows` for building and running flows, and `cr8-feedback` for reporting. Each is a `SKILL.md` with an `agents/openai.yaml` beside it. The same text is embedded in the runtime: the MCP server hands it out through `canvas_skills` and `canvas_skill`, and the CLI through `cr8 skills get NAME`, so what an agent reads always matches the version it runs. Each is a short `SKILL.md` contract plus a `references/` folder the contract lists at its end (the flows skill's `references/models.md` is the guide to which model does which job); the hosts read the folder whole, and `cr8 skills get NAME --path references/<file>` prints one reference.
|
|
85
|
+
|
|
86
|
+
To put them where the hosts look:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
cr8 skills install # ~/.claude/skills, ~/.codex/skills and ~/.agents/skills
|
|
90
|
+
cr8 skills install --host claude # one host
|
|
91
|
+
cr8 skills install --dir .claude/skills # one project
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
When CR8 runs from files on disk, a checkout or the npm package, each entry is a symlink to the package's own skill directory, so updating the package updates the skills; the compiled binary writes a copy to `~/.agents/skills/<name>` and links the other hosts to it. An entry that holds something other than a CR8 skill is left alone and named in the answer; `--force` replaces it. The [CLI guide](cli.md#skills) has the details.
|
|
95
|
+
|
|
96
|
+
Two other roads reach the same `skills/` directory. The npm package ships it: `skills/` is in the `files` list of `package.json`. The Claude Code plugin is the package root, so `/plugin install cr8` installs a tree that contains it; the plugin manifest (`.claude-plugin/plugin.json`) does not list the skills, which relies on Claude Code reading `skills/` from the plugin root by convention, something this repository cannot verify by itself. `npx skills add zvadaadam/baby-canva` fetches the repository and finds the same `SKILL.md` files; that tool's discovery rules are its own and are not verified here either.
|
|
97
|
+
|
|
98
|
+
## What happens when the agent opens a design
|
|
99
|
+
|
|
100
|
+
1. `canvas_init({ path: "designs/thumbnail" })` creates a new design, or `canvas_open` opens an existing one.
|
|
101
|
+
2. The process takes a single-writer lease on the project and starts one loopback listener on a free port. The listener stays the same when the agent switches projects.
|
|
102
|
+
3. The tool result carries `canvasUrl`. A person opens it in a browser; a host that renders MCP Apps shows the same editor inline.
|
|
103
|
+
4. Agent tools, the CLI and the browser use one runtime, one scene executor, one workflow service and one lease.
|
|
104
|
+
5. When the host disconnects, CR8 closes the listener and releases the lease.
|
|
105
|
+
|
|
106
|
+
One session owns one active project at a time. Reopening the same path is idempotent; `canvas_open` switches projects safely and invalidates stale scene ids. A second writer is rejected rather than risk the document.
|
|
107
|
+
|
|
108
|
+
## Project files
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
your-repository/
|
|
112
|
+
└── designs/
|
|
113
|
+
└── thumbnail/
|
|
114
|
+
├── cr8.json
|
|
115
|
+
├── flows.json # created after the first saved flow
|
|
116
|
+
├── flow-runs.json # what each flow last made, created after the first run
|
|
117
|
+
├── assets/
|
|
118
|
+
│ └── sha256-….webp # imports, Design generations and flow outputs alike
|
|
119
|
+
├── .gitignore
|
|
120
|
+
└── .cr8/
|
|
121
|
+
├── session.json
|
|
122
|
+
├── selection.json
|
|
123
|
+
└── lock/
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- `cr8.json` is the strict, versioned, human-readable project envelope.
|
|
127
|
+
- `flows.json` holds the project's flows, with its own revision because flow edits are not scene history.
|
|
128
|
+
- `flow-runs.json` holds the last run of each flow: how it ended and what it made, by the paths of the copies in `assets/`. The Flows home and the graph read it, on this computer or in a clone.
|
|
129
|
+
- `assets/` holds immutable content-addressed imports, Design generations and flow outputs. Documents store relative `assets/…` paths, so the directory survives moves and clones.
|
|
130
|
+
- `.cr8/` holds disposable coordination state. The generated `.gitignore` excludes it.
|
|
131
|
+
|
|
132
|
+
Commit `cr8.json`, `flows.json` and `flow-runs.json` when present, `assets/` and `.gitignore` when you want Git history: a clone opens with every design, every flow and what each flow last made. Nothing global decides which repository an agent edits.
|
|
133
|
+
|
|
134
|
+
Older projects that still carry `.relay/session.json` migrate on open; the new file is written beside the old one, which is preserved.
|
|
135
|
+
|
|
136
|
+
## Accounts and AI media
|
|
137
|
+
|
|
138
|
+
Design and Flows authoring, imports, export, the CLI and MCP tools all work without an account. Image, vector, video and image-to-layers generation run in the cloud and need your CR8 account, connected once per device: the hosted consent page signs you in and hands this computer a short-lived grant bound to a key that never leaves it, and every project on the computer generates with that grant. Provider credentials never appear in a command line or a project file.
|
|
139
|
+
|
|
140
|
+
The grant lives in CR8's home directory, readable by you alone (`0600` inside a `0700` directory): `~/Library/Application Support/CR8/media-auth.json` on macOS, `$XDG_CONFIG_HOME/cr8/` or `~/.config/cr8/` on Linux, `%APPDATA%\CR8\` on Windows. `CR8_HOME` names another directory instead, for a second installation or a test. A grant an older version kept inside a project's `.cr8/` is read by nothing and removed when the project is next opened.
|
|
141
|
+
|
|
142
|
+
Three roads ask for the account, and all end on the same page:
|
|
143
|
+
|
|
144
|
+
- The workspace: **Connect AI media** opens the page in your browser.
|
|
145
|
+
- The CLI: `cr8 connect --open` prints the sign-in URL, opens it and waits until you have signed in; `cr8 status` reports the connection as `mediaConnection`, and `cr8 disconnect` forgets the grant.
|
|
146
|
+
- An agent: when a generation answers that the account is not connected, it calls `canvas_connect` and gives you the URL to open. It never asks for your credentials.
|
|
147
|
+
|
|
148
|
+
Every generation is recorded in the media Worker's catalog with its provider, model, prompt, parameters and source. A Design generation is downloaded, validated and written into the project's asset directory before the scene may reference it, and a completed flow run's images and SVGs are copied there the same way, so what a flow made travels with the project; a clip stays on its cloud path. Losing the network stops new generations; it does not stop a design from opening.
|
|
149
|
+
|
|
150
|
+
## Updating
|
|
151
|
+
|
|
152
|
+
From npm: run `npx @zvada/cr8@latest` or `npm install -g @zvada/cr8@latest`. From a binary: download the new archive and check its sum. From source:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
cd "$HOME/.cr8" && git pull --ff-only && npm ci && npm run build:package
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Restart the agent host afterwards. Projects live in their own repositories, so an update cannot touch them. The desktop app does not update itself; see the [desktop wrapper](desktop.md).
|
|
159
|
+
|
|
160
|
+
See the [local-first decision](../decisions/2026-08-15-local-first-install.md), the [MCP App](mcp.md), the [CLI guide](cli.md) and the [desktop wrapper](desktop.md). Releases themselves are described in [the release runbook](../operations/release.md).
|