Talk to your board
Paste what you learned and Shape puts every fact where it belongs. Ask “what blocks the launch?” and get the answer drawn, each piece linked back. After a week of comments, one click on Rethink brings the whole board up to date.
Think it · Plan it · Present it · Prompt it
Shape is one board for the whole project. Throw in what you know (meeting notes, a Slack thread, a screenshot) and the AI you already pay for sorts it into mindmaps, plans, timelines, screens and decisions. Then show it to every audience, present it as slides, or copy it as a prompt and let an LLM build it.
brew install dobrinov/tap/shape
irm https://dobrinov.github.io/shape/install.ps1 | iex
curl -fsSL https://dobrinov.github.io/shape/install.sh | sh
Paste in PowerShell · more ways ↓
This is the real editor, running in your browser. It is Shape’s own board. Double-click Roadmap to open the board inside it, or right-click anything.
A project lives in six places: a whiteboard, a roadmap, a ticket board, a wireframe tool, a doc of decisions and a slide deck. They drift apart the day after the kick-off. Shape keeps them on one board, and lets the AI keep it current.
Paste what you learned and Shape puts every fact where it belongs. Ask “what blocks the launch?” and get the answer drawn, each piece linked back. After a week of comments, one click on Rethink brings the whole board up to date.
Mindmaps, kanban, gantt charts that forecast, timelines, wireframes for phone and web, decision records, risk matrices, charts and slides. They sit side by side, with boards inside boards for the details.
A board is a short text file. It diffs and merges like code, it works offline in its own window, and it is still readable in ten years. Collaboration is commits and pull requests, so there is nothing new to host.
Write, paste or drop in what you have: notes, a list, interview quotes, a screenshot. No structure needed.
The AI sorts it into the right blocks: findings into a mindmap, dates onto a timeline, work onto the kanban, an outage into a post-mortem. You see each change before you keep it.
Open the board through the eyes of leadership, legal or design. Present it as slides. Or copy it as a prompt and hand it to Claude, ChatGPT or your coding agent to build.
Sketch the product before anyone opens a design tool. Pick a phone, a tablet or a browser window, click components in, and draw the flow with an arrow from a button to the screen it opens. It sits on the same board as the plan, the data model and the decisions it depends on.
Headers, navbars, sidebars and tab bars; fields, selects, toggles and sliders; buttons, lists, tables, cards, tabs, steppers, maps, charts, alerts and more. Select a screen and click them in, or pick one from the full list.
Every button and link is its own element. Drag from one to another screen to draw where it goes; drop it on empty space and the next screen appears beside it. Screen flow starts you with three linked screens.
A screen is a few lines of text: button submit: Sign in [blue]. Edit it as text, review it in a pull request, or tell the AI “a sign-up flow with Google” and it draws the screens.
Copy the screens as a prompt and each comes out as a list of its components, with the flow between them. That is a spec a coding agent can build.
# ⌘⇧C: the board, as a spec to build from
# Build: Shape on a phone
The board below describes what to build…
## Screens
### Open as (wireframe screen, mobile: its components top to bottom)
- header: Roadmap
- title: Who is looking?
- radio: Full board | Product | Delivery | Business
- button: Open (blue)
### Connections
- Roadmap → Open as: opens
- Open → Roadmap: on a laptop
## Data & flows
### Boards (database table `boards`)
| column | type | key | references |
|---|---|---|---|
| path | text | PK | |
| theme | text | | |
## Comments
- On Open as: Remember the last perspective?
For a complex build, the best prompt is a picture of it. Lay out the system, the screens, the data model and the decisions on a board, then press ⌘⇧C. Shape writes the whole thing up as a clean Markdown spec, with every part, every arrow and every open question, ready to paste into Claude, ChatGPT, Cursor or your coding agent.
shape prompt plan.shape --target buildThe same board tells the story differently to different people. Nobody keeps a separate copy for the board meeting.
Each picture is a few lines of text, drawn by Shape itself. Put them next to each other, or look at the example board that uses them all.
Type a map with Tab and Enter. Branch it into Context, Constraints, Steps and Acceptance, and “Copy as prompt” gives your coding agent a spec.
Phone, tablet and web screens from about 40 components: fields, buttons, lists, tabs, tab bars, maps and more. Arrows from a button make the flow.
What happened when, with the moments that mattered starred. Write dates the way people say them: “Oct 2026”, “Q4”, “7–14 May”.
Columns of cards with owners and colours. Drag a card to move it; the file just lists the cards in order.
Durations, dependencies, milestones and progress. Unfinished work pushes everything after it, and slips show in red.
Loops that come round again: build–measure–learn, a release train, a review cycle.
Context, options, decision and consequences, with a status, so “why did we do this?” has an answer.
Risks by probability and impact, worst first, with owners. Drag a dot to re-rate it.
A button opens a whole board inside this one, nested as deep as you like, all in one file.
Who talks to whom, in order, with replies and self-calls.
Tables, types and keys, with relationships worked out from the columns. Or read them from your structure.sql or schema.rb and keep them in step with it.
Who does each step: the flow runs across the lanes and lines up step by step.
Bars, lines, areas, pie, donut and scatter, from a small table you edit as text.
RACI charts, options and trade-offs: rows you can point arrows and comments at.
Comment on any box, arrow or spot, reply and resolve. The AI acts on open comments when it rethinks the board.
Paper, blueprint, midnight, contrast, or your team's own colours, shared across boards.
No API keys and no new bill. Shape uses the command-line tool of the subscription you are already signed into: Claude Code, Codex or Gemini. Without one, it hands you the prompt to paste into any chat.

