npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

excalidraw-room-cli

v0.1.6

Published

JSON-first CLI for editing shared Excalidraw rooms

Downloads

64

Readme

Excalidraw Room CLI

excalidraw-room is a JSON-first CLI for reading, editing, and exporting shared Excalidraw rooms.

It is useful when you want a script or an AI agent to make precise changes to a live Excalidraw room without clicking around in the browser UI.

Requirements

  • Bun 1.1+
  • Node.js, used by the export runner
  • Google Chrome or Chromium for PNG/SVG export

If Chrome is not in a standard location, set:

export EXCALIDRAW_ROOM_CHROME_BIN="/path/to/chrome"

Install

From npm:

npm install -g excalidraw-room-cli@latest

From GitHub with Bun:

bun add -g excalidraw-room-cli

Check the install:

excalidraw-room help
excalidraw-room version

Quick Start

Create a new shared room:

ROOM_URL="$(excalidraw-room create-room --json | bun -e 'const data = await Bun.stdin.json(); console.log(data.roomUrl)')"

Or use an existing Excalidraw shared room URL:

ROOM_URL="https://excalidraw.com/#room=...,..."

Inspect the room:

excalidraw-room status "$ROOM_URL"
excalidraw-room dump "$ROOM_URL" room.json

Add elements:

excalidraw-room apply-json "$ROOM_URL" <<'JSON'
{
  "mode": "append",
  "ops": [
    {
      "type": "addRect",
      "x": 80,
      "y": 80,
      "width": 260,
      "height": 140,
      "backgroundColor": "#dbe4ff",
      "label": "Agent\nentrypoint"
    },
    {
      "type": "addArrow",
      "x1": 340,
      "y1": 150,
      "x2": 420,
      "y2": 150
    }
  ]
}
JSON

Export the room:

excalidraw-room export-image "$ROOM_URL" room.png
excalidraw-room export-image "$ROOM_URL" room.svg

Commands

excalidraw-room help
excalidraw-room version
excalidraw-room create-room [--json]
excalidraw-room status <roomUrl>
excalidraw-room dump <roomUrl> [out.json]
excalidraw-room watch <roomUrl>
excalidraw-room snapshot <roomUrl> [out.json]
excalidraw-room restore <roomUrl> <snapshot.json>
excalidraw-room apply-json <roomUrl> [spec.json|-]
excalidraw-room send-file <roomUrl> <elements.json> [--mode append|replace]
excalidraw-room export-image <roomUrl> <out.png|out.svg> [options]

Agent integration commands:

excalidraw-room skill
excalidraw-room skills list
excalidraw-room skills get core
excalidraw-room setup --all-agents

Version Check

excalidraw-room version

Prints the installed package version, checks the latest version in npm, and shows update commands when a newer version is available.

Create Room

excalidraw-room create-room

Creates an empty shared Excalidraw room and prints:

  • roomId
  • roomKey
  • roomUrl

Use --json when another tool needs to consume the result:

excalidraw-room create-room --json

Example output:

{
  "roomId": "JUP-lk92luW3XjW16k3c",
  "roomKey": "m7D7utg2V8m2ptM-A2kHWg",
  "roomUrl": "https://excalidraw.com/#room=JUP-lk92luW3XjW16k3c,m7D7utg2V8m2ptM-A2kHWg"
}

Apply JSON

apply-json is the main write command:

excalidraw-room apply-json <roomUrl> [spec.json|-]

Input can come from:

  • a file: apply-json <roomUrl> spec.json
  • stdin: apply-json <roomUrl> -
  • stdin without -: apply-json <roomUrl>

Format 1: Command

Add elements:

{
  "command": "elements.add",
  "ops": [
    {
      "type": "addRect",
      "x": 80,
      "y": 80,
      "width": 260,
      "height": 140,
      "backgroundColor": "#dbe4ff",
      "label": "Planner\nstep"
    }
  ]
}

Update existing elements:

{
  "command": "elements.update",
  "updates": [
    {
      "id": "element-id",
      "set": {
        "text": "Updated label",
        "fontFamily": 2
      }
    }
  ]
}

Delete elements:

{
  "command": "elements.delete",
  "ids": ["id-1", "id-2"]
}

Delete all live elements:

{
  "command": "elements.delete",
  "all": true
}

