feat(plugins): add Codex CLI plugin mirroring the Claude Code plugin

Ports the official draw.io `drawio` skill to OpenAI's Codex CLI as a
sibling of the existing Claude Code plugin.

- plugins/codex/drawio/: Codex plugin root (folder name == plugin.json
  "name", as Codex requires), nested under the codex/ host group.
  - .codex-plugin/plugin.json with an interface block (official draw.io
    SVG logo, brandColor #F08705, display name, default prompts)
  - skills/drawio/SKILL.md byte-identical to the Claude plugin's copy
    (Codex uses the same /drawio:drawio invocation and fetches the same
    shared references from GitHub — no in-repo duplication)
  - assets/drawio-logo.svg (official drawio-desktop icon), README, DEVELOPING
- .agents/plugins/marketplace.json: Codex marketplace manifest at the repo
  root, alongside the Claude .claude-plugin/marketplace.json
- docs: plugins/README.md, README.md, CLAUDE.md updated for the new host

Verified with the local codex CLI: `codex plugin marketplace add` +
`codex plugin list` resolve drawio@drawio v1.1.0 from the manifest.
This commit is contained in:
Roman Bange
2026-07-16 18:20:40 +02:00
parent d9dc69efea
commit 9c00f62de2
9 changed files with 723 additions and 3 deletions
+20
View File
@@ -0,0 +1,20 @@
{
"name": "drawio",
"interface": {
"displayName": "draw.io"
},
"plugins": [
{
"name": "drawio",
"source": {
"source": "local",
"path": "./plugins/codex/drawio"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Productivity"
}
]
}
+2
View File
@@ -5,12 +5,14 @@ The official draw.io MCP (Model Context Protocol) server that enables LLMs to op
## Repository Structure
- **`.claude-plugin/marketplace.json`** — Claude Code plugin marketplace manifest. Lists this repo's plugins (currently just `drawio`, sourced from `./plugins/claude-code`); plugin metadata is inherited from each plugin's own `plugin.json`. Users install with `/plugin marketplace add jgraph/drawio-mcp` then `/plugin install drawio@drawio`.
- **`.agents/plugins/marketplace.json`** — Codex CLI plugin marketplace manifest (Codex's format: `source` object + `policy` + `category`). Lists the `drawio` plugin sourced from `./plugins/codex/drawio`; metadata is inherited from that plugin's own `.codex-plugin/plugin.json`. Users install with `codex plugin marketplace add jgraph/drawio-mcp` then `codex plugin add drawio@drawio`.
- **`shared/`** — Shared XML generation reference (`xml-reference.md`), the single source of truth for all LLM prompts.
- **`mcp-app-server/`** — MCP App server (renders diagrams inline in chat via iframe). Hosted at `https://mcp.draw.io/mcp`. Can also be self-hosted via Node.js or Cloudflare Workers.
- **`mcp-tool-server/`** — Original MCP tool server (stdio-based, opens browser). Published as `@drawio/mcp` on npm.
- **`project-instructions/`** — Claude Project instructions (no MCP required, no install).
- **`plugins/`** — Assistant-side plugins grouped by host, one subdirectory per AI assistant.
- **`plugins/claude-code/`** — Claude Code plugin: ships the `drawio` skill (generates native `.drawio` files, authored as Mermaid — converted + laid out by the desktop CLI — or as XML directly with optional ELK `--layout`; exports to PNG/SVG/PDF, or opens as a browser URL via `app.diagrams.net`). Mermaid conversion, ELK layout, and image export need draw.io Desktop; plain XML `.drawio`/`url` output does not. Installable via the repo-root marketplace or `claude --plugin-dir ./plugins/claude-code`. No MCP required.
- **`plugins/codex/drawio/`** — Codex CLI plugin: the Codex port of the Claude Code plugin, shipping the same `drawio` skill. `skills/drawio/SKILL.md` is byte-identical to the Claude plugin's copy (Codex uses the same `/drawio:drawio` invocation and fetches the same shared references from GitHub). Differs only in host wrapping: a `.codex-plugin/plugin.json` manifest with an `interface` block (official draw.io SVG logo, `brandColor`, default prompts). Nested under `codex/` because Codex requires the plugin root folder name to equal `plugin.json` `"name"` (`drawio`). No MCP required.
- **`shape-search/`** — Shape search index generator. Loads draw.io's `app.min.js` via jsdom to extract all shape styles and tags into `search-index.json`, which powers the `search_shapes` MCP tool. Re-run after updating `drawio-dev` to pick up new or changed shapes.
Most subdirectories have their own `CLAUDE.md` with implementation details.
+9
View File
@@ -73,6 +73,15 @@ By default, the plugin writes a `.drawio` file and opens it in draw.io. Mention
**[Full documentation →](plugins/claude-code/README.md)**
The same `drawio` skill is also packaged as a **Codex CLI** plugin (under [`plugins/codex/drawio/`](plugins/codex/drawio/README.md)) — install it inside Codex with:
```bash
codex plugin marketplace add jgraph/drawio-mcp
codex plugin add drawio@drawio
```
**[Full documentation →](plugins/codex/drawio/README.md)**
---
## Alternative: Project Instructions (No MCP Required)
+21 -3
View File
@@ -5,23 +5,41 @@ This directory groups assistant-side integrations by **host** — one subdirecto
| Directory | Host | Status |
|-----------|------|--------|
| [`claude-code/`](claude-code/README.md) | [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | ✅ Available |
| [`codex/drawio/`](codex/drawio/README.md) | [Codex CLI](https://github.com/openai/codex) | ✅ Available |
The Claude Code plugin is published through a marketplace manifest at the repo root ([`.claude-plugin/marketplace.json`](../.claude-plugin/marketplace.json)), so users can install it with:
Each host has its own marketplace manifest at the repo root, so users install with that
host's own commands.
**Claude Code** — via [`.claude-plugin/marketplace.json`](../.claude-plugin/marketplace.json):
```
/plugin marketplace add jgraph/drawio-mcp
/plugin install drawio@drawio
```
**Codex** — via [`.agents/plugins/marketplace.json`](../.agents/plugins/marketplace.json):
```bash
codex plugin marketplace add jgraph/drawio-mcp
codex plugin add drawio@drawio
```
## Adding a plugin for another host
If support for another assistant (Cursor, Codex, etc.) is added later, it lands as a sibling directory at this level:
Support for a new assistant lands as a sibling directory at this level:
```
plugins/
── claude-code/ ← Claude Code plugin
── claude-code/ ← Claude Code plugin (plugin root)
└── codex/ ← Codex host group
└── drawio/ ← Codex plugin root (folder name == plugin.json "name")
```
Codex normalizes a plugin's root folder name to match its `plugin.json` `"name"`, so the
Codex plugin root is nested one level (`codex/drawio/`) inside the host group directory;
Claude Code has no such rule, so `claude-code/` is itself the plugin root. If another
assistant (Cursor, etc.) is added later, it follows the same pattern in its own way.
The draw.io guidance itself — *how* to generate `.drawio` files, embed XML in PNG/SVG/PDF, and produce `app.diagrams.net` URLs — is shared. Only the wrapping (manifest format, file layout, invocation prefix) differs per host, and each host has its own plugin/skill model, so the wrapping is not assumed to be uniform.
The single source of truth for draw.io XML generation guidance lives at [`../shared/xml-reference.md`](../shared/xml-reference.md) — every plugin references that file rather than duplicating its contents.
@@ -0,0 +1,40 @@
{
"name": "drawio",
"version": "1.1.0",
"description": "Generate native .drawio diagrams from Codex using Mermaid or XML, with optional ELK layout, PNG/SVG/PDF export, and browser URL output.",
"author": {
"name": "draw.io",
"url": "https://www.drawio.com"
},
"homepage": "https://github.com/jgraph/drawio-mcp/tree/main/plugins/codex/drawio",
"repository": "https://github.com/jgraph/drawio-mcp",
"license": "Apache-2.0",
"keywords": [
"draw.io",
"diagrams",
"mermaid",
"flowcharts",
"xml"
],
"skills": "./skills/",
"interface": {
"displayName": "draw.io",
"shortDescription": "Create editable draw.io diagrams in Codex.",
"longDescription": "Generate native .drawio files from Mermaid or draw.io XML, optionally apply ELK layouts, export editable PNG/SVG/PDF files with embedded diagram XML, or open diagrams in the draw.io browser editor.",
"developerName": "draw.io",
"category": "Productivity",
"capabilities": [
"Skills"
],
"websiteURL": "https://www.drawio.com",
"brandColor": "#F08705",
"composerIcon": "./assets/drawio-logo.svg",
"logo": "./assets/drawio-logo.svg",
"logoDark": "./assets/drawio-logo.svg",
"defaultPrompt": [
"Create a flowchart for user login.",
"Draw an architecture diagram for this system.",
"Export this diagram as an editable SVG."
]
}
}
+90
View File
@@ -0,0 +1,90 @@
# Codex Plugin: drawio
A Codex CLI plugin that ships the `drawio` skill: it generates native `.drawio` files,
authored either as Mermaid (converted + laid out by the draw.io desktop CLI) or as draw.io
XML directly, with optional ELK `--layout` for XML, export to PNG/SVG/PDF (with embedded XML)
via the desktop CLI, or a browser URL that opens the diagram directly at `app.diagrams.net`.
No MCP server required.
This is the Codex counterpart of the [Claude Code plugin](../../claude-code/README.md). The
skill body is host-agnostic — it drives the draw.io Desktop CLI directly — so
`skills/drawio/SKILL.md` is kept **byte-identical** to the Claude plugin's `SKILL.md`
(including the `/drawio:drawio` invocation examples, which Codex uses too). Only the host
wrapping differs: the manifest schema (`.codex-plugin/plugin.json` vs `.claude-plugin/plugin.json`),
the `interface` block (Codex-only — logo, brand color, default prompts), and the marketplace
format.
## Key Files
| File | Purpose |
|------|---------|
| `.codex-plugin/plugin.json` | Codex plugin manifest — name, version, description, author, license, and the `interface` block (display name, logo, `brandColor`, default prompts) |
| `skills/drawio/SKILL.md` | The skill itself (its folder name `drawio` becomes the second half of the `/drawio:drawio` invocation); byte-identical to the Claude plugin's copy |
| `assets/drawio-logo.svg` | Official draw.io logo (vector `drawio-desktop` icon), referenced by `interface.composerIcon`/`logo`/`logoDark` |
| `README.md` | Installation and usage documentation |
| `../../../.agents/plugins/marketplace.json` | Codex marketplace manifest at the repo root; lists this plugin with `source.path: "./plugins/codex/drawio"` and inherits the rest of its metadata from `plugin.json` |
## Layout
Codex normalizes a plugin's root folder name to match `plugin.json` `"name"`. To keep the
repo's one-directory-per-host convention (`plugins/<host>/`, see
[`plugins/README.md`](../../README.md)) **and** satisfy Codex's folder==name rule, the plugin
root is nested one level inside the host directory:
```
plugins/codex/ ← host group directory
└── drawio/ ← Codex plugin root (folder name == plugin.json "name" = "drawio")
├── .codex-plugin/plugin.json
├── skills/drawio/SKILL.md
├── assets/drawio-logo.svg
├── README.md
└── DEVELOPING.md
```
## References (fetched, not bundled)
Like the Claude plugin, `SKILL.md` fetches the two shared guides via their GitHub raw URLs at
runtime — the single source of truth for all draw.io prompts — so nothing is duplicated in
the plugin:
- `https://raw.githubusercontent.com/jgraph/drawio-mcp/main/shared/xml-reference.md`
- `https://raw.githubusercontent.com/jgraph/drawio-mcp/main/shared/mermaid-reference.md`
When updating diagram-generation guidance, edit only the files under `shared/` — changes
propagate to this plugin (and every other consumer) automatically.
## URL Mode Compatibility
The `url` mode produces the exact same `https://app.diagrams.net/#create=...` URL format as
the [MCP Tool Server](../../../mcp-tool-server/README.md) (`mcp-tool-server/src/index.js`).
Node.js's built-in `zlib.deflateRawSync` and `pako.deflateRaw` both implement RFC 1951, so
their outputs are interchangeable. No external npm dependencies are added to the skill — only
Node.js built-ins (`zlib`, `child_process`, `fs`, `os`, `path`).
## draw.io CLI Locations
- **macOS**: `/Applications/draw.io.app/Contents/MacOS/draw.io`
- **Linux**: `drawio` (on PATH via snap/apt/flatpak)
- **Windows**: `"C:\Program Files\draw.io\draw.io.exe"`
- **WSL2**: `"/mnt/c/Program Files/draw.io/draw.io.exe"` (detect via `grep -qi microsoft /proc/version`)
The skill tries `drawio` first, then falls back to the platform-specific path. On WSL2, use
`wslpath -w` to convert paths when opening files with `cmd.exe /c start`.
## Testing Locally
```bash
codex plugin marketplace add /path/to/drawio-mcp
codex plugin add drawio@drawio
codex plugin list # confirm drawio@drawio appears
```
Then ask Codex for a diagram, or invoke `/drawio:drawio ...`, and confirm the `.drawio` file
(or export / URL) is produced.
## Coding Conventions
- **Allman brace style**: Opening braces go on their own line for all control structures,
functions, objects, and callbacks.
- Prefer `function()` expressions over arrow functions for callbacks.
- See the root `CLAUDE.md` for examples.
+130
View File
@@ -0,0 +1,130 @@
# Draw.io Plugin for Codex
A [Codex CLI](https://github.com/openai/codex) plugin that generates native `.drawio`
files. Codex authors each diagram as **Mermaid** (converted and laid out by the draw.io
desktop CLI) or as **draw.io XML** directly — with optional **ELK auto-layout** for XML,
export to PNG/SVG/PDF (with embedded XML so the file remains editable in draw.io), or a
browser URL that opens the diagram directly in `app.diagrams.net`. No MCP setup required.
This is the Codex port of the [Claude Code plugin](../../claude-code/README.md); it ships
the same `drawio` skill. Only the host wrapping (manifest schema, invocation, logo) differs —
the draw.io guidance itself is the shared single source of truth in [`shared/`](../../../shared).
## How It Works
When you ask Codex to create a diagram, it will:
1. Choose how to author it — **Mermaid** for standard types (flowchart, sequence, class,
state, ER, gantt, mindmap…) when the desktop app is installed, or **draw.io XML** for
custom styling, precise positioning, specific shape libraries, or when no desktop app is
present
2. Produce a native `.drawio` file — convert the Mermaid with the desktop CLI, or write the
XML directly (optionally running an ELK `--layout` pass so you don't hand-place cells)
3. Handle the requested output:
- PNG / SVG / PDF — export using the draw.io desktop CLI
- `url` — compress the XML with Node.js's built-in `zlib` and open
`https://app.diagrams.net/#create=...` in your browser (keeps the `.drawio` file as a
local copy)
- *(default)* — leave the `.drawio` file as-is
4. Open the result
## Prerequisites
- [Codex CLI](https://github.com/openai/codex) installed
- [draw.io Desktop](https://github.com/jgraph/drawio-desktop/releases) installed — required
for Mermaid conversion, ELK layout, and PNG/SVG/PDF export. Not needed for plain XML
`.drawio` or `url` output, which Codex can produce with no desktop app
## Installation
### Via the drawio marketplace (recommended)
Add this repository as a Codex plugin marketplace, then install the plugin:
```bash
codex plugin marketplace add jgraph/drawio-mcp
codex plugin add drawio@drawio
```
The Codex marketplace manifest lives at
[`.agents/plugins/marketplace.json`](../../../.agents/plugins/marketplace.json) at the repo
root and points at this directory (`./plugins/codex/drawio`). The rest of the plugin's
metadata is inherited from [`.codex-plugin/plugin.json`](.codex-plugin/plugin.json).
### Local development
To add the marketplace from a local clone (e.g. while iterating on the skill), point
`codex plugin marketplace add` at the repo root instead of the `owner/repo` slug:
```bash
codex plugin marketplace add /path/to/drawio-mcp
codex plugin add drawio@drawio
```
## Usage
In most cases you don't type a command at all — just ask Codex for a diagram ("draw a
flowchart for user login") and the skill triggers automatically from its description. To
invoke it explicitly, Codex namespaces plugin skills as `/<plugin>:<skill>`, so the command
is `/drawio:drawio`:
```
/drawio:drawio create a flowchart for user login
```
By default, this writes a `.drawio` file and opens it in draw.io. To export to an image
format or open the diagram in the browser, mention the format in your request:
```
/drawio:drawio png flowchart for user login → login-flow.drawio.png
/drawio:drawio svg: ER diagram for e-commerce → er-diagram.drawio.svg
/drawio:drawio pdf architecture overview → architecture-overview.drawio.pdf
/drawio:drawio url flowchart for user login → opens app.diagrams.net in browser, keeps login-flow.drawio locally
```
## Output Formats
| Format | Output | Editor | Dependency |
|--------|--------|--------|------------|
| (default) | `.drawio` file | draw.io Desktop, or the browser app | None |
| `png` | `.drawio.png` (embedded XML) | draw.io Desktop, or any viewer | draw.io Desktop (for export) |
| `svg` | `.drawio.svg` (embedded XML) | draw.io Desktop, or any viewer | draw.io Desktop (for export) |
| `pdf` | `.drawio.pdf` (embedded XML) | draw.io Desktop, or any PDF viewer | draw.io Desktop (for export) |
| `url` | Browser tab at `app.diagrams.net` + `.drawio` file kept locally | draw.io editor in browser | Node.js |
The `.drawio.*` double extension signals that the file contains embedded diagram XML. Open
any of these in draw.io to recover and edit the full diagram. The intermediate `.drawio`
source file is deleted after image export since the exported file contains the complete
diagram. In `url` mode, the `.drawio` file is kept so you have a persistent local copy to
re-edit or share.
`url` mode uses only Node.js's built-in `zlib` (deflate-raw compression) and `child_process`
(browser open) — no external dependencies. The resulting `https://app.diagrams.net/#create=...`
URL is the same format used by the [MCP Tool Server](../../../mcp-tool-server/README.md), so
behavior is identical.
## References
The skill fetches two shared guides from GitHub at runtime — the single source of truth for
all draw.io prompts across the repository. No extra files are bundled in the plugin.
- [`shared/xml-reference.md`](../../../shared/xml-reference.md) — draw.io XML generation
(edge routing, containers, layers, tags, metadata, dark mode, etc.), used when authoring XML
- [`shared/mermaid-reference.md`](../../../shared/mermaid-reference.md) — Mermaid syntax for
all supported diagram types plus flowchart styling, used when authoring Mermaid
## Logo
The Codex `interface` uses the official draw.io logo
([`assets/drawio-logo.svg`](assets/drawio-logo.svg), the vector
[`drawio-desktop` icon](https://github.com/jgraph/drawio-desktop/blob/dev/build/icon.svg))
for the composer icon and the light/dark plugin logo, with `brandColor` `#F08705`.
## Other Variants
This repository offers multiple ways to integrate draw.io with AI assistants:
- **[Claude Code Plugin](../../claude-code/README.md)** — the same `drawio` skill for Claude Code
- **[MCP App Server](../../../mcp-app-server/README.md)** — Inline diagrams in chat (Claude.ai, VS Code)
- **[MCP Tool Server](../../../mcp-tool-server/README.md)** — Opens diagrams in browser via MCP (Claude Desktop)
- **[Project Instructions](../../../project-instructions/README.md)** — Claude.ai Projects, no install needed
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 161.6 161.6" style="enable-background:new 0 0 161.6 161.6;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F08705;}
.st1{fill:#DF6C0C;}
.st2{fill:#FFFFFF;}
.st3{fill:#333333;}
</style>
<g>
<path class="st0" d="M161.6,154.7c0,3.9-3.2,6.9-6.9,6.9H6.9c-3.9,0-6.9-3.2-6.9-6.9V6.9C0,3,3.2,0,6.9,0h147.8
c3.9,0,6.9,3.2,6.9,6.9L161.6,154.7L161.6,154.7z"/>
<g>
<path class="st1" d="M161.6,154.7c0,3.9-3.2,6.9-6.9,6.9H55.3l-32.2-32.7l20-32.7l59.4-73.8l58.9,60.7L161.6,154.7z"/>
</g>
<path class="st2" d="M132.7,90.3h-17l-18-30.6c4-0.8,7-4.4,7-8.6V28c0-4.9-3.9-8.8-8.8-8.8h-30c-4.9,0-8.8,3.9-8.8,8.8v23.1
c0,4.3,3,7.8,6.9,8.6L46,90.4H29c-4.9,0-8.8,3.9-8.8,8.8v23.1c0,4.9,3.9,8.8,8.8,8.8h30c4.9,0,8.8-3.9,8.8-8.8V99.2
c0-4.9-3.9-8.8-8.8-8.8h-2.9L73.9,60h13.9l17.9,30.4h-3c-4.9,0-8.8,3.9-8.8,8.8v23.1c0,4.9,3.9,8.8,8.8,8.8h30
c4.9,0,8.8-3.9,8.8-8.8V99.2C141.5,94.3,137.6,90.3,132.7,90.3z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+389
View File
@@ -0,0 +1,389 @@
---
name: drawio
description: Always use when user asks to create, generate, draw, or design a diagram, flowchart, architecture diagram, ER diagram, sequence diagram, class diagram, network diagram, mockup, wireframe, or UI sketch, or mentions draw.io, drawio, drawoi, .drawio files, or diagram export to PNG/SVG/PDF.
---
# Draw.io Diagram Skill
Generate draw.io diagrams as native `.drawio` files. Author each diagram either as **Mermaid** (concise text that the draw.io desktop CLI converts and lays out for you) or as **draw.io XML** directly. Optionally auto-layout XML-authored diagrams with **ELK**, export to PNG/SVG/PDF with the diagram XML embedded (so the exported file stays editable in draw.io), or generate a browser URL that opens the diagram directly in the draw.io editor.
## Authoring: Mermaid or XML?
The desktop CLI can convert Mermaid to a native `.drawio` file, so **prefer Mermaid** for the diagram types it handles well — its parser lays the diagram out automatically, which is far more reliable than hand-positioning cells in XML.
| Author as | Best for | Needs desktop CLI? |
|-----------|----------|--------------------|
| **Mermaid** | Flowcharts, sequence, class, state, ER, gantt, mindmap, timeline, user journey, quadrant, C4, git graph, pie, and other standard types | Yes — to convert to `.drawio` |
| **XML** | Custom styling, precise/hand positioning, specific shape libraries (AWS, Azure, network, UML detail…), or when the desktop CLI is not installed | No (optional ELK `--layout` needs the CLI) |
- **Prefer Mermaid** when the desktop CLI is available and the request is one of the standard types above — write terse Mermaid and let draw.io lay it out.
- **Use XML** for precise control, or as the universal fallback: XML needs no CLI at all, so it's the only option when the desktop app isn't installed (output a `.drawio` file or a `url`).
- For XML-authored diagrams you can ask the CLI to apply an **ELK auto-layout** (`--layout`) instead of computing coordinates yourself — the same layouts the draw.io editor's *Arrange ▸ Layout* menu applies, and the same engine the draw.io MCP app server uses. See [ELK layout for XML](#elk-layout-for-xml).
If you're unsure whether the desktop CLI is present, detect it first (see [Locating the CLI](#locating-the-cli)). No CLI → author as XML and deliver a `.drawio` file or a `url`.
## The pipeline
Every diagram becomes a native `.drawio` file first, then is delivered in the requested output format. This keeps the delivery step identical whether you authored Mermaid or XML.
1. **Author → `.drawio`**
- **Mermaid**: write the Mermaid to a `.mmd` file, then convert it with the CLI:
```bash
drawio -x -f xml -o diagram.drawio diagram.mmd
```
Delete the `.mmd` afterward — the `.drawio` is the artifact. draw.io's Mermaid parser has already laid the diagram out, so no `--layout` is needed.
- **XML**: write the mxGraphModel XML to `diagram.drawio` (see [XML format](#xml-format)). Optionally apply an ELK layout (see [ELK layout for XML](#elk-layout-for-xml)).
2. **Deliver** (identical for both sources):
- *(no format)* → keep `diagram.drawio` and open it.
- **png / svg / pdf** → export from the `.drawio` with embedded XML, then delete the source `.drawio`:
```bash
drawio -x -f png -e -b 10 -o diagram.drawio.png diagram.drawio
```
- **url** → build a browser URL from the `.drawio` XML, open it, and keep the `.drawio` as a local copy (see [Browser URL output](#browser-url-output)).
3. **Open the result** — the exported file, the URL, or the `.drawio`. If the open command fails, print the absolute path (or URL) so the user can open it manually.
**Always convert Mermaid to `.drawio` first, then export** — do not export a `.mmd` straight to an image. Direct Mermaid → PNG export with `-e` is broken in current draw.io Desktop (the embedded-XML step crashes); the two-step path (convert, then export the `.drawio`) is reliable and produces an editable embed. See [Troubleshooting](#troubleshooting).
If Mermaid was requested but no desktop CLI is available, fall back to authoring the same diagram directly as XML.
## ELK layout for XML
XML-authored diagrams can be auto-positioned by the CLI's `--layout` pass — the same ELK layouts as the editor's *Arrange ▸ Layout* menu and the same engine the draw.io MCP app server uses. Generate the cells with approximate (or even `0,0`) positions and let ELK place them; you only have to get the graph *structure* — nodes and edges — right.
Add `--layout <name>` to any CLI call that reads your XML. The simplest form lays out in place after you write the file (reading and overwriting the same path is supported):
```bash
drawio -x -f xml --layout verticalFlow -o diagram.drawio diagram.drawio
```
Or combine layout with export in a single call (works for XML input):
```bash
drawio -x -f png -e -b 10 --layout verticalFlow -o diagram.drawio.png diagram.drawio
```
### Layout presets
| Name | Layout |
|------|--------|
| `verticalFlow` | Layered, top-to-bottom — flowcharts, pipelines |
| `horizontalFlow` | Layered, left-to-right |
| `verticalTree` | Tree, top-down — hierarchies, org charts |
| `horizontalTree` | Tree, left-to-right |
| `radialTree` | Radial tree |
| `organic` | Force-directed — networks, mind-map-like graphs |
### Custom layout JSON
For finer control, pass a JSON **array** (starting with `[`) instead of a preset name — the same format as the editor's custom-layout dialog:
```bash
drawio -x -f xml --layout '[{"layout":"elkLayered","config":{"elk.direction":"RIGHT"}}]' -o diagram.drawio diagram.drawio
```
Each entry is `{"layout": <algorithm>, "config": { … }}`:
- **Algorithms**: `elkLayered`, `elkTree`, `elkRadial`, `elkOrganic`, `elkStress`, `elkBox`.
- **`config`**: keys starting with `elk.` are ELK options — e.g. `elk.direction` (`UP` / `DOWN` / `LEFT` / `RIGHT`), `elk.spacing.nodeNode`, `elk.layered.spacing.nodeNodeBetweenLayers`. The keys `edgeStyle` (e.g. `orthogonal`) and `corners` (e.g. `rounded`) control connector rendering.
### Orthogonal edge routing
`--layout libavoid` routes the **edges** orthogonally around the shapes (the editor's *Arrange ▸ Layout ▸ Orthogonal Routing*) without moving any vertex — the complement of the node layouts above. Use it as an in-place pass on hand-positioned XML whose connectors cross shapes:
```bash
drawio -x -f xml --layout libavoid -o diagram.drawio diagram.drawio
```
Skip it after a flow/tree preset — those already route their edges.
**When to use it:** author the graph structure as XML without worrying about coordinates, then apply `verticalFlow` / `horizontalFlow` for flow-style diagrams or `organic` for networks. Mermaid-authored diagrams are already laid out — don't add `--layout`.
## Mermaid syntax reference
When authoring Mermaid, fetch and follow the shared Mermaid reference (all supported diagram types plus flowchart styling — `style`, `classDef`, `linkStyle`):
https://raw.githubusercontent.com/jgraph/drawio-mcp/main/shared/mermaid-reference.md
Match the language of the diagram labels to the user's language.
## Choosing the output format
Check the user's request for a format preference. Examples:
- `/drawio:drawio create a flowchart` → Mermaid → `flowchart.drawio`
- `/drawio:drawio png flowchart for login` → Mermaid → `login-flow.drawio.png`
- `/drawio:drawio svg: ER diagram` → Mermaid → `er-diagram.drawio.svg`
- `/drawio:drawio pdf AWS architecture overview` → XML (needs AWS shapes) → `architecture-overview.drawio.pdf`
- `/drawio:drawio url flowchart for user login` → opens browser at `app.diagrams.net` with the diagram, keeps `login-flow.drawio` locally
If no format is mentioned, just produce the `.drawio` file and open it in draw.io. The user can always ask to export later.
### Supported export formats
| Format | Embed XML | Notes |
|--------|-----------|-------|
| `png` | Yes (`-e`) | Viewable everywhere, editable in draw.io |
| `svg` | Yes (`-e`) | Scalable, editable in draw.io |
| `pdf` | Yes (`-e`) | Printable, editable in draw.io |
| `jpg` | No | Lossy, no embedded XML support |
PNG, SVG, and PDF all support `--embed-diagram` — the exported file contains the full diagram XML, so opening it in draw.io recovers the editable diagram.
## Browser URL output
When the user requests `url` format, generate a draw.io URL that opens the diagram directly in the browser editor at `app.diagrams.net` — no draw.io Desktop required to *view* it. (Mermaid-authored diagrams still need the desktop CLI to convert to `.drawio` first; if no CLI is available, author the diagram as XML and build the URL from that.)
### How it works
1. The `.drawio` file is written to disk as usual (gives the user a persistent local copy they can re-edit)
2. The XML is compressed with Node.js's built-in `zlib` and base64-encoded
3. The result is embedded in a `https://app.diagrams.net/#create=...` URL
4. The URL is opened in the default browser
This uses only Node.js built-in modules (`zlib`, `child_process`) — no external dependencies.
### URL generation
Run this `node -e` one-liner to read the `.drawio` file and print the URL (replace `DIAGRAM.drawio` with the actual filename):
```bash
URL=$(node -e '
const fs = require("fs");
const zlib = require("zlib");
const xml = fs.readFileSync(process.argv[1], "utf8");
const compressed = zlib.deflateRawSync(encodeURIComponent(xml)).toString("base64");
const payload = encodeURIComponent(JSON.stringify({ type: "xml", compressed: true, data: compressed }));
console.log("https://app.diagrams.net/?grid=0&pv=0&border=10&edit=_blank#create=" + payload);
' "DIAGRAM.drawio")
```
The URL format matches the MCP Tool Server. Node.js's `zlib.deflateRawSync` and `pako.deflateRaw` both implement RFC 1951 and produce identical output, so URLs from either source are interchangeable.
### Opening the URL
| Environment | Command |
|-------------|---------|
| macOS | `open "$URL"` |
| Linux (native) | `xdg-open "$URL"` |
| WSL2 | Write a temp `.url` file, open via `cmd.exe` (see below) |
| Windows (native) | Write a temp `.url` file, open via `start` (see below) |
**Why the `.url` workaround on Windows/WSL2?** `cmd.exe`'s `start` command treats `&` as a command separator and strips everything after `#` in URLs. The diagram payload lives in the `#create=...` fragment, so passing the URL directly causes it to be silently lost. A `.url` shortcut file preserves the URL intact.
**macOS / Linux example:**
```bash
open "$URL" # macOS
xdg-open "$URL" # Linux
```
**WSL2 example:**
```bash
TMPFILE=$(mktemp --suffix=.url)
printf '[InternetShortcut]\r\nURL=%s\r\n' "$URL" > "$TMPFILE"
cmd.exe /c start "" "$(wslpath -w "$TMPFILE")"
```
**Windows (native) example:**
Do **not** build the `.url` file with `echo URL=%URL%`. The generated URL contains `&` characters (`?grid=0&pv=0&...`) that `cmd.exe` treats as command separators, so the shortcut is written truncated and the diagram payload is lost — the exact failure the `.url` file is meant to prevent. Let Node write the file directly (it already holds the URL string) and open only the resulting path, which never contains `&`:
```bash
TMPFILE=$(node -e '
const fs = require("fs");
const os = require("os");
const path = require("path");
const p = path.join(os.tmpdir(), "drawio.url");
fs.writeFileSync(p, "[InternetShortcut]\r\nURL=" + process.argv[1] + "\r\n");
process.stdout.write(p);
' "$URL")
cmd.exe /c start "" "$TMPFILE"
```
### After opening
Print the URL so the user can copy or share it, and confirm the local file path:
```
Opened in browser: <URL>
Local file: DIAGRAM.drawio
```
The `.drawio` file stays on disk so the user can re-edit it later, attach it elsewhere, or export it to an image format on demand.
### URL length
The URL embeds the full compressed diagram in its hash fragment. Very large diagrams may hit browser URL length limits (typically ~32K2MB depending on the browser). For complex diagrams that exceed the limit, fall back to writing the `.drawio` file and opening it locally.
## draw.io CLI
The draw.io desktop app includes a command-line interface used for **converting Mermaid** to `.drawio`, applying **ELK layouts** (`--layout`), and **exporting** to PNG/SVG/PDF. All three require the desktop app to be installed.
### Locating the CLI
First, detect the environment, then locate the CLI accordingly:
#### WSL2 (Windows Subsystem for Linux)
WSL2 is detected when `/proc/version` contains `microsoft` or `WSL`:
```bash
grep -qi microsoft /proc/version 2>/dev/null && echo "WSL2"
```
On WSL2, use the Windows draw.io Desktop executable via `/mnt/c/...`:
```bash
DRAWIO_CMD="/mnt/c/Program Files/draw.io/draw.io.exe"
```
Double-quote the path so the space in `Program Files` is treated as part of the path. Do **not** wrap it in backticks — in bash, backticks are command substitution, which would try to *execute* the binary at locate-time instead of storing its path.
If draw.io is installed in a non-default location, check common alternatives:
```bash
# Default install path
"/mnt/c/Program Files/draw.io/draw.io.exe"
# Per-user install (if the above does not exist)
"/mnt/c/Users/$WIN_USER/AppData/Local/Programs/draw.io/draw.io.exe"
```
#### macOS
```bash
/Applications/draw.io.app/Contents/MacOS/draw.io
```
#### Linux (native)
```bash
drawio # typically on PATH via snap/apt/flatpak
```
#### Windows (native, non-WSL2)
```
"C:\Program Files\draw.io\draw.io.exe"
```
Use `which drawio` (or `where draw.io` on Windows) to check if it's on PATH before falling back to the platform-specific path.
### Convert / layout / export commands
**Convert Mermaid to `.drawio`:**
```bash
drawio -x -f xml -o diagram.drawio diagram.mmd
```
**Apply an ELK layout to XML** (see [ELK layout for XML](#elk-layout-for-xml)):
```bash
drawio -x -f xml --layout verticalFlow -o diagram.drawio diagram.drawio
```
**Export to an image format:**
```bash
drawio -x -f <format> -e -b 10 -o "<output>" "<input.drawio>"
```
**WSL2 export example:**
```bash
"/mnt/c/Program Files/draw.io/draw.io.exe" -x -f png -e -b 10 -o "diagram.drawio.png" "diagram.drawio"
```
Key flags:
- `-x` / `--export`: export mode (also used for Mermaid conversion and layout passes)
- `-f` / `--format`: output format (`xml`, png, svg, pdf, jpg) — use `xml` to produce a `.drawio` from Mermaid or a layout pass
- `--layout`: run a layout before writing the output — an ELK preset name, the `libavoid` edge-routing pass, or a custom-layout JSON array
- `--mermaid-image 1`: convert Mermaid to a single static SVG image cell (the Mermaid source stays on the cell for re-editing) instead of an editable diagram — only when the user explicitly asks for a non-editable image cell
- `-e` / `--embed-diagram`: embed diagram XML in the output (PNG, SVG, PDF only)
- `-o` / `--output`: output file path
- `-b` / `--border`: border width around diagram (default: 0)
- `-t` / `--transparent`: transparent background (PNG only)
- `-s` / `--scale`: scale the diagram size
- `--width` / `--height`: fit into specified dimensions (preserves aspect ratio)
- `-a` / `--all-pages`: export all pages (PDF only)
- `-p` / `--page-index`: select a specific page (1-based)
### Opening the result
| Environment | Command |
|-------------|---------|
| macOS | `open <file>` |
| Linux (native) | `xdg-open <file>` |
| WSL2 | `cmd.exe /c start "" "$(wslpath -w <file>)"` |
| Windows | `start <file>` |
**WSL2 notes:**
- `wslpath -w <file>` converts a WSL2 path (e.g. `/home/user/diagram.drawio`) to a Windows path (e.g. `C:\Users\...`). This is required because `cmd.exe` cannot resolve `/mnt/c/...` style paths.
- The empty string `""` after `start` is required to prevent `start` from interpreting the filename as a window title.
**WSL2 example:**
```bash
cmd.exe /c start "" "$(wslpath -w diagram.drawio)"
```
## File naming
- Use a descriptive filename based on the diagram content (e.g., `login-flow`, `database-schema`)
- Use lowercase with hyphens for multi-word names
- When authoring Mermaid, write it to a matching `.mmd` file, convert to `.drawio`, then delete the `.mmd` — the `.drawio` is the artifact
- For export, use double extensions: `name.drawio.png`, `name.drawio.svg`, `name.drawio.pdf` — this signals the file contains embedded diagram XML
- After a successful export, delete the intermediate `.drawio` file — the exported file contains the full diagram
- For `url` mode, keep the `.drawio` file (no double extension) — the URL is a view/edit handle and the local file is the persistent copy
## XML format
A `.drawio` file is native mxGraphModel XML. When authoring as XML, generate it directly; Mermaid is converted to this same format by the CLI (`-f xml`), so both authoring routes end up as a native `.drawio`.
### Basic structure
Every diagram must have this structure:
```xml
<mxGraphModel adaptiveColors="auto">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<!-- Diagram cells go here with parent="1" -->
</root>
</mxGraphModel>
```
- Cell `id="0"` is the root layer
- Cell `id="1"` is the default parent layer
- All diagram elements use `parent="1"` unless using multiple layers
(The example above uses an XML comment only to point out where cells go — never emit comments in real output; see [XML well-formedness](#critical-xml-well-formedness).)
## XML reference
For the complete draw.io XML reference including common styles, edge routing, containers, layers, tags, metadata, dark mode colors, and XML well-formedness rules, fetch and follow the instructions at:
https://raw.githubusercontent.com/jgraph/drawio-mcp/main/shared/xml-reference.md
## Troubleshooting
| Problem | Cause | Solution |
|---------|-------|----------|
| draw.io CLI not found | Desktop app not installed or not on PATH | Author as XML and deliver a `.drawio` file or `url` (Mermaid conversion, ELK layout, and image export all need the desktop app). Tell the user they can install the draw.io desktop app to enable those |
| Mermaid → PNG export crashes | Direct `.mmd` → PNG with `-e` is broken in current draw.io Desktop (embedded-XML step) | Use the two-step path: convert Mermaid to `.drawio` first (`-f xml`), then export the `.drawio` to PNG — the intermediate file embeds correctly |
| Blank diagram from Mermaid | Misspelled type keyword, or a syntax error (bad node ID, unquoted label) | Check the [Mermaid reference](#mermaid-syntax-reference); the first non-directive line's keyword selects the diagram type |
| Layout does nothing / errors | Unknown preset name, custom JSON not an array, or a desktop build too old for `--layout` / `.mmd` input | Use a preset from [Layout presets](#layout-presets) or a JSON array starting with `[`; on an old desktop build, author as XML with explicit positions and tell the user updating draw.io Desktop enables Mermaid conversion and layouts |
| Export produces empty/corrupt file | Invalid XML (e.g. double hyphens in comments, unescaped special characters) | Validate XML well-formedness before writing; see the XML well-formedness section below |
| Diagram opens but looks blank | Missing root cells `id="0"` and `id="1"` | Ensure the basic mxGraphModel structure is complete |
| Edges not rendering | Edge mxCell is self-closing (no child mxGeometry element) | Every edge must have `<mxGeometry relative="1" as="geometry" />` as a child element |
| File won't open after export | Incorrect file path or missing file association | Print the absolute file path so the user can open it manually |
| Browser opens with empty diagram in `url` mode | `cmd.exe` stripped the `#create=...` fragment | Use the `.url` temp-file workaround on Windows/WSL2 (see [Opening the URL](#opening-the-url)) — never pass the URL directly to `cmd.exe /c start` |
| URL is too long for the browser | Very large diagram exceeds browser URL length limit | Fall back to writing the `.drawio` file and opening it locally |
## CRITICAL: XML well-formedness
- **NEVER include ANY XML comments (`<!-- -->`) in the output.** XML comments are strictly forbidden — they waste tokens, can cause parse errors, and serve no purpose in diagram XML.
- Escape special characters in attribute values: `&amp;`, `&lt;`, `&gt;`, `&quot;`
- Always use unique `id` values for each `mxCell`