# The Claude Code plugin

> Page: https://docs.plotwork.dev/agents/claude-code-plugin. Index of every page: https://docs.plotwork.dev/llms.txt

The Plotwork plugin for Claude Code joins the MCP server and the command line, so a diagram you ask for ends up as an SVG in your docs with no step of your own. It is for anyone who uses Claude Code in a repository with documentation.

## TL;DR

| Question | Answer |
|---|---|
| What does it add? | The local MCP server, a hook that draws diagrams with the command line every time Claude saves one, a gallery on localhost that reloads, and three skills that tell Claude how to use them together. |
| What if Claude starts to write Mermaid? | The hook refuses a new Mermaid, PlantUML, Graphviz, or D2 block in a documentation file and tells Claude which Plotwork tools to use instead. `PLOTWORK_MERMAID=warn` or `allow` relaxes it. |
| How do I install it? | `/plugin marketplace add plotwork-official/plotwork-claude-plugin`, then `/plugin install plotwork@plotwork`. |
| What happens when Claude saves a `.diagram` file? | The hook runs `plotwork render` and writes the SVG beside it, with the source inside. |
| What happens when Claude saves a Markdown page with a `diagram` fence? | The hook runs `plotwork sync`: a light and a dark SVG land in `assets/diagrams/` beside the page, and the picture block is written under the fence. |
| What if the diagram has a mistake? | Nothing is written. Claude gets each mistake with its line, column, and hint, fixes it, and saves again. |
| How do I see the pictures? | Ask Claude to preview them, or run `/plotwork:preview`. The gallery is on `http://127.0.0.1:3900` and reloads within a second of a change. |
| Does it need an account or a key? | No. The MCP server, the command line, and the gallery all run on your machine. |
| Does it use the network? | `npx` downloads the MCP server and the command line from npm the first time. After that, nothing is sent by default. |

## How the pieces fit

The MCP tools write and check the source. The command line draws the pictures on disk. The hook runs the command line the moment Claude saves a file, so the SVG never passes through the model and the picture is the one CI draws.

**Diagram source**

```diagram
sequence "Plugin save loop" desc="Claude writes the source with the MCP tools, saves it, and the hook draws the SVG with the command line."

actor you    person   "You"
actor claude agent    "Claude Code"
actor mcp    service  "Plotwork MCP" sub="draw_diagram"
actor hook   function "Plugin hook"  sub="After each save"
actor cli    service  "Command line" sub="render or sync"

you    -> claude : "Add a diagram of checkout to the docs"
claude -> mcp    : "Check the source"
mcp    --> claude : "Valid, with an outline"
claude -> hook   : "Saves the page or .diagram file"
hook   -> cli    : "Draw it"
alt "the diagram is valid" {
  cli  --> hook  : "SVGs written"
  hook --> claude : "Files drawn"
} else "it has a mistake" {
  cli  --> hook  : "Line, column, hint"
  hook --> claude : "Blocked: fix and save again"
}
claude --> you   : "Diagram is in the docs"
```

*Picture: Plugin save loop: 5 participants. Claude writes the source with the MCP tools, saves it, and the hook draws the SVG with the command line.*

**Text description**

**Participants:**

- You, person
- Claude Code, agent
- Plotwork MCP (draw_diagram), service
- Plugin hook (After each save), function
- Command line (render or sync), service

**Steps:**

- 1. You to Claude Code: Add a diagram of checkout to the docs
- 2. Claude Code to Plotwork MCP: Check the source
- 3. Plotwork MCP to Claude Code (dashed): Valid, with an outline
- 4. Claude Code to Plugin hook: Saves the page or .diagram file
- 5. Plugin hook to Command line: Draw it
- alt: the diagram is valid
  - 6. Command line to Plugin hook (dashed): SVGs written
  - 7. Plugin hook to Claude Code (dashed): Files drawn
- else: it has a mistake
  - 8. Command line to Plugin hook (dashed): Line, column, hint
  - 9. Plugin hook to Claude Code (dashed): Blocked: fix and save again
- 10. Claude Code to You (dashed): Diagram is in the docs

## 1. Install the plugin

Inside Claude Code:

```text
/plugin marketplace add plotwork-official/plotwork-claude-plugin
/plugin install plotwork@plotwork
```

Or name the marketplace in the install itself:

```text
/plugin install plotwork --marketplace plotwork-official/plotwork-claude-plugin
```

The repository [plotwork-official/plotwork-claude-plugin](https://github.com/plotwork-official/plotwork-claude-plugin) holds the plugin and its marketplace, and is updated with each change to the plugin. To update an installed copy, run `/plugin marketplace update plotwork`.

Restart Claude Code when it asks. Run `/mcp` to confirm that the `plotwork` server is connected. The plugin needs Node 22 or newer.

If you already added the server with `claude mcp add plotwork`, remove that one with `claude mcp remove plotwork` so Claude sees one set of tools.

## 2. Ask for a diagram

Ask in plain words, and say where it goes:

| You say | What Claude does |
|---|---|
| "Add a diagram of the checkout flow to `docs/architecture.md`." | Writes a `diagram` fence into the page. The hook syncs it. |
| "Draw our Terraform in `infra/` as a diagram for the docs site." | Calls `import_source`, saves `docs/diagrams/infra.diagram`. The hook writes `infra.svg`. |
| "Illustrate the README." | Calls `plan_document_diagrams`, adds a fence for each section that needs one, and saves. |
| "Move the Mermaid diagrams in `docs/` to Plotwork." | Calls `sync_markdown` with `convertMermaid` for each page. |
| "Show me the diagrams." | Starts the gallery and gives you its address. |

Claude picks these up from the skills without being told their names. You can also run one yourself: `/plotwork:draw`, `/plotwork:document`, or `/plotwork:preview`.

## 3. Where the pictures go

| What Claude saved | What the hook writes | How the docs show it |
|---|---|---|
| A fence in `docs/guide.md` | `docs/assets/diagrams/<id>.svg` and `<id>.dark.svg`, and the picture block under the fence | The picture block is a `<picture>` element that follows the reader's light or dark setting |
| `docs/diagrams/checkout.diagram` | `docs/diagrams/checkout.svg`, with the source embedded | Link it from any page with a Markdown image whose path is `diagrams/checkout.svg`, relative to the page |

Commit the SVGs with the page. Never edit the picture block by hand; the next sync rewrites it. The [Markdown and GitHub](https://docs.plotwork.dev/markdown-and-github.md) guide explains the picture block.

The command line reads your [repository settings](https://docs.plotwork.dev/repository-settings.md) on every run, so header defaults in `plotwork.config.json` apply to the hook's pictures. At the start of a session the plugin tells Claude the file is there, so the MCP tools use it too.

## 4. Preview on localhost

The gallery shows every SVG under the project, grouped by folder, with each light picture beside its dark one. It skips `node_modules`, `.git`, and build output.

| Setting | Default | Change it |
|---|---|---|
| Folder | The project root | Ask for one folder, such as "preview `docs`" |
| Port | 3900, or the next free one of the ten after it | Ask for a port |
| Address | 127.0.0.1 only | Not changeable; it is never reachable from another machine |

Pictures are shown in `<img>` elements, where a script inside an SVG never runs, and the server answers only for `.svg` files.

## 5. Mermaid and other diagram languages

Claude knows Mermaid well, so it reaches for it by habit. The plugin steers it to Plotwork at three points, and none of them repeats on every turn.

| When | What the plugin does |
|---|---|
| The session starts | One sentence in the session note: draw diagrams with the Plotwork tools, never Mermaid, PlantUML, Graphviz, or D2. |
| Your prompt asks for a diagram | Two sentences of guidance, only when the prompt names a diagram as a whole word: diagram, flowchart, flow chart, sequence diagram, architecture diagram, ERD, entity relationship, Mermaid, mind map, Gantt, state machine, C4, swimlane, or org chart. "Diagrammatic" does not count. |
| Claude is about to save a new block | The write is refused before it happens, with what to do instead. |

### What is refused

A write is refused when it adds a block in another diagram language to a documentation file:

| Part | What counts |
|---|---|
| Languages | A fence of `mermaid`, `plantuml`, `puml`, `dot`, `graphviz`, or `d2`, with backticks or tildes; a `<div class="mermaid">` or `<pre class="mermaid">` element; a Sphinx `.. mermaid::`, `.. graphviz::`, or `.. uml::` directive. |
| Files | `.md`, `.mdx`, `.markdown`, `.rst`, `.txt`, a markdown cell of an `.ipynb` notebook, and a README or CHANGELOG with no extension. Code and data files are never read, so a test that holds Mermaid in a string is left alone. |
| Folders left alone | `node_modules`, `.git`, build output, `vendor`, and test fixtures (`fixtures`, `__fixtures__`, `__tests__`, `testdata`, `__snapshots__`). |
| Only new blocks | An edit whose old text already held the block goes through, and so does a rewrite of a page that keeps the blocks it had. Working near an existing Mermaid diagram is never blocked. |

Claude reads this reason, and in practice follows it in the same turn:

```text
This page is drawn with Plotwork, so write a ```diagram fence in Plotwork's language instead of mermaid. Call mcp__plugin_plotwork_plotwork__get_diagram_syntax once if you have not read the language, check the source with mcp__plugin_plotwork_plotwork__draw_diagram (svg "never"), and the plugin syncs the fence into a picture when you save. To keep this Mermaid, call mcp__plugin_plotwork_plotwork__convert_mermaid with it and write the Plotwork source it returns; for a whole page of Mermaid, call mcp__plugin_plotwork_plotwork__sync_markdown with convertMermaid true. If the person asked for mermaid by name, tell them the Plotwork plugin refused it and that PLOTWORK_MERMAID=allow lets it through.
```

### When you want Mermaid

| `PLOTWORK_MERMAID` | Effect |
|---|---|
| `convert`, or unset | The default. A new block is refused with the reason above. |
| `warn` | The write goes through, and Claude gets the same reason as a note. |
| `allow` | The write goes through with nothing said, and the session and prompt notes leave Mermaid out. |

To set it for one repository, put it in the `env` of the repository's `.claude/settings.json`, which Claude Code passes to the hook:

```json
{
  "env": {
    "PLOTWORK_MERMAID": "warn"
  }
}
```

It is not a field of `plotwork.config.json`: every released command line, Action, and MCP server checks that file strictly, and would refuse a field it does not know.

### Without the plugin

If you added the MCP server with `claude mcp add` and do not want the plugin, this hook in your `.claude/settings.json` refuses a new Mermaid fence in a Markdown file in the same way. It is plain Node with nothing to install. The plugin does more: it also covers PlantUML, Graphviz, D2, notebooks, and fixtures, adds the prompt and session notes, and draws the fences on save, so prefer the plugin when you can install it.

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "node -e \"let s='';process.stdin.on('data',c=>s+=c).on('end',()=>{const fs=require('fs'),e=JSON.parse(s),i=e.tool_input||{},f=String(i.file_path||'');if(!['.md','.mdx','.markdown'].some(x=>f.toLowerCase().endsWith(x)))return;const n=t=>(String(t||'').match(/^ {0,3}(\\x60{3,}|~{3,})[ \\t]*mermaid\\b/gim)||[]).length;const old=e.tool_name==='Write'&&fs.existsSync(f)?fs.readFileSync(f,'utf8'):'';const edits=i.edits||[{old_string:i.old_string??old,new_string:i.new_string??i.content}];if(edits.some(x=>n(x.new_string)>n(x.old_string)))console.log(JSON.stringify({hookSpecificOutput:{hookEventName:'PreToolUse',permissionDecision:'deny',permissionDecisionReason:'Draw this with Plotwork instead of Mermaid: write a diagram fence in the Plotwork language and check it with the draw_diagram tool, or call convert_mermaid on this Mermaid and use the source it returns. For a whole page of Mermaid, call sync_markdown with convertMermaid true.'}}))})\"",
            "timeout": 5
          }
        ]
      }
    ]
  }
}
```

## 6. Settings

| Variable | Effect |
|---|---|
| `PLOTWORK_HOOKS=off` | Turns the hook off, including the Mermaid guard. The skills then run the command line themselves. |
| `PLOTWORK_MERMAID` | `convert` (the default), `warn`, or `allow`. See [When you want Mermaid](#when-you-want-mermaid). |
| `PLOTWORK_CLI` | The command the hook runs instead of the default, such as `yarn plotwork`. It is split on spaces. |
| `PLOTWORK_PUBLISH=library` | Off unless set. After a drawing that worked, the hook also saves the file's diagrams to an organisation's private library and gives the agent the link. See [Save to your organisation's library](#save-to-your-organisations-library). |
| `PLOTWORK_API_KEY`, `PLOTWORK_ORG` | The key the library save uses, and the organisation it saves to. Without `PLOTWORK_ORG`, the hook uses `brand.organization` from `plotwork.config.json`. |

Without `PLOTWORK_CLI`, the hook runs the `plotwork` your project installed in `node_modules`, and otherwise `npx -y @buun_group/plotwork@0.1.0`, the release this plugin pins. Pin the same release in CI, as [Keep diagrams in sync in CI](https://docs.plotwork.dev/diagrams-in-ci.md) shows, so the check draws what the hook drew.

### Save to your organisation's library

Set `PLOTWORK_PUBLISH=library`, `PLOTWORK_API_KEY` and `PLOTWORK_ORG` in the environment Claude Code starts with, or in the `env` of your Claude Code settings. Each time the hook draws a `.diagram` file or syncs a page, it then runs `plotwork publish <file> --org <org>` and adds the link to the note the agent reads, so the agent can hand it to you. Only members of the organisation can open it.

| Question | Answer |
|---|---|
| Can it publish to a public link? | No. The hook always names the organisation, and does nothing when none is named. Use `plotwork publish` yourself for a public link. |
| What if the save fails? | The note says why, and nothing is blocked: the files are still drawn in the repository. |
| Which command line does it need? | A release that has `publish`. Set `PLOTWORK_CLI` to a newer one if the pinned release is older. |

## Troubleshooting

| What you see | Why | Fix |
|---|---|---|
| Claude says the hook could not run `npx` | No Node on the path, or no network for the first download | Install Node 22, or install the command line in the project with `npm install --save-dev @buun_group/plotwork@0.1.0` |
| The first save takes a few seconds | `npx` is downloading the command line | Later saves use the cached copy |
| A picture is stale after you edit by hand | The hook runs only when Claude saves | Run `npx -y @buun_group/plotwork@0.1.0 sync <page>` |
| A Mermaid block you asked for was refused | The guard refuses new Mermaid in documentation by default | Ask Claude to keep it, and set `PLOTWORK_MERMAID=allow` or `warn` in the `env` of `.claude/settings.json` |
| The tools appear twice | The server is added both by the plugin and by `claude mcp add` | `claude mcp remove plotwork` |

## See also

| Doc | Why |
|---|---|
| [Connecting an agent](https://docs.plotwork.dev/mcp/connect.md) | Add the MCP server to other clients, or use the hosted server |
| [Command line overview](https://docs.plotwork.dev/cli/overview.md) | Every command the hook and the skills run |
| [Markdown and GitHub](https://docs.plotwork.dev/markdown-and-github.md) | How a fence and its picture block look in a page |
| [Migrating from Mermaid](https://docs.plotwork.dev/migrating-from-mermaid.md) | What `convert_mermaid` and `sync_markdown` do with existing Mermaid |
| [Keep diagrams in sync in CI](https://docs.plotwork.dev/diagrams-in-ci.md) | Fail a pull request whose pictures are stale |
| [Writing diagrams with an agent](https://docs.plotwork.dev/mcp/agent-loop.md) | The loop the skills follow |