Format 2: Transaction

Full redraw is an explicit transaction. Deletion creates tombstones so open browser clients remove old elements.

{
  "commands": [
    { "command": "elements.delete", "all": true },
    {
      "command": "elements.add",
      "ops": [
        { "type": "addText", "x": 100, "y": 100, "text": "New scene" }
      ]
    }
  ]
}

Transactions are simulated in order and written once. If any command is invalid, no room update is written.

Format 3: Legacy Operation Array

[
  {
    "type": "addRect",
    "x": 80,
    "y": 80,
    "width": 260,
    "height": 140,
    "backgroundColor": "#dbe4ff",
    "label": "Planner\nstep"
  },
  {
    "type": "addArrow",
    "x1": 340,
    "y1": 150,
    "x2": 420,
    "y2": 150
  }
]

Format 4: Legacy Mode and Operations

{
  "mode": "append",
  "ops": [
    {
      "type": "addRect",
      "x": 80,
      "y": 80,
      "width": 260,
      "height": 140,
      "backgroundColor": "#dbe4ff",
      "label": "Planner\nstep"
    }
  ]
}

Supported modes:

  • append: add new elements without removing existing elements
  • replace: replace the scene
  • patch: update existing elements by id

Prefer command payloads for new work. Legacy replace remains available for compatibility.

Format 5: Legacy Raw Elements

{
  "mode": "replace",
  "elements": [
    {
      "id": "custom-id",
      "type": "rectangle"
    }
  ]
}

Command payloads can also add strict raw Excalidraw elements:

{
  "command": "elements.add",
  "elements": []
}

Raw elements must be complete Excalidraw elements. elements.add fails when an incoming id already exists live.

Operations

addRect

{
  "type": "addRect",
  "x": 80,
  "y": 80,
  "width": 260,
  "height": 140,
  "backgroundColor": "#dbe4ff",
  "strokeColor": "#1e1e1e",
  "label": "Agent\nentrypoint",
  "labelFontSize": 24,
  "labelColor": "#1e1e1e"
}

addText

{
  "type": "addText",
  "x": 220,
  "y": 240,
  "text": "Free note",
  "fontSize": 24,
  "strokeColor": "#1e1e1e",
  "textAlign": "center"
}

addArrow

By coordinates:

{
  "type": "addArrow",
  "x1": 340,
  "y1": 150,
  "x2": 420,
  "y2": 150,
  "strokeColor": "#1e1e1e"
}

Between existing elements:

{
  "type": "addArrow",
  "fromId": "left-card-id",
  "toId": "right-card-id",
  "strokeColor": "#1e1e1e"
}

move

{
  "type": "move",
  "id": "element-id",
  "dx": 40,
  "dy": 20
}

or:

{
  "type": "move",
  "id": "element-id",
  "x": 600,
  "y": 320
}

delete

{
  "type": "delete",
  "ids": ["id-1", "id-2", "id-3"]
}

For new payloads, prefer the command form:

{
  "command": "elements.delete",
  "ids": ["id-1", "id-2", "id-3"]
}

Export

excalidraw-room export-image "$ROOM_URL" room.png
excalidraw-room export-image "$ROOM_URL" room.svg
excalidraw-room export-image "$ROOM_URL" crop.png --crop 80,360,1900,980
excalidraw-room export-image "$ROOM_URL" one.png --crop-element <id> --padding 40
excalidraw-room export-image "$ROOM_URL" group.png --crop-elements <id1,id2,id3> --padding 60

Export uses Excalidraw scene JSON and @excalidraw/excalidraw. It is not a browser screenshot.

Crop coordinates use Excalidraw scene coordinates.

Agent Setup

Install the local discovery skill for supported agents:

excalidraw-room setup --all-agents

Or install it for one target:

excalidraw-room setup --claude
excalidraw-room setup --codex
excalidraw-room setup --cursor
excalidraw-room setup --universal

This writes a small discovery SKILL.md into standard local skill directories. The full agent workflow is available through:

excalidraw-room skill

Local Files

The CLI stores runtime files under:

  • snapshots: ~/.excalidraw-room-cli/snapshots
  • export cache: ~/.excalidraw-room-cli/cache

Compatibility

apply-spec is still accepted as a compatibility alias for apply-json. Prefer apply-json for new usage.