A board is one text file. Your team already knows how to share it: commit, branch, open a pull request.
link: plans/q3.shape#launchOne statement per line. Write it by hand, draw it in the editor, or let an agent change it with a few small edits. A pull request shows exactly what changed.
kanban, timeline, screen, gantt, adr, mindmap…# docs/roadmap.shape
kanban week: This week {
column todo: To do {
schema: Schema block [owner: deyan]
}
column doing: Doing {
site: Landing page [blue]
}
}
screen view: Open as [mobile] {
title: Who is looking?
radio: Full board | Product | Delivery
button open: Open [blue]
}
timeline shape: Shape, so far {
2026-10-07: First release
2026-10-18: Renamed to Shape [important]
}
comment on schema by mia: Its own perspective?
# in your terminal $ shape ask docs/roadmap.shape "split Build into API and UI" # comments → a task for your coding agent $ shape prompt docs/roadmap.shape --target code # let an agent read a few lines, not the whole board $ shape query docs/roadmap.shape kind:kanban near:schema
Install the bundled skills and Claude Code (or any agent) can read, draw and grow boards with few tokens.
shape skills install # ./.claude/skills shape skills install --global # ~/.claude/skills
One script tag puts a board in any page, read-only or with the full editor. It all runs in the browser; nothing is uploaded.
<script src="shape.embed.js"></script>
<div data-shape data-mode="view" style="height:420px">
<script type="text/plain">
you: You [person]
you -> board: draws the plan
</script>
</div>
// or the npm package (Node and browsers)
import { init, Board } from "@dobrinov/shape";
Or just try it in your browser first, with nothing to install.
For Apple silicon and Intel Macs, signed and notarized by Apple. Open it and drag Shape to Applications; .shape files then open with a double-click. Shape → Install the shape Command… adds shape to Terminal. With Homebrew: brew install --cask dobrinov/tap/shape.
brew install dobrinov/tap/shape
Later: brew upgrade shape. For double-clicking .shape files, add the app (Shape.dmg) too: the two work together.
curl -fsSL https://dobrinov.github.io/shape/install.sh | sh
Paste it in Terminal. It puts shape in ~/.local/bin and Shape in your Applications. Run it again to upgrade.
irm https://dobrinov.github.io/shape/install.ps1 | iex
Open PowerShell from the Start menu and paste it. It installs Shape for you (no admin rights), adds it to the Start menu and makes .shape files open with a double-click. Run it again to upgrade.
Get shape-…-windows-x86_64.zip from the latest release, unpack it anywhere and run shape.exe install-app once from there.
curl -fsSL https://dobrinov.github.io/shape/install.sh | sh
It puts shape in ~/.local/bin and makes .shape files open with a double-click. Run it again to upgrade.
brew install dobrinov/tap/shape
Later: brew upgrade shape. Or get an archive from the latest release.
git clone https://github.com/dobrinov/shape shape && cd shape make install
Needs Rust with the wasm32-unknown-unknown target and wasm-pack.
Then open Shape: it opens a new board in its own window, and asks where to keep it once you have something on it.
Yes. Shape is open source under the MIT licence, with no paid tier.
No. Shape uses the command-line tool of an AI subscription you already have (Claude Code, Codex or Gemini CLI), signed in as you. If you have none, the ✦ button explains how to set one up, and meanwhile shows the prompt to paste into any chat.
Nowhere new. A board is a file on your disk, the editor runs on your machine, and AI requests go through your own AI tool. The site's playground runs entirely in your browser.
Through git: commit the file, branch, open a pull request. Shape shows what a branch changed, merges boards element by element, and signs comments with your name. Outside git, it keeps versions you can go back to.
Yes, that is one of the best uses. Draw what you want built (the parts, the screens, the data, the rules), then copy the whole board or a selection as a prompt (⌘⇧C). It is plain Markdown, so it works with any model or coding agent, and the board stays the source you refine between attempts.
For the thinking, planning and explaining part of a project, often yes: it is one board instead of several. It does not try to be a ticket tracker with workflows and permissions.
diagram before. Does anything break?No. Shape was called diagram until October 2026. The diagram command still works as an alias, .diagram files open, merge and link like .shape ones, and with Homebrew, brew migrate diagram once moves you to the shape formula.
What changed in each release. The full history is in CHANGELOG.md, and every release is on the Releases page.
shape install-app keeps the Mac app. With Shape.app from Shape.dmg in Applications, shape install-app (from Homebrew, say) no longer replaces it with the older script copy: it lets the app open your boards. shape install-app --remove only removes that script copy; to remove the app, move it to the Bin..shape file opens it in Shape, each board in its own window, and opening Shape itself starts a new board. The app finds your AI's command-line tool the way your terminal does. Shape → Install the shape Command… adds shape to Terminal; a shape from Homebrew stays as it is.shape skills install --global no longer stops with HOME not set: the skills go into your user folder.claude.cmd). Before, they looked for it in a way only macOS and Linux understand.tech): architecture sections, implementation decisions, a mindmap's technical branches, on the board and in their summaries. Something tagged both still shows. ✦ Rethink and Sort into perspectives tag technical things tech, and the next Rethink after this upgrade tags what is already on your board.group arch: Architecture [tags: tech], adr embed: Use an iframe [proposed, tags: tech]. A section tagged for a perspective shows whole in it.web for a web app or a widget in one), and asks when the board does not say.platform: ios (or web, android, or any word) marks which platform a task is for, with a chip by its name in that platform's colour, the same on every chart. Names stay short: Implement with an iOS chip and Implement with an Android chip, instead of Implement (iOS). Right-click a task → Platform…. Hovering a task says its platform too.shape with no file) no longer asks where to save it first: you start drawing at once. Your work is kept as a draft from the first change, and the draft opens again if Shape is closed before it is saved.comment on api, db: …. Delete one of them and the comment stays on the others.shape ask and shape apply list what changed inside canvases too, instead of saying No changes. So does the session log.rethought: 0.74.0, one line in the file, so it travels with git). After an upgrade, the next ✦ Rethink is told what the new version's built-in perspectives can show (test scenarios for QA, a canvas per project for Delivery…) and reshapes the board for them where it fits, from what is already on it. On opening such a board, Shape offers that Rethink once. Boards with only custom perspectives, or none, are left as they are.row: TASK puts a gantt milestone on another task's row (Beta on the Build bar) instead of a row of its own.expected column is a table of test scenarios. Right-click a scenario → Passed, Failed, Blocked or To run sets its status and tints the row.irm https://dobrinov.github.io/shape/install.ps1 | iex into PowerShell: it installs Shape for you (no admin rights), puts it on your PATH and in the Start menu, and makes .shape files open with a double-click. On macOS and Linux, curl -fsSL https://dobrinov.github.io/shape/install.sh | sh does the same without Homebrew. Run either again to upgrade, and the New badge says which one to run.shape install-app on Windows adds Shape to the Start menu too (--remove takes it out).shape.exe. The old diagram name is now a tiny diagram.cmd next to it, instead of a second copy of the program.shape logs shows the latest session; shape logs ai and shape logs errors show just those, --list the sessions, --session N one of them, --full everything, and --clear deletes them. So when something goes wrong, an agent helping you can see what happened.--debug logs the details too: every change you make, each perspective and canvas opened, the editor's warnings.~/Library/Logs/Shape on macOS) and hold board content; the last 30 sessions are kept. SHAPE_NO_LOG=1 turns them off, SHAPE_LOG_DIR puts them elsewhere.shape import FILE BOARD…. A board without perspectives of its own takes its canvases' set, so its summaries work straight away.canvas: id on the task. A badge by its name says how many risks it holds, in the worst one's colour, and opens it. On the Roadmap, each canvas's bar has the same badge.# notes and its own layout. Now only that line changes, and changing the set of a board written with type: rewrites that line too.brew upgrade shape) and See what's new for the release notes; or that you have the latest version; or why it could not check. The New: … badge in the editor follows. In a terminal: shape version --check.perspectives: project (startup, agency, product, none). type: project, as it was written before, still works.-i), Gemini includes them (@FILE); another command finds their paths in SHAPE_AI_IMAGES. They are deleted once it has answered.shape skills install (in ~/.claude/skills or a repository's .claude/skills) are brought up to date the first time a newer Shape runs, which says which it updated. A skill you edited is left as it is. SHAPE_NO_SKILL_REFRESH=1 turns it off.forecast revenue: Revenue [unit: £] { now: 12k · Phase 1 GA [adds: 3k, ramp: 3] … }. Revenue now, and what each launch adds a month once it has ramped up. A launch is a gantt milestone by its name, so its date comes from the plan (or on: DATE). Drawn month by month, as planned and as forecast: when the plan slips, the curve moves. Blocks → Revenue forecast starts one with the board's milestones; right-click → Edit as text….blocker), decisions needed (proposed decision records, a section of asks), top risks, and what changed since a week ago;shape svg|png FILE --perspective delivery exports a perspective's summary (--as-of DATE, --base REF for what changed).schema db: Database [file: db/structure.sql] { … } puts the tables of a real schema file on the board: a Postgres structure.sql, a MySQL or SQLite dump, or a Rails schema.rb, read by the parser of schema. Columns keep their types, primary keys, unique columns, nullability, defaults and foreign keys (drawn with crow's feet).shape schema BOARD db/structure.sql adds a schema (or updates the one from that file; --only 'users orders*' keeps some tables); shape schema BOARD updates every schema from its file, in canvases too. Updating changes only what changed, and keeps what you added on the board, like a relationship's name.examples/model.sql.From a beta tester's notes:
todo launch: Launch checklist { … }, one item per line, [x] done and [ ] to do (Markdown-style - [ ] works too). Two more spaces make a sub-item. An item can have an owner, a due date (due:) and details.shape install-app again to see it in Finder and the Dock..shape / .diagram document icon (which now reads SHAPE). Run shape install-app again to get it in Finder and the Dock.finance or commercial still show there.team tags still count.shape (shape plan.shape, shape ask …, shape install-app). diagram stays as an alias: the release archives and Homebrew install it next to shape..shape files. .diagram files still open, save, link (plans/q3.diagram#launch), merge and show in history, and install-app registers both extensions.brew install dobrinov/tap/shape; brew upgrade moves an installed diagram over.SHAPE_AI, SHAPE_WEB_DIR, SHAPE_NO_UPDATE_CHECK and SHAPE_SKIP_WASM. The DIAGRAM_* names still work. `shape `` blocks. A reply with a `` `diagram ``` block still applies.shape-draw, shape-review, shape-edit, shape-mindmap and shape-embed; installing them removes the old diagram-* ones.Shape (Shape.mount, Shape.render, <div data-shape>); Diagram and data-diagram still work. The npm package is @dobrinov/shape; the crates are shape, shape-core and shape-wasm.shape merge --install registers a shape merge driver for both extensions.shape apply with a reply holding a whole board in a fenced block read past the fence's name.login.submit); before, a new component named by its text could lose it.diagram prompt FILE --target build. Screens list their components by kind. The landing page and the README now say Shape is a way to write prompts too.diagram install-app replaces Diagram.app), the file type, the help text, the README and the website. The diagram command, .diagram files, the Homebrew formula and the repository keep their names, so nothing breaks.screen login: Sign in [mobile] { … } draws a screen as a phone, a tablet or a browser window (web), its components one per line, top to bottom: kind [id]: text [attrs].| (tabs: Home | Search | Me). A tab bar and a floating button sit at the bottom; a sidebar takes the left of a wide screen.login.submit), so an arrow from a button to another screen draws the flow. In the editor, drag from a component to a screen; dropped on empty canvas, it makes the next screen of the same device, beside the first.add_group with screen, add_node with widget, or merge the block), and a new Screens and flow recipe. The Product, User and Design perspectives show screens. The example board has a canvas of checkout screens.diagram FILE (and double-clicking a .diagram file) opens the editor in a native app window instead of a browser tab: the system webview (WebKit on macOS, WebView2 on Windows). Closing the window saves what is pending and stops. On macOS it has an app menu, so ⌘C / ⌘V / ⌘Z / ⌘Q work. Links out of the editor open in your browser. --browser opens a tab as before; --no-open runs only the server. Where no window can be made, the browser opens.diagram with no file (or opening Diagram.app on its own) shows a save dialog to name the board and pick its folder; Cancel creates nothing.--no-default-features), so they still run without WebKitGTK and open the browser; build from source for the window there.presentation: Title [transition: …, instructions: …] { … }, one slide per line (risks [title: …, notes: …, transition: zoom], * for the whole board), written back without touching the rest of the file. Op presentation; the AI's op reference has it. The example board has one.builtin_perspectives(kind).--ai) or use any other command. The copy-the-prompt dialog links to it too.Check it works sends a one-word prompt to test it. With an AI connected, the ✦ menu's Your AI: check it, or change it… opens the same dialog.
~/.local/bin, ~/.claude/local, Homebrew, npm and bun folders), so an editor opened from Finder or a desktop launcher finds them.GET /api/ai lists the installed CLIs; POST /api/ai/check; failed calls come with a hint.diagram ask / diagram expand's), so a model no longer guesses the year when it writes dates..diagram-history/<file>/: one at most every five minutes of saving, signed by whoever saved, the newest 200 kept.GET /api/history and GET /api/history/version?id=; PUT /api/file takes the author in X-Diagram-Author..diagram files in a recipes/ folder, from the board's folder up to the repository's root, first line # recipe: Name — when to use it. The editor and diagram ask read them.recipes module; prompts take recipes; WASM recipes, set_recipes; server GET /api/recipes.cycle loop: Build loop { Plan · Build · Measure · Learn }, one step per line. The steps go round a circle with an arrow from each to the next and from the last back to the first; the circle grows with the steps so they never overlap. Steps take colours, details, links and comments. In the editor: Blocks → Cycle; right-click to add a step after one or edit the cycle as text. Perspectives can show cycles (show: cycle).type: product brings Product, Technical, User and Senior management. type: project brings Senior management, Team, Product and Technical. Both also bring Legal, Finance, Marketing, Commercial and Design. A sketch (the default) has none.perspective legal: Legal [tags: legal, show: adr]. One with a built-in's id overrides it.diagram new FILE --template product and --template project start boards with a type, starter content and perspective tags. The Board popover changes a board's type.perspectives module, BoardKind, Session::apply_top (ops for the whole board while a canvas is open); op perspective; set key type; render option perspective. WASM perspectives, board_type, apply_top.#/id on the top board, #/plan/id inside canvas plan.prompt::answer_board, prompt::answer_parts, Session::answer_board_prompt; WASM answer_board_prompt, answer_parts.The editor's redesign:
research · 4 changes since main, or on main the changes not committed yet. It counts every canvas and updates as you edit. Clicking it shows those changes on the board; clicking again stops.change_count; WASM count_changes; /api/since also gives branch and main.prompt::RETHINK_DEFAULT and an instructions argument for rethink / Session::rethink_prompt; WASM rethink_default; npm rethinkPrompt({instructions}).DATE: what happened [important], with the date as you write it: 2026-10-28, 28 Oct 2026, Oct 2026, mid Dec 2026, Q4 2026, 2026, ~6 Aug 2026, or a span (7–14 May 2026). Events sit on a line by date:date | event table into a timeline, keeping ids, comments and links (⌘Z turns it back). A date that cannot be read is refused with what dates look like. Ask, Rethink and prompts read events in time order. Core timeline module; timeline on groups, date and important on nodes (DSL, JSON, ops, typings).{"op":"in","canvas":"plan/details","ops":[…]}: change things inside a canvas from the board around it. A single op that carries ops is no longer mistaken for a batch.prompt::question, prompt::answer_refs, Session::question_prompt, Session::answer_refs. WASM question_prompt, answer_refs.diagram install-app (once; --remove undoes it) gives .diagram files a document icon (the logo on a page) and makes a double-click open the board in the editor..diagram type (io.github.dobrinov.diagram.board, plain text underneath, so Quick Look still shows it). It goes in ~/Applications, or in ~/Library/Application Support/diagram when that folder is not yours. It keeps your PATH, so ✦ AI finds your CLI.application/x-diagram, its icon and a .desktop entry under ~/.local/share.--idle-exit: an editor server started from a double-click stops once no editor tab has been heard from for 3 minutes. Tabs check in every 30 seconds, also in the background.brew upgrade diagram for a Homebrew install), and a New: x.y.z badge in the top bar links to its notes. A failed check is silent. DIAGRAM_NO_UPDATE_CHECK=1 turns it off; it is off under CI too. Server GET /api/update.Pin (render output) has author and replies.main (or since the last commit, on main), and the AI revises the older parts around it. Without git (a file that is not in a repository, the playground) it rethinks the canvas as it is.prompt::rethink, prompt::reply_note, Session::rethink_prompt. WASM rethink_prompt, reply_note. npm Board.rethinkPrompt({since, label}), replyNote. Server GET /api/since; editor option since().vX.Y.Z builds diagram for macOS (Apple silicon and Intel), Linux (x86_64 and arm64) and Windows (x86_64), and publishes them on GitHub Releases with checksums and notes from this changelog. Homebrew: brew install dobrinov/tap/diagram.main.diagram --version (and -V) prints the version.title attributes stay for scripts and accessibility.examples/example.diagram replaces the thirteen separate examples. It tells one project, a checkout relaunch, and uses every feature. The top board holds the architecture: all 13 shapes, colours and #hex, details, tags, web and #id links, nested sections, every kind of arrow, comments with replies and a resolved one, and a theme of its own with light and dark. Canvases open from links in four styles:paper theme.diagram new templates (flow, architecture, board) now live in crates/cli/templates/. make dev and the site use the new example.diagram merge --install makes git merge .diagram files element by element. Different changes to the same box (one person's colour, another's detail) both land; additions and removals merge, canvases inside merge in turn. Only the same field changed two ways, or a change on one side and a removal on the other, is a conflict. The file keeps yours with a # merge: … note on top, and git leaves it unmerged.git adds it. A file git merged line by line, with <<<<<<< markers, opens the same way.diagram merge BASE OURS THEIRS [-o OUT]. Core merge module (merge3, resolve, prompt, split_markers). WASM merge3, merge_resolve, merge_svg, merge_prompt, merge_answer, split_markers. Server GET /api/conflict, POST /api/resolve. Editor resolveConflict({base, ours, theirs, done}). scripts/e2e/merge.mjs (real git merges) in make e2e.canvas payments: Payments flow { … }, written indented at the end of the parent's file, is a board of its own: boxes, blocks, comments, images, and canvases of its own. A box with canvas: payments is the way in. Its shape is how the link looks: a button (pill, the default), a card (box), text, a sticky, …. The box has a badge; double-click it or click the badge to open the canvas. The trail at the top leads back up, and the URL keeps the open canvas (?canvas=payments/fraud).--canvas payments/fraud makes any CLI command (brief, apply, svg, …) work inside a canvas.add_canvas, update_canvas, canvas on add_node / update_node. WASM: open_canvas, canvas_trail, replace_here. Editor API: openCanvas(path), canvasPath(), the canvas event. JSON: canvases, node.canvas. scripts/e2e/canvases.mjs in make e2e.shot: Login [image: img1, w: 328, h: 228]). The image is kept in the file as base64, on an asset img1: data:image/png;base64,… line at the end, so boxes stay readable and a diff touches one line. Big images are scaled to 1600px, and large photos are stored as JPEG.brief and query never include the base64: a model reads [image: img1] and a note of what images there are, and a whole-diagram reply keeps the board's images. Removing the last box that shows an image removes the image.add_asset, and image on add_node / update_node. JSON: assets, node.image. PNG export draws the images (resvg with raster-images). scripts/e2e/images.mjs in make e2e.[rel: member of] names the relationship on its line. Leave out a column's type (email [unique]) for a conceptual model.diff lists a changed relationship name. The editor's column text takes rel:. In JSON: column.rel.sequence login: Sign in { with participants (user: User [person]) and then messages (user -> web: opens /login, api ..> web: 201 for a reply). Participants sit side by side with dashed lifelines; messages run top to bottom in the order written, straight from lifeline to lifeline, and a message to itself loops back. Messages are ordinary arrows (labels, colours, comments) and are written inside their block; an edit keeps them there.add_group with sequence, update_edge with index (a message's place).brief list the participants and the numbered messages; query kind:sequence; examples/sequence.diagram; scripts/e2e/sequence.mjs in make e2e.adr db: Use Postgres for orders [accepted] { with one field per line (context: …, options: …, decision: …, consequences: …, or any names). Drawn as a card: the status in a coloured pill (proposed, accepted, rejected, superseded, deprecated), then each field's name over its text. Fields are elements (db.context): comment on one, link to it, draw an arrow from one record to another (supersedes).add_group / update_group with adr (the status); fields are nodes with detail. Prompts list the fields in bold; query kind:adr.Group::plotted, charts::plot_any). examples/decisions.diagram; scripts/e2e/adr.mjs in make e2e.kanban sprint: Sprint 12 { with column todo: To do { … } inside; cards are boxes, stacked in the order written, all as wide as the widest; each column's title shows its card count. It is swimlanes laid out as columns ("lanes": true, "kanban": true in JSON), so moving, colouring, comments and arrows work as before.update_node with group and index); right-click a column → Add card, Add column after, Remove column.query kind:kanban; examples/kanban.diagram; scripts/e2e/kanban.mjs in make e2e.source() and prompt() get their errors as data from the WASM side (source_result, prompt_result: {ok, text} or {ok: false, error}) instead of looking for an error: prefix in the text, and throw DiagramError.js/test/types.test.mjs) checks that every op in index.d.ts has the same fields, and the same required ones, as the Rust Op enum, so the types cannot drift from the format.link: delivery.diagram or link: ../plans/q3.diagram#m1, relative to the board. In the editor the link badge opens that board in place (the URL carries ?file=…&focus=m1, so back returns), with the element selected; pending edits are saved first. Right-click → Link to a board… lists the other boards in the repository. The local server opens only .diagram files under the board's git repository (or folder).diagram check reports links to boards that do not exist or have no such element. Badges and prompts say where a board link goes ("Go to m1 on delivery.diagram").goTo(id); options openBoard(path, id) and boards(). scripts/e2e/links.mjs in make e2e.add_outline line can end in attributes, Launch [id: launch, red, collapsed]; a free id is used and the rest apply one by one (a bad one is left out instead of dropping them all). Topics without an id get a short one from the label's first words (who-books-the-venue, at most four words) instead of the whole sentence. Ids in files you wrote are unchanged.add_outline takes group for a new map (diagram expand FILE --new TOPIC --in SECTION).entity users: Users { … } with one column per line, email: text [unique], team_id: uuid [fk: teams], bio: text [null], created_at: timestamptz [default: now()]. Columns show PK / FK / UQ badges, their type and ? when nullable; a foreign key is drawn from the column to the one it references and pulls related tables together. Columns are elements (users.email): comment on one, link to it, hover it for everything about it.diff lists columns added, dropped and changed (type, keys, references, default); --base shows them in green, red and amber, dropped columns included. Prompts show a table as a Markdown table of its columns, and brief includes the tables.add_group with entity, nodes with column; query kind:entity, kind:column. examples/schema.diagram; scripts/e2e/entity.mjs in make e2e.group a: A [x: 400, y: 120] { (and the move op) places any section, not only swimlanes, charts and tables; its boxes are laid out inside it. Dragging a section by its frame in the editor now places the section instead of pinning each box in it (a section whose boxes were already placed one by one moves as before). Adding a section no longer reshuffles the ones you placed.scripts/e2e/board.mjs in make e2e.diagram ask FILE "…" [--on ID,ID] [--dry-run] [--print]: the same from the command line.--ai presets for subscription CLIs: claude (Claude Code, claude -p), claude:sonnet (a model), codex (Codex CLI), gemini (Gemini CLI); without --ai / DIAGRAM_AI, the first of them installed. Any command still works. (The default for Claude Code is now your plan's default model instead of Haiku; claude:haiku keeps it fast.)Board.askPrompt(request, ids), askAgain(prompt, reply, error); WASM ask_prompt, ask_again. scripts/e2e/ask.mjs (with a stand-in harness) in make e2e.light { … } and dark { … } hold what differs. A board follows the viewer's mode (the editor's light/dark switch, --dark for exports), so a team's brand theme works for everyone. Old theme id [base: dark] { … } blocks read as that mode.paper, blueprint, midnight, contrast.theme_text(name).blueprint and midnight are gone until every theme has a light and a dark mode; paper and contrast stay. Boards that named them fall back to the default theme.theme: paper | blueprint | midnight | contrast (presets), the id of a theme block on the board, or a shared file (theme: ./brand.theme). A theme brand [base: light|dark] { … } block sets background, dots, text, muted, surface, border, line, section, header, title, title-text, pin, any named colour (blue: #3b6fd8), font and radius; the rest comes from its base. Themes apply to the board, its SVG/PNG/HTML exports (a file theme is carried into the HTML) and the editor's canvas. Unknown keys and bad colours are errors.theme (add or replace a theme from its text), set theme, remove of a theme. JS: Board.addThemeFile(name, src), Board.themes(), render().canvas; WASM add_theme_file, themes, theme_preset.dir).scripts/e2e/themes.mjs in make e2e.table id: Title { … } with a header row and rows of cells separated by |. Columns line up in the file; long cells wrap on the board; a colour tints a row. Rows are elements named in their table (options.local): comment on a row, link to it, point arrows at it, hover it for its cells by column. Prompts show tables as Markdown.index places any member of a group (table and chart rows, gantt tasks, boxes in a section), not only mindmap topics. Add task after now puts the new task right below the one it follows (it used to append it at the end).add_group/update_group take table and columns, nodes cells; query kind:table, kind:row. examples/tables.diagram; scripts/e2e/tables.mjs in make e2e.chart id: Title [bar|line|area|pie|donut|scatter] { … } holding a small table (quarter | EU | US, Q1 | 120 | 80, or Jira 45). Bars side by side, stacked or horizontal; lines; stacked areas; pie; donut with the total in the middle; scatter (label | x | y). Axes with round ticks, a legend for several series, unit: (k€, %, $ in front), w:/h:. Rows are nodes named in their chart (revenue.q1): point arrows, comments and links at a bar or a slice; hover for its values; a colour on a row colours it.add_group/update_group take chart, stacked, horizontal, unit, series, axis, and nodes values; query kind:plot, kind:row. Renaming a chart renames its rows. examples/charts.diagram; scripts/e2e/charts.mjs in make e2e.done), and what waits for it moves with it, also in other charts and past fixed start dates. Charts draw a slip as a red dashed extension with +5d, and a hollow diamond where a milestone will now land; the timeline grows to fit. The editor shows it live; exports take --today or --as-of DATE.diagram schedule FILE [CHART] [--as-of DATE] [--json]: every task's planned and forecast dates and status (done, late, behind, in progress, pushed back, upcoming).brief with a date (--today, --as-of; Copy as prompt in the editor uses today) add forecast end 2026-10-26 (+5d, behind) to tasks.diff (and what apply prints) lists the milestones and chart ends a plan change moves: milestone m1 moves 2026-10-17 → 2026-10-19 (+2d).Board.schedule({today}), Board.brief({today}), Board.selection(ids, {today}), render({today}) takes a Date. WASM: schedule, brief_at, selection_markdown_at.[detail: fast, opinionated, red] reads as the detail "fast, opinionated" and the colour red (also ;, and in label, resolution, owner). Brackets that start like attributes but don't read as them ([shape: box, opinionated]) are now an error with the line, instead of silently becoming part of the label (models hit this constantly).gantt -> b, risks -- b, comment -> x are arrows again; group, gantt, risks and mindmap only open a block on a line that ends with {.prompt --context auto|near|section|all: a prompt about comments shows only what they are about on a big board (auto: the whole board up to 60 lines, else the commented sections; near: the commented blocks and their neighbours), and tells the model the rest exists. On a 300-element board one comment's prompt went from about 24k to 6.7k characters. Also in the WASM/JS prompt options and used by the editor.--base); title changes keep their case; description changes are listed.risks id: Title [scale: 5] { … } with one risk per line, Label [p: 4, i: 3, owner: ana, detail: "…"]. Drawn as a probability × impact grid with cells tinted by severity (low, medium, high, critical), each risk a numbered dot in its cell, and a list of the risks with their scores beside it; unrated risks wait in the list. Hover a dot or a row for its rating, owner and description.… = 16 (critical), owner ana — description), brief includes them, query knows kind:risk and kind:matrix; ops add_group (risks, levels), update_group (levels), add_node / update_node (probability, impact). JS types updated.examples/risks.diagram; scripts/e2e/risks.mjs (part of make e2e).Tools for agents that drive boards:
diagram add FILE [DSL|-] and the merge op: statements in the diagram language added to a board as if written at its end. New elements are created; one written again by its id gets the attributes given (api [red]); a group written again keeps its place. The cheapest way for a model to add a lot at once.diagram query FILE SELECTOR…: just part of a board, as diagram language with the sections around it: group:/chart:, map:, near:, label~, kind:, owner:, tag:, color:, comments:open (--ids for ids). Also Board.query() / Board.select() in the JS package and query() in WASM.diagram apply FILE '{"op":…}'.--focus ID,ID crops svg/png/html (and the focus render option) to some elements.diff (and the summary apply prints) now shows changes to gantt tasks and charts (dates, durations, dependencies, milestones, progress, owners, scale) and topic moves.Board.merge(dsl) in the JS package.js/ (make js): an ES module for Node ≥ 18 and browsers with index.d.ts types. await init(), then Board.parse(src) / Board.empty() with apply(ops | {ops} | model reply) (atomic; throws DiagramError with the failing op's index), source(), document(), render(), prompt(), brief(), outline(), markdown(), selection(ids), diff(base), expandPrompt(); one-shot parse, render, convert, spec, jsonSchema, version, mindmapPrompt, replyOutline. Objects in and out, camelCase options; Op is a typed union of every op. make test runs its tests once js/pkg is built. Marked private for now: the npm name diagram is taken.markdown(id) returns an empty string for an unknown id again.diagram apply (also a whole ``diagram reply), comment, reply and resolve rewrite only the statements whose elements changed, put new statements next to their kind (a box inside its section, an arrow after the last arrow, a comment after the comments) and leave every other line, blank line and # note alone. A chain like web, mobile -> cdn -> gw is split only when one of its arrows changes; a renamed box keeps its line; a changed mindmap or gantt chart is rewritten as a block. The result is read back before it is written, and the whole file is reprinted only when the edit can't be placed (e.g. moving a section into another one). A 6-op edit of a 60-line board now changes 10 lines instead of 40. diagram fmt` still reprints everything.[milestone] makes a task a point in time, drawn as a diamond on its day (right-click → Make it a milestone).done: 60% (or done) shades the part of the bar that is done and shows 5d · 60% / 5d ✓ (right-click → Progress…).owner: ana shows next to the task's name (right-click → Owner…).--today for diagram svg|png|html).after: its id); the line is dashed and runs along the row line, clear of the task names. Both charts need dates.after: design means this chart's Design, even when another chart's Design took the id design (it used to link the other chart's task). chart/task names a task of another chart when this one has one of the same name.Build: 2026-10-12 → 2026-10-16, 5d, 60% done, owner ana. The ops reference for models now covers gantt charts.outline --md, markdown()), a block with link: #id reads "label (see “Target”)", and the target (swimlanes, a gantt chart, a section, a mindmap or a single block with its arrows) follows as a section headed "— linked from “label”". Links inside it are followed too (up to 8 blocks), and nothing is repeated. Web links stay Markdown links.yes → 5. Confirm order).Design: 2026-10-12 → 2026-10-16, 5d.diagram brief is now the title and counts, gantt dates and swimlane steps (what the source doesn't spell out), then the source with every id and comment. It used to list every node and arrow and then repeat them in the source (about half the size now on an architecture board), and it ignored gantt charts.Sat 17 Oct – Wed 21 Oct · 5 days). Dragging the end of a bar shows the same label. Dragging a bar out of its chart shows it leaving.scale: day | week | month | quarter on a chart (right-click it → Scale…). Lines and dates at each day, Monday, month or quarter; month and quarter labels carry the year when it changes. Durations also take 1m (30 days) and 1q (91 days), and are written that way when they divide evenly.5d, 2w, 1m, 1q. Duration… replaces Longer / Shorter.after:), instead of an arrow. Loops are refused. Right-click a dependency line → Remove dependency, or a task → Starts after… to tick the tasks it waits for.link: #id). Linked blocks get a link badge; clicking it pans and zooms to the target and selects it (a web link opens in a new tab). Remove link takes it off. Exports keep web links clickable.notes.diagram · Saved).x/y on the lanes or gantt line, which the move, nudge and unpin ops now handle. Inside, they are still laid out automatically.⌘⇧C). Markdown with the board's title, the blocks as bullets under their sections' headings (gantt tasks with dates and durations), then the arrows between them and their open comments. Right-clicking a multi-selection also offers Put in a section and Delete. Core: prompt::selection; WASM: selection_markdown(ids).## sections only when every one of them has topics or a detail under it; otherwise the map is one nested list under the title (a shopping list stays a list).Flowcharts, swimlanes, gantt charts and comments on the board; a simpler editor that looks like schema; tidier mindmaps.
update_edge with new ends keeps an automatic id (a->b) in step, comments included.lanes id: Title { lane a: A { … } … } (a group with "lanes": true). Lanes are bands (rows when the flow runs right, columns when it runs down) with their titles at the side; everything in them is ranked together, so the flow lines up across lanes. In the editor: the Swimlanes button (selected blocks go in the first lane), drop a block into a lane to move it there, right-click a lane to rename it, add one after it or remove it.gantt id: Title [start: 2026-10-12] { Design [5d] Build [2w, after: design] … } (a group with "gantt": true; tasks are nodes with start, days, after). Drawn as a timeline: week dates, task names, bars and dependency arrows. In the editor: the Gantt button (a chart starting today), drag a bar to reschedule it, right-click a task to make it longer or shorter or add one after it.examples/swimlanes.diagram, examples/gantt.diagram.x/y relative to the map's centre); its branches follow it and grow away from the centre, and its siblings close up. The move op now works on topics.code: true / panel: true, or ?sidebars in the local editor, bring them back). The Prompt and Compare buttons are gone from the toolbar.group); drop a block into a section to add it, drag it out to take it out; right-click a section to rename or remove it.title: is metadata now (briefs, export names). It is not drawn; --title draws it in exports. New files start without one.diagram with no FILE starts a new untitled.diagram (untitled-2.diagram, … when taken) instead of reopening diagram.diagram.Mindmaps, as the first FigJam-style building block of the board.
mindmap id: Topic [layout: right|left|both|down] { …indented outline… }. Topics are ordinary nodes (parent in JSON), so comments, ops, diffs and cross-links work on them. Folding ([collapsed]), branch colours, Markdown bullets in the outline.both) and org-chart (down) maps. The centre is a pill, main branches are outlined cards, sub-topics sit on coloured underlines and curved branches. A map is one block on the board, next to boxes and stickies.ai(prompt) option in the editor, --ai CMD / $DIAGRAM_AI for the CLI and the local server (default claude -p --model haiku when installed); without a harness the prompt is shown to copy.add_outline; parent / index / mindmap / collapsed on add_node and update_node; removing a topic removes its branch (keep_members lifts it).diagram outline FILE [ID] [--md], diagram expand FILE ID [--ask …] and --new TOPIC.mindmap diagrams import and export.diagram-mindmap.Visual polish from the stress test: group title pills, dotted canvas background, soft shadows, refreshed theme colours. Fixed invalid SVG (duplicate stroke-width) when diffing added or changed groups. Stress-test examples and report in examples/stress/.
First release: DSL, JSON and Mermaid formats, ops API, layered/grid layout with groups, SVG/PNG/HTML export, browser editor with comments, comment-to-prompt and reply application, git-aware diffs, embed bundle, Rust crate and agent skills.
Open the playground, paste the notes from your last meeting and press ✦.
Try Shape now