Skip to content

opencoredev/excalidraw-cli

Repository files navigation

Excalidraw CLI

License GitHub Package

Control a live Excalidraw canvas from AI agents using a plain CLI and a loadable agent skill.


Setup

Two things to get running: the canvas server (the thing you draw on) and the CLI (the thing that controls it).

1. Start the canvas server

With Docker (no build step, works anywhere):

docker run -d -p 3000:3000 --name excalidraw ghcr.io/opencoredev/excalidraw-cli-canvas:latest

Don't have Docker? Install Docker Desktop — free for personal use on Mac, Windows, and Linux.

Without Docker (requires Bun, runs directly):

bunx --bun github:opencoredev/excalidraw-cli serve

Don't have Bun?

curl -fsSL https://bun.sh/install | bash

Open a new terminal after installing, then re-run.

2. Install the CLI

bun add -g github:opencoredev/excalidraw-cli

3. Verify

excalidraw status
# → {"status":"healthy","elements_count":0}

Open http://localhost:3000 in your browser to see the canvas.


Quick Start

excalidraw create --type rectangle --x 100 --y 100 --width 160 --height 60 --text "Hello"
excalidraw viewport --fit
excalidraw screenshot --out hello.png

Managing the Canvas Server

# Stop
docker stop excalidraw

# Restart after a reboot
docker start excalidraw

# View logs
docker logs -f excalidraw

# Remove
docker rm -f excalidraw

Point the CLI at a non-default server:

export EXCALIDRAW_URL=http://myserver:3000
excalidraw status

Agent Skills

Skill What it's for
excalidraw CLI commands, how to use the canvas
excalidraw-design-guide Colors, sizing, layout, anti-patterns
excalidraw-workflow Planning, element-by-element drawing, review

Install all three:

bunx skills add opencoredev/excalidraw-cli

Or install individually:

bunx skills add opencoredev/excalidraw-cli --skill excalidraw
bunx skills add opencoredev/excalidraw-cli --skill excalidraw-design-guide
bunx skills add opencoredev/excalidraw-cli --skill excalidraw-workflow

To update, just re-run — it overwrites in place:

bunx skills update

Skills are plain markdown files in skills/ — loaded by your agent on demand, zero overhead when not in use.


Why CLI + Skill Instead of MCP

This project started as an MCP server (yctimlin/mcp_excalidraw). We rewrote it as a CLI + skill for three reasons:

MCP CLI + Skill
Context when idle All tool schemas always loaded Zero — skill is loaded on demand
Process management Daemon, ports, crashes to manage Stateless CLI, nothing to babysit
Agent compatibility Depends on client MCP support Any agent with bash access

"Adding just the popular GitHub MCP defines 93 additional tools and swallows another 55,000 of those valuable tokens. Existing CLI tools gain all of that functionality for a token cost close to zero — because every frontier LLM knows how to use them already." — Simon Willison, simonwillison.net, Aug 2025

The numbers back it up: the Playwright MCP server alone eats 22.2% of Claude's 200K context window just to list its tools (demiliani.com). Three MCP servers together consume over 20% before any work starts (EclipseSource). The problem is acknowledged at the protocol level — Huawei engineers filed a formal spec proposal to fix it in the MCP repo itself (#1576).

The canvas server still runs as a simple Express app. The difference is the agent interface — instead of tool schemas loaded into context on every request, it's bash commands the agent runs when needed, guided by a skill file it loads on demand.


CLI Reference

All commands output JSON. Set EXCALIDRAW_URL env var or pass --url to target a different canvas.

Server

excalidraw serve [--port 3000] [--host localhost]
excalidraw status

Elements

excalidraw create --type rectangle --x 100 --y 100 --width 160 --height 60 --text "Box"
excalidraw create --type arrow --x 0 --y 0 --start <id> --end <id>
excalidraw update <id> --text "New Label" --stroke-color "#e03131"
excalidraw delete <id>
excalidraw get <id>
excalidraw query [--type rectangle]
excalidraw clear

Batch create (recommended for diagrams)

excalidraw batch diagram.json
cat diagram.json | excalidraw batch

Batch JSON format:

{
  "elements": [
    {"id":"svc-a","type":"rectangle","x":100,"y":100,"width":160,"height":60,"label":{"text":"Service A"},"strokeColor":"#1971c2","backgroundColor":"#a5d8ff"},
    {"id":"svc-b","type":"rectangle","x":100,"y":240,"width":160,"height":60,"label":{"text":"Service B"},"strokeColor":"#2f9e44","backgroundColor":"#b2f2bb"},
    {"type":"arrow","x":0,"y":0,"start":{"id":"svc-a"},"end":{"id":"svc-b"},"label":{"text":"HTTP"}}
  ]
}

Scene I/O

excalidraw export [--out scene.excalidraw]
excalidraw import scene.excalidraw [--mode replace|merge]
excalidraw snapshot v1
excalidraw restore v1
excalidraw describe

Viewport

excalidraw viewport --fit
excalidraw viewport --element <id>
excalidraw viewport --zoom 1.5
excalidraw screenshot [--format png|svg] [--out file.png]

Layout

excalidraw align id1 id2 id3 --alignment left|right|center|top|bottom|middle
excalidraw distribute id1 id2 id3 --direction horizontal|vertical
excalidraw group id1 id2 id3
excalidraw ungroup <groupId>
excalidraw duplicate id1 id2 [--dx 20] [--dy 20]
excalidraw lock id1 id2
excalidraw unlock id1 id2

Utilities

excalidraw url                        # Shareable excalidraw.com link (encrypted)
excalidraw mermaid diagram.mmd        # Convert Mermaid diagram to Excalidraw
echo "graph TD; A-->B" | excalidraw mermaid
excalidraw guide                      # Print design guide as JSON

Environment Variables

Variable Default Description
EXCALIDRAW_URL http://localhost:3000 Canvas server URL

Docker Compose

For a persistent, auto-restart setup (canvas survives reboots):

docker compose up -d      # start in background
docker compose down       # stop
docker compose logs -f    # stream logs

docker-compose.yml is included in the repo and pulls the prebuilt image from GHCR — no build step required.


Development

bun install
bun run src/cli.ts --help     # Run CLI directly (no build step)
bun src/server.ts             # Start canvas server directly
bun run type-check            # TypeScript check
bun run build:frontend        # Build React frontend

Known Limitations

  • In-memory state — restarting the server clears the canvas. Use excalidraw export to persist.
  • Screenshot needs a browserexcalidraw screenshot requires the canvas open in a browser tab.

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 11

Languages