|
1 | 1 | # Monet — Claude Agent Guide |
2 | 2 |
|
| 3 | +## ⚠️ CANVAS MODE — MANDATORY RULES (read this first) |
| 4 | + |
| 5 | +When `activeView=canvas` is reported by the hook or `editorctl get-state`: |
| 6 | + |
| 7 | +**There are EXACTLY 3 canvas options. No others exist.** |
| 8 | +1. **Paper.js** — code drawing with vector graphics (`canvas-run-paperjs`) |
| 9 | +2. **Matter.js** — physics and animation (`canvas-run-matterjs`) |
| 10 | +3. **GPT image 2** — AI-generated image (`generate-image` + `canvas-add-image`) |
| 11 | + |
| 12 | +**REMOVED — do NOT offer these under any name:** |
| 13 | +- ~~Design mode~~ — removed |
| 14 | +- ~~Editable layers~~ — removed |
| 15 | +- ~~Figma-style layout~~ — removed |
| 16 | +- ~~Node-based design~~ — removed |
| 17 | +- ~~Direct canvas design~~ — removed |
| 18 | + |
| 19 | +When the user asks for something visual in canvas mode, present ONLY these three options using these EXACT labels. Copy them verbatim. Do not invent a fourth option or rephrase option 1 as anything design-related. |
| 20 | + |
| 21 | +## ⚠️ BRAND RULE — NO EXCEPTIONS (applies to ALL canvas work) |
| 22 | + |
| 23 | +**If the user's message contains ANY URL or domain name (e.g. `spotify.com`, `https://linear.app`, `notion.so`), you MUST fetch that page and extract brand tokens BEFORE writing a single line of canvas/design code.** |
| 24 | + |
| 25 | +Do not use assumed or memorized brand colors. Do not skip this step even if you think you know the brand. **Fetch first, design second — every time.** |
| 26 | + |
| 27 | +```bash |
| 28 | +# Step 1 — extract colors, fonts, border-radius |
| 29 | +curl -sL "<url>" | grep -Eo '(#[0-9a-fA-F]{3,8}|font-family:[^;"}]+|font-size:[^;"}]+|border-radius:[^;"}]+)' | sort -u | head -60 |
| 30 | + |
| 31 | +# Step 2 — find logo |
| 32 | +curl -sL "<url>" | grep -Eo '(src|href)="[^"]*logo[^"]*"' | head -10 |
| 33 | +curl -sL "<url>" | grep 'og:image' |
| 34 | +``` |
| 35 | + |
| 36 | +Extract and hard-code before coding: background & surface colors, primary/accent colors, text colors, font families, font sizes/weights, border radius, and logo. Never guess — if fetch fails, tell the user and ask them to paste the hex values. |
| 37 | + |
| 38 | +--- |
| 39 | + |
3 | 40 | Monet is an Electron video editor with terminal-first AI agent control. You have three interfaces: |
4 | 41 | 1. **MCP tools** (`video_editor_*`) — live timeline control via the MCP server |
5 | 42 | 2. **CLI** (`editorctl`) — direct commands from this terminal |
@@ -72,6 +109,131 @@ npx remotion render remotion/src/index.ts TitleCard out.mp4 --props '{"title":"H |
72 | 109 | - Rendered videos land in `remotion-renders/` as MP4 — drag into the Monet timeline or use `video_editor_render_remotion` which auto-imports. |
73 | 110 | - Zod schemas on compositions let you pass typed props from MCP. |
74 | 111 |
|
| 112 | +## Brand Aesthetic from a URL |
| 113 | + |
| 114 | +> **MANDATORY — NO EXCEPTIONS** |
| 115 | +> If the user's message contains any URL or domain name (e.g. `spotify.com`, `https://linear.app`, `notion.so`), you **MUST** fetch that page and extract its brand tokens **before writing a single line of canvas/design code**. Do not use assumed or memorized brand colors. Do not skip this step even if you think you know the brand. Fetch first, design second — every time. |
| 116 | +
|
| 117 | +```bash |
| 118 | +# Step 1 — fetch HTML and extract CSS tokens |
| 119 | +curl -sL "<url>" | grep -Eo '(#[0-9a-fA-F]{3,8}|font-family:[^;"}]+|font-size:[^;"}]+|border-radius:[^;"}]+)' | sort -u | head -60 |
| 120 | + |
| 121 | +# Step 2 — find logo |
| 122 | +curl -sL "<url>" | grep -Eo '(src|href)="[^"]*logo[^"]*"' | head -10 |
| 123 | +curl -sL "<url>" | grep 'og:image' |
| 124 | +``` |
| 125 | + |
| 126 | +Or use the WebFetch / browser tool to read the live page and its `<style>` tags / inline CSS. |
| 127 | + |
| 128 | +**Extract and note before coding:** |
| 129 | +| Token | Where to look | |
| 130 | +|-------|--------------| |
| 131 | +| Background & surface colors | `background`, `background-color`, CSS variables like `--bg`, `--surface` | |
| 132 | +| Primary / accent colors | Buttons, links, active states, `--primary`, `--accent` | |
| 133 | +| Text colors | `color` on `body`, headings, muted text | |
| 134 | +| Font families | `font-family` on `body` or headings | |
| 135 | +| Font sizes & weights | `font-size`, `font-weight` on headlines vs body | |
| 136 | +| Border radius | Cards, buttons, avatars | |
| 137 | +| Spacing scale | Padding/margin on cards and containers | |
| 138 | +| Shadows | `box-shadow` values | |
| 139 | +| **Logo** | `<img>` with `logo` in src/alt/class, inline `<svg>` in header/nav, `og:image` meta tag | |
| 140 | + |
| 141 | +**Also extract the logo.** The logo shape, color usage, and style (wordmark vs icon vs combination) tells you the brand's visual weight and personality. Use it to: |
| 142 | +- Match the exact brand colors (logos are the ground truth — more reliable than CSS variables) |
| 143 | +- Reproduce the logo mark as a canvas shape (e.g. a simplified SVG path drawn with `ctx`) when it adds authenticity to the frame |
| 144 | +- Set the tone: a geometric minimal logo = clean spacing + sans-serif; a bold serif logo = heavier weights + tighter layout |
| 145 | + |
| 146 | +```bash |
| 147 | +# Find logo URLs in the page |
| 148 | +curl -sL "<url>" | grep -Eo '(src|href)="[^"]*logo[^"]*"' | head -10 |
| 149 | +curl -sL "<url>" | grep -Eo 'content="[^"]*og:image[^"]*"' | head -5 |
| 150 | +# Or look at the og:image meta directly |
| 151 | +curl -sL "<url>" | grep 'og:image' |
| 152 | +``` |
| 153 | + |
| 154 | +**Then hard-code those exact values** into the Matter.js / Paper.js / HTML script. |
| 155 | + |
| 156 | +> ⛔ **Never use assumed/memorized brand colors when a URL was provided.** If the fetch fails, tell the user and ask them to paste the hex values — do not fall back to guessing. |
| 157 | +
|
| 158 | +--- |
| 159 | + |
| 160 | +## Canvas — Matter.js Physics Frames |
| 161 | + |
| 162 | +Use `canvas_run_matterjs` (MCP) or `editorctl canvas-run-matterjs <frameId> "<script>"` (CLI) to place a live physics scene on the canvas. |
| 163 | + |
| 164 | +### Two valid script patterns — pick ONE, never mix |
| 165 | + |
| 166 | +#### Pattern A — Self-contained (recommended for rich UIs) |
| 167 | +The script creates and owns the engine, render loop, and runner. Use this when you need custom drawing (Canvas 2D API), manual `Engine.update`, or `requestAnimationFrame`. |
| 168 | + |
| 169 | +```js |
| 170 | +// ✅ Pattern A — self-contained |
| 171 | +const { Engine, Bodies, Composite, Mouse, MouseConstraint, Events } = Matter; |
| 172 | +const W = 390, H = 844; |
| 173 | +const engine = Engine.create({ gravity: { y: 1.5 } }); |
| 174 | +const canvas = document.querySelector('canvas'); // always use THIS — do NOT create a new one |
| 175 | +canvas.width = W; canvas.height = H; |
| 176 | +const ctx = canvas.getContext('2d'); |
| 177 | + |
| 178 | +// add bodies, set up mouse, etc. |
| 179 | +const ground = Bodies.rectangle(W/2, H+25, W, 50, { isStatic: true }); |
| 180 | +Composite.add(engine.world, [ground]); |
| 181 | + |
| 182 | +function loop() { |
| 183 | + Engine.update(engine, 1000/60); |
| 184 | + ctx.clearRect(0, 0, W, H); |
| 185 | + // draw everything with ctx here |
| 186 | + requestAnimationFrame(loop); |
| 187 | +} |
| 188 | +loop(); |
| 189 | +``` |
| 190 | + |
| 191 | +#### Pattern B — Simple bodies only (for quick physics scenes) |
| 192 | +Do NOT declare `engine`, `render`, `runner`, or Matter vars — the template provides them. Just add bodies and configure gravity. The template handles `Render.run` and `Runner.run`. |
| 193 | + |
| 194 | +```js |
| 195 | +// ✅ Pattern B — template-managed (engine, render, width, height are already declared) |
| 196 | +var ground = Bodies.rectangle(width/2, height+25, width, 50, { isStatic: true, render: { fillStyle: '#334155' } }); |
| 197 | +var ball = Bodies.circle(width/2, 50, 30, { restitution: 0.8, render: { fillStyle: '#5b82f7' } }); |
| 198 | +Composite.add(engine.world, [ground, ball]); |
| 199 | +engine.gravity.y = 1; |
| 200 | +``` |
| 201 | + |
| 202 | +### Rules — read before writing any Matter.js script |
| 203 | + |
| 204 | +| Rule | Why | |
| 205 | +|------|-----| |
| 206 | +| **Never use `element: document.body` in `Render.create`** | Creates a hidden second canvas; the visible canvas stays blank | |
| 207 | +| **If using Pattern B, never declare `const engine` or `let engine`** | Conflicts with the template's `var engine` → SyntaxError → blank canvas | |
| 208 | +| **If using Pattern A, never also call `Render.run` / `Runner.run` from Pattern B setup** | Double render loop = glitchy or invisible output | |
| 209 | +| **Always use `document.querySelector('canvas')` for the canvas element** | The iframe has exactly one canvas; this is always the right one | |
| 210 | +| **`Runner.run` requires TWO args: `Runner.run(Runner.create(), engine)`** | Matter.js 0.20.0 — single-arg `Runner.run(engine)` silently does nothing | |
| 211 | +| **Wrap custom draw logic in `Events.on(render, 'afterRender', ...)` when using Pattern B** | Lets Matter.js Render handle the rAF loop while you overlay custom 2D drawing | |
| 212 | + |
| 213 | +### Available globals in Pattern B scripts |
| 214 | +``` |
| 215 | +engine render width height |
| 216 | +Engine Render Runner Bodies Composite World |
| 217 | +Body Events Constraint Mouse MouseConstraint |
| 218 | +``` |
| 219 | + |
| 220 | +### Common mistake — mixing patterns (broken) |
| 221 | +```js |
| 222 | +// ❌ BROKEN — declares const engine (conflicts with template's var engine) |
| 223 | +const { Engine, Bodies } = Matter; // SyntaxError: can't redeclare |
| 224 | +const engine = Engine.create(); // never reached |
| 225 | +const canvas = document.querySelector('canvas'); |
| 226 | +Render.create({ element: document.body }); // creates invisible second canvas |
| 227 | +``` |
| 228 | + |
| 229 | +### Canvas CLI commands |
| 230 | +```bash |
| 231 | +editorctl canvas-add-frame "My Frame" 390 844 matterjs # create new frame |
| 232 | +editorctl canvas-run-matterjs <frameId> "$(cat script.js)" # apply script |
| 233 | +editorctl canvas-frames # list frames + IDs |
| 234 | +editorctl canvas-done # clear loading overlay |
| 235 | +``` |
| 236 | + |
75 | 237 | ## Other editor capabilities |
76 | 238 |
|
77 | 239 | See `AGENT_CAPABILITIES.md` for the full MCP tool list and `SKILL.md` for detailed API reference. |
0 commit comments