* docs: deep audit — fix stale config keys, missing commands, and registry drift Cross-checked ~80 high-impact docs pages (getting-started, reference, top-level user-guide, user-guide/features) against the live registries: hermes_cli/commands.py COMMAND_REGISTRY (slash commands) hermes_cli/auth.py PROVIDER_REGISTRY (providers) hermes_cli/config.py DEFAULT_CONFIG (config keys) toolsets.py TOOLSETS (toolsets) tools/registry.py get_all_tool_names() (tools) python -m hermes_cli.main <subcmd> --help (CLI args) reference/ - cli-commands.md: drop duplicate hermes fallback row + duplicate section, add stepfun/lmstudio to --provider enum, expand auth/mcp/curator subcommand lists to match --help output (status/logout/spotify, login, archive/prune/ list-archived). - slash-commands.md: add missing /sessions and /reload-skills entries + correct the cross-platform Notes line. - tools-reference.md: drop bogus '68 tools' headline, drop fictional 'browser-cdp toolset' (these tools live in 'browser' and are runtime-gated), add missing 'kanban' and 'video' toolset sections, fix MCP example to use the real mcp_<server>_<tool> prefix. - toolsets-reference.md: list browser_cdp/browser_dialog inside the 'browser' row, add missing 'kanban' and 'video' toolset rows, drop the stale '38 tools' count for hermes-cli. - profile-commands.md: add missing install/update/info subcommands, document fish completion. - environment-variables.md: dedupe GMI_API_KEY/GMI_BASE_URL rows (kept the one with the correct gmi-serving.com default). - faq.md: Anthropic/Google/OpenAI examples — direct providers exist (not just via OpenRouter), refresh the OpenAI model list. getting-started/ - installation.md: PortableGit (not MinGit) is what the Windows installer fetches; document the 32-bit MinGit fallback. - installation.md / termux.md: installer prefers .[termux-all] then falls back to .[termux]. - nix-setup.md: Python 3.12 (not 3.11), Node.js 22 (not 20); fix invalid 'nix flake update --flake' invocation. - updating.md: 'hermes backup restore --state pre-update' doesn't exist — point at the snapshot/quick-snapshot flow; correct config key 'updates.pre_update_backup' (was 'update.backup'). user-guide/ - configuration.md: api_max_retries default 3 (not 2); display.runtime_footer is the real key (not display.runtime_metadata_footer); checkpoints defaults enabled=false / max_snapshots=20 (not true / 50). - configuring-models.md: 'hermes model list' / 'hermes model set ...' don't exist — hermes model is interactive only. - tui.md: busy_indicator -> tui_status_indicator with values kaomoji|emoji|unicode|ascii (not kawaii|minimal|dots|wings|none). - security.md: SSH backend keys (TERMINAL_SSH_HOST/USER/KEY) live in .env, not config.yaml. - windows-wsl-quickstart.md: there is no 'hermes api' subcommand — the OpenAI-compatible API server runs inside hermes gateway. user-guide/features/ - computer-use.md: approvals.mode (not security.approval_level); fix broken ./browser-use.md link to ./browser.md. - fallback-providers.md: top-level fallback_providers (not model.fallback_providers); the picker is subcommand-based, not modal. - api-server.md: API_SERVER_* are env vars — write to per-profile .env, not 'hermes config set' which targets YAML. - web-search.md: drop web_crawl as a registered tool (it isn't); deep-crawl modes are exposed through web_extract. - kanban.md: failure_limit default is 2, not '~5'. - plugins.md: drop hard-coded '33 providers' count. - honcho.md: fix unclosed quote in echo HONCHO_API_KEY snippet; document that 'hermes honcho' subcommand is gated on memory.provider=honcho; reconcile subcommand list with actual --help output. - memory-providers.md: legacy 'hermes honcho setup' redirect documented. Verified via 'npm run build' — site builds cleanly; broken-link count went from 149 to 146 (no regressions, fixed a few in passing). * docs: round 2 audit fixes + regenerate skill catalogs Follow-up to the previous commit on this branch: Round 2 manual fixes: - quickstart.md: KIMI_CODING_API_KEY mentioned alongside KIMI_API_KEY; voice-mode and ACP install commands rewritten — bare 'pip install ...' doesn't work for curl-installed setups (no pip on PATH, not in repo dir); replaced with 'cd ~/.hermes/hermes-agent && uv pip install -e ".[voice]"'. ACP already ships in [all] so the curl install includes it. - cli.md / configuration.md: 'auxiliary.compression.model' shown as 'google/gemini-3-flash-preview' (the doc's own claimed default); actual default is empty (= use main model). Reworded as 'leave empty (default) or pin a cheap model'. - built-in-plugins.md: added the bundled 'kanban/dashboard' plugin row that was missing from the table. Regenerated skill catalogs: - ran website/scripts/generate-skill-docs.py to refresh all 163 per-skill pages and both reference catalogs (skills-catalog.md, optional-skills-catalog.md). This adds the entries that were genuinely missing — productivity/teams-meeting-pipeline (bundled), optional/finance/* (entire category — 7 skills: 3-statement-model, comps-analysis, dcf-model, excel-author, lbo-model, merger-model, pptx-author), creative/hyperframes, creative/kanban-video-orchestrator, devops/watchers, productivity/shop-app, research/searxng-search, apple/macos-computer-use — and rewrites every other per-skill page from the current SKILL.md. Most diffs are tiny (one line of refreshed metadata). Validation: - 'npm run build' succeeded. - Broken-link count moved 146 -> 155 — the +9 are zh-Hans translation shells that lag every newly-added skill page (pre-existing pattern). No regressions on any en/ page.
213 lines
7.7 KiB
Markdown
213 lines
7.7 KiB
Markdown
---
|
|
title: "Excalidraw — Hand-drawn Excalidraw JSON diagrams (arch, flow, seq)"
|
|
sidebar_label: "Excalidraw"
|
|
description: "Hand-drawn Excalidraw JSON diagrams (arch, flow, seq)"
|
|
---
|
|
|
|
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
|
|
|
# Excalidraw
|
|
|
|
Hand-drawn Excalidraw JSON diagrams (arch, flow, seq).
|
|
|
|
## Skill metadata
|
|
|
|
| | |
|
|
|---|---|
|
|
| Source | Bundled (installed by default) |
|
|
| Path | `skills/creative/excalidraw` |
|
|
| Version | `1.0.0` |
|
|
| Author | Hermes Agent |
|
|
| License | MIT |
|
|
| Platforms | linux, macos, windows |
|
|
| Tags | `Excalidraw`, `Diagrams`, `Flowcharts`, `Architecture`, `Visualization`, `JSON` |
|
|
|
|
## Reference: full SKILL.md
|
|
|
|
:::info
|
|
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
|
:::
|
|
|
|
# Excalidraw Diagram Skill
|
|
|
|
Create diagrams by writing standard Excalidraw element JSON and saving as `.excalidraw` files. These files can be drag-and-dropped onto [excalidraw.com](https://excalidraw.com) for viewing and editing. No accounts, no API keys, no rendering libraries -- just JSON.
|
|
|
|
## When to use
|
|
|
|
Generate `.excalidraw` files for architecture diagrams, flowcharts, sequence diagrams, concept maps, and more. Files can be opened at excalidraw.com or uploaded for shareable links.
|
|
|
|
## Workflow
|
|
|
|
1. **Load this skill** (you already did)
|
|
2. **Write the elements JSON** -- an array of Excalidraw element objects
|
|
3. **Save the file** using `write_file` to create a `.excalidraw` file
|
|
4. **Optionally upload** for a shareable link using `scripts/upload.py` via `terminal`
|
|
|
|
### Saving a Diagram
|
|
|
|
Wrap your elements array in the standard `.excalidraw` envelope and save with `write_file`:
|
|
|
|
```json
|
|
{
|
|
"type": "excalidraw",
|
|
"version": 2,
|
|
"source": "hermes-agent",
|
|
"elements": [ ...your elements array here... ],
|
|
"appState": {
|
|
"viewBackgroundColor": "#ffffff"
|
|
}
|
|
}
|
|
```
|
|
|
|
Save to any path, e.g. `~/diagrams/my_diagram.excalidraw`.
|
|
|
|
### Uploading for a Shareable Link
|
|
|
|
Run the upload script (located in this skill's `scripts/` directory) via terminal:
|
|
|
|
```bash
|
|
python skills/diagramming/excalidraw/scripts/upload.py ~/diagrams/my_diagram.excalidraw
|
|
```
|
|
|
|
This uploads to excalidraw.com (no account needed) and prints a shareable URL. Requires the `cryptography` pip package (`pip install cryptography`).
|
|
|
|
---
|
|
|
|
## Element Format Reference
|
|
|
|
### Required Fields (all elements)
|
|
`type`, `id` (unique string), `x`, `y`, `width`, `height`
|
|
|
|
### Defaults (skip these -- they're applied automatically)
|
|
- `strokeColor`: `"#1e1e1e"`
|
|
- `backgroundColor`: `"transparent"`
|
|
- `fillStyle`: `"solid"`
|
|
- `strokeWidth`: `2`
|
|
- `roughness`: `1` (hand-drawn look)
|
|
- `opacity`: `100`
|
|
|
|
Canvas background is white.
|
|
|
|
### Element Types
|
|
|
|
**Rectangle**:
|
|
```json
|
|
{ "type": "rectangle", "id": "r1", "x": 100, "y": 100, "width": 200, "height": 100 }
|
|
```
|
|
- `roundness: { "type": 3 }` for rounded corners
|
|
- `backgroundColor: "#a5d8ff"`, `fillStyle: "solid"` for filled
|
|
|
|
**Ellipse**:
|
|
```json
|
|
{ "type": "ellipse", "id": "e1", "x": 100, "y": 100, "width": 150, "height": 150 }
|
|
```
|
|
|
|
**Diamond**:
|
|
```json
|
|
{ "type": "diamond", "id": "d1", "x": 100, "y": 100, "width": 150, "height": 150 }
|
|
```
|
|
|
|
**Labeled shape (container binding)** -- create a text element bound to the shape:
|
|
|
|
> **WARNING:** Do NOT use `"label": { "text": "..." }` on shapes. This is NOT a valid
|
|
> Excalidraw property and will be silently ignored, producing blank shapes. You MUST
|
|
> use the container binding approach below.
|
|
|
|
The shape needs `boundElements` listing the text, and the text needs `containerId` pointing back:
|
|
```json
|
|
{ "type": "rectangle", "id": "r1", "x": 100, "y": 100, "width": 200, "height": 80,
|
|
"roundness": { "type": 3 }, "backgroundColor": "#a5d8ff", "fillStyle": "solid",
|
|
"boundElements": [{ "id": "t_r1", "type": "text" }] },
|
|
{ "type": "text", "id": "t_r1", "x": 105, "y": 110, "width": 190, "height": 25,
|
|
"text": "Hello", "fontSize": 20, "fontFamily": 1, "strokeColor": "#1e1e1e",
|
|
"textAlign": "center", "verticalAlign": "middle",
|
|
"containerId": "r1", "originalText": "Hello", "autoResize": true }
|
|
```
|
|
- Works on rectangle, ellipse, diamond
|
|
- Text is auto-centered by Excalidraw when `containerId` is set
|
|
- The text `x`/`y`/`width`/`height` are approximate -- Excalidraw recalculates them on load
|
|
- `originalText` should match `text`
|
|
- Always include `fontFamily: 1` (Virgil/hand-drawn font)
|
|
|
|
**Labeled arrow** -- same container binding approach:
|
|
```json
|
|
{ "type": "arrow", "id": "a1", "x": 300, "y": 150, "width": 200, "height": 0,
|
|
"points": [[0,0],[200,0]], "endArrowhead": "arrow",
|
|
"boundElements": [{ "id": "t_a1", "type": "text" }] },
|
|
{ "type": "text", "id": "t_a1", "x": 370, "y": 130, "width": 60, "height": 20,
|
|
"text": "connects", "fontSize": 16, "fontFamily": 1, "strokeColor": "#1e1e1e",
|
|
"textAlign": "center", "verticalAlign": "middle",
|
|
"containerId": "a1", "originalText": "connects", "autoResize": true }
|
|
```
|
|
|
|
**Standalone text** (titles and annotations only -- no container):
|
|
```json
|
|
{ "type": "text", "id": "t1", "x": 150, "y": 138, "text": "Hello", "fontSize": 20,
|
|
"fontFamily": 1, "strokeColor": "#1e1e1e", "originalText": "Hello", "autoResize": true }
|
|
```
|
|
- `x` is the LEFT edge. To center at position `cx`: `x = cx - (text.length * fontSize * 0.5) / 2`
|
|
- Do NOT rely on `textAlign` or `width` for positioning
|
|
|
|
**Arrow**:
|
|
```json
|
|
{ "type": "arrow", "id": "a1", "x": 300, "y": 150, "width": 200, "height": 0,
|
|
"points": [[0,0],[200,0]], "endArrowhead": "arrow" }
|
|
```
|
|
- `points`: `[dx, dy]` offsets from element `x`, `y`
|
|
- `endArrowhead`: `null` | `"arrow"` | `"bar"` | `"dot"` | `"triangle"`
|
|
- `strokeStyle`: `"solid"` (default) | `"dashed"` | `"dotted"`
|
|
|
|
### Arrow Bindings (connect arrows to shapes)
|
|
|
|
```json
|
|
{
|
|
"type": "arrow", "id": "a1", "x": 300, "y": 150, "width": 150, "height": 0,
|
|
"points": [[0,0],[150,0]], "endArrowhead": "arrow",
|
|
"startBinding": { "elementId": "r1", "fixedPoint": [1, 0.5] },
|
|
"endBinding": { "elementId": "r2", "fixedPoint": [0, 0.5] }
|
|
}
|
|
```
|
|
|
|
`fixedPoint` coordinates: `top=[0.5,0]`, `bottom=[0.5,1]`, `left=[0,0.5]`, `right=[1,0.5]`
|
|
|
|
### Drawing Order (z-order)
|
|
- Array order = z-order (first = back, last = front)
|
|
- Emit progressively: background zones → shape → its bound text → its arrows → next shape
|
|
- BAD: all rectangles, then all texts, then all arrows
|
|
- GOOD: bg_zone → shape1 → text_for_shape1 → arrow1 → arrow_label_text → shape2 → text_for_shape2 → ...
|
|
- Always place the bound text element immediately after its container shape
|
|
|
|
### Sizing Guidelines
|
|
|
|
**Font sizes:**
|
|
- Minimum `fontSize`: **16** for body text, labels, descriptions
|
|
- Minimum `fontSize`: **20** for titles and headings
|
|
- Minimum `fontSize`: **14** for secondary annotations only (sparingly)
|
|
- NEVER use `fontSize` below 14
|
|
|
|
**Element sizes:**
|
|
- Minimum shape size: 120x60 for labeled rectangles/ellipses
|
|
- Leave 20-30px gaps between elements minimum
|
|
- Prefer fewer, larger elements over many tiny ones
|
|
|
|
### Color Palette
|
|
|
|
See `references/colors.md` for full color tables. Quick reference:
|
|
|
|
| Use | Fill Color | Hex |
|
|
|-----|-----------|-----|
|
|
| Primary / Input | Light Blue | `#a5d8ff` |
|
|
| Success / Output | Light Green | `#b2f2bb` |
|
|
| Warning / External | Light Orange | `#ffd8a8` |
|
|
| Processing / Special | Light Purple | `#d0bfff` |
|
|
| Error / Critical | Light Red | `#ffc9c9` |
|
|
| Notes / Decisions | Light Yellow | `#fff3bf` |
|
|
| Storage / Data | Light Teal | `#c3fae8` |
|
|
|
|
### Tips
|
|
- Use the color palette consistently across the diagram
|
|
- **Text contrast is CRITICAL** -- never use light gray on white backgrounds. Minimum text color on white: `#757575`
|
|
- Do NOT use emoji in text -- they don't render in Excalidraw's font
|
|
- For dark mode diagrams, see `references/dark-mode.md`
|
|
- For larger examples, see `references/examples.md`
|