Synced 79 commits from EveryInc/compound-engineering-plugin upstream while
preserving fork-specific customizations (Python/FastAPI pivot, Zoominfo-internal
review agents, deploy-wiring operational lessons, custom personas).
## Triage decisions (15 conflicts resolved)
Keep deleted (7) -- fork already removed these in prior cleanups:
- agents/design/{design-implementation-reviewer,design-iterator,figma-design-sync}
(no fork successor; backend-Python focus doesn't need UI/Figma agents)
- agents/docs/ankane-readme-writer (replaced by python-package-readme-writer)
- agents/review/{data-migration-expert,performance-oracle,security-sentinel}
(replaced by *-reviewer naming convention: data-migrations-reviewer,
performance-reviewer, security-reviewer)
Keep local (1):
- agents/workflow/lint.md (Python tooling: ruff/mypy/djlint/bandit; upstream
deleted the file). Fixed pre-existing duplicate "2." numbering bug.
Restore from upstream (1):
- agents/review/data-integrity-guardian.md (kept for GDPR/CCPA privacy
compliance angle not covered by data-migrations-reviewer)
Merge both (6) -- upstream structural wins layered with fork intent:
- agents/research/best-practices-researcher.md (upstream <examples> removal +
fork's Rails/Ruby -> Python/FastAPI translations)
- skills/ce-brainstorm/SKILL.md (universal-brainstorming routing + Slack
context + non-obvious angles + fork's Deploy wiring flag)
- skills/ce-plan/SKILL.md (universal-planning routing + planning-bootstrap +
fork's two Deploy wiring check bullets)
- skills/ce-review/SKILL.md (Run ID, model tiering haiku->sonnet, compact-JSON
artifact contract, file-type awareness, cli-readiness-reviewer + fork's
zip-agent-validator, design-conformance-reviewer, Stage 6 Zip Agent
Validation)
- skills/ce-review/references/persona-catalog.md (cli-readiness row + adversarial
refinement + fork's Language & Framework Conditional layer; 22 personas total)
- skills/ce-work/SKILL.md (Parallel Safety Check, parallel-subagent constraints,
Phase 3-4 compression + fork's deploy-values self-review row, with duplicate
checklist bullet collapsed to single occurrence)
## Auto-applied (no triage needed)
- 225 remote-only files: accepted as-is (new docs, brainstorms, plans,
upstream skills, tests, scripts)
- 70 local-only files: 46 preserved as-is (kieran-python, tiangolo-fastapi,
zip-agent-validator, design-conformance-reviewer, essay/proof commands,
excalidraw-png-export, etc.); 24 stayed deleted (dhh-rails-style,
andrew-kane-gem-writer, dspy-ruby Ruby skills no longer needed)
## README updated
- Removed Design section (3 deleted agents)
- Removed deleted Review entries (data-migration-expert, dhh-rails-reviewer,
kieran-rails-reviewer, performance-oracle, security-sentinel)
- Added new Review entries: design-conformance-reviewer, previous-comments-reviewer,
tiangolo-fastapi-reviewer, zip-agent-validator
- Workflow: added lint
- Docs: replaced ankane-readme-writer with python-package-readme-writer
## Known issues (not introduced by merge decisions)
- 9 detect-project-type.sh tests fail on macOS bash 3.2 (script uses
`declare -A` which requires bash 4+). Upstream regression in commit 070092d
(#568). Resolution: install bash 4+ via `brew install bash` locally;
upstream fix tracked separately.
- 2 review-skill-contract tests reference deleted agents (dhh-rails-reviewer,
data-migration-expert). Pre-existing fork inconsistency, not new.
bun run release:validate: passes (46 agents, 51 skills, 0 MCP servers)
156 lines
6.9 KiB
Markdown
156 lines
6.9 KiB
Markdown
---
|
|
name: excalidraw-png-export
|
|
description: "This skill should be used when creating diagrams, architecture visuals, or flowcharts and exporting them as PNG files. It uses the Excalidraw MCP to render hand-drawn style diagrams locally and Playwright to export them to PNG without sending data to any remote server. Triggers on requests like 'create a diagram', 'make an architecture diagram', 'draw a flowchart and export as PNG', or any request that needs a visual diagram delivered as an image file."
|
|
---
|
|
|
|
# Excalidraw PNG Export
|
|
|
|
Create hand-drawn style diagrams with the Excalidraw MCP and export them locally to PNG files. All rendering happens on the local machine. Diagram data never leaves the user's computer.
|
|
|
|
## Prerequisites
|
|
|
|
### First-Time Setup
|
|
|
|
Run the setup script once per machine to install Playwright and Chromium headless:
|
|
|
|
```bash
|
|
bash <skill-path>/scripts/setup.sh
|
|
```
|
|
|
|
This creates a `.export-runtime` directory inside `scripts/` with the Node.js dependencies. The setup is idempotent and skips installation if already present.
|
|
|
|
### Required MCP
|
|
|
|
The Excalidraw MCP server must be configured. Verify availability by checking for `mcp__excalidraw__create_view` and `mcp__excalidraw__read_checkpoint` tools.
|
|
|
|
## File Location Convention
|
|
|
|
Save diagram source files alongside their PNG exports in the project's image directory. This enables re-exporting diagrams when content or styling changes.
|
|
|
|
**Standard pattern:**
|
|
```
|
|
docs/images/my-diagram.excalidraw # source (commit this)
|
|
docs/images/my-diagram.png # rendered output (commit this)
|
|
```
|
|
|
|
**When updating an existing diagram**, look for a `.excalidraw` file next to the PNG. If one exists, edit it and re-export rather than rebuilding from scratch.
|
|
|
|
**Temporary files** (raw checkpoint JSON) go in `/tmp/excalidraw-export/` and are discarded after conversion.
|
|
|
|
## Workflow
|
|
|
|
### Step 1: Design the Diagram Elements
|
|
|
|
Translate the user's request into Excalidraw element JSON. Load [excalidraw-element-format.md](./references/excalidraw-element-format.md) for the full element specification, color palette, and sizing guidelines.
|
|
|
|
Key design decisions:
|
|
- Choose appropriate colors from the palette to distinguish different components
|
|
- Use `label` on shapes instead of separate text elements
|
|
- Use `roundness: { type: 3 }` for rounded corners on rectangles
|
|
- Include `cameraUpdate` as the first element to frame the view (MCP rendering only)
|
|
- Use arrow bindings (`startBinding`/`endBinding`) to connect shapes
|
|
|
|
### Step 2: Render with Excalidraw MCP
|
|
|
|
Call `mcp__excalidraw__create_view` with the element JSON array. This renders an interactive preview in the Claude Code UI.
|
|
|
|
```
|
|
mcp__excalidraw__create_view({ elements: "<JSON array string>" })
|
|
```
|
|
|
|
The response includes a `checkpointId` for retrieving the rendered state.
|
|
|
|
### Step 3: Extract the Checkpoint Data
|
|
|
|
Call `mcp__excalidraw__read_checkpoint` with the checkpoint ID to get the full element JSON back.
|
|
|
|
```
|
|
mcp__excalidraw__read_checkpoint({ id: "<checkpointId>" })
|
|
```
|
|
|
|
### Step 4: Convert Checkpoint to .excalidraw File
|
|
|
|
Use the `convert.mjs` script to transform raw MCP checkpoint JSON into a valid `.excalidraw` file. This handles all the tedious parts automatically:
|
|
|
|
- Filters out pseudo-elements (`cameraUpdate`, `delete`, `restoreCheckpoint`)
|
|
- Adds required Excalidraw defaults (`seed`, `version`, `fontFamily`, etc.)
|
|
- Expands `label` properties on shapes/arrows into proper bound text elements
|
|
|
|
```bash
|
|
# Save checkpoint JSON to a temp file, then convert to the project's image directory:
|
|
node <skill-path>/scripts/convert.mjs /tmp/excalidraw-export/raw.json docs/images/my-diagram.excalidraw
|
|
```
|
|
|
|
The input JSON should be the raw checkpoint data from `mcp__excalidraw__read_checkpoint` (the `{"elements": [...]}` object). The output `.excalidraw` file goes in the project's image directory (see File Location Convention above).
|
|
|
|
**For batch exports**: Write each checkpoint to a separate raw JSON file, then convert each one:
|
|
```bash
|
|
node <skill-path>/scripts/convert.mjs raw1.json diagram1.excalidraw
|
|
node <skill-path>/scripts/convert.mjs raw2.json diagram2.excalidraw
|
|
```
|
|
|
|
**Manual alternative**: If you need to write the `.excalidraw` file by hand (e.g., without the convert script), each element needs these defaults:
|
|
|
|
```
|
|
angle: 0, roughness: 1, opacity: 100, groupIds: [], seed: <unique int>,
|
|
version: 1, versionNonce: <unique int>, isDeleted: false,
|
|
boundElements: null, link: null, locked: false
|
|
```
|
|
|
|
Text elements also need: `fontFamily: 1, textAlign: "left", verticalAlign: "top", baseline: 14, containerId: null, originalText: "<same as text>"`
|
|
|
|
Bound text (labels on shapes/arrows) needs: `containerId: "<parent-id>"`, `textAlign: "center"`, `verticalAlign: "middle"`, and the parent needs `boundElements: [{"id": "<text-id>", "type": "text"}]`.
|
|
|
|
### Step 5: Export to PNG
|
|
|
|
Run the export script. Determine the runtime path relative to this skill's scripts directory:
|
|
|
|
```bash
|
|
cd <skill-path>/scripts/.export-runtime && node <skill-path>/scripts/export_png.mjs docs/images/my-diagram.excalidraw docs/images/my-diagram.png
|
|
```
|
|
|
|
The script:
|
|
1. Starts a local HTTP server serving the `.excalidraw` file and an HTML page
|
|
2. Launches headless Chromium via Playwright
|
|
3. The HTML page loads the Excalidraw library from esm.sh (library code only, not user data)
|
|
4. Calls `exportToBlob` on the local diagram data
|
|
5. Extracts the base64 PNG and writes it to disk
|
|
6. Cleans up temp files and exits
|
|
|
|
The script prints the output path on success. Verify the result with `file <output.png>`.
|
|
|
|
### Step 5.5: Validate and Iterate
|
|
|
|
Run the validation script on the `.excalidraw` file to catch spatial issues:
|
|
|
|
```bash
|
|
node <skill-path>/scripts/validate.mjs docs/images/my-diagram.excalidraw
|
|
```
|
|
|
|
Then read the exported PNG back using the Read tool to visually inspect:
|
|
|
|
1. All label text fits within its container (no overflow/clipping)
|
|
2. No arrows cross over text labels
|
|
3. Spacing between elements is consistent
|
|
4. Legend and titles are properly positioned
|
|
|
|
If the validation script or visual inspection reveals issues:
|
|
1. Identify the specific elements that need adjustment
|
|
2. Edit the `.excalidraw` file (adjust coordinates, box sizes, or arrow waypoints)
|
|
3. Re-run the export script (Step 5)
|
|
4. Re-validate
|
|
|
|
### Step 6: Deliver the Result
|
|
|
|
Read the PNG file to display it to the user. Provide the file path so the user can access it directly.
|
|
|
|
## Troubleshooting
|
|
|
|
**Setup fails**: Verify Node.js v18+ is installed (`node --version`). Ensure npm has network access for the initial Playwright/Chromium download.
|
|
|
|
**Export times out**: The HTML page has a 30-second timeout. If it fails, check browser console output in the script's error messages. Common cause: esm.sh CDN is temporarily slow on first load.
|
|
|
|
**Blank PNG**: Ensure elements include all required properties (see Step 4 defaults). Missing `seed`, `version`, or `fontFamily` on text elements can cause silent render failures.
|
|
|
|
**"READY" never fires**: The `exportToBlob` call requires valid elements. Filter out `cameraUpdate` and other pseudo-elements before writing the `.excalidraw` file.
|