Skip to content
Back to skills

Gen Readme Diagram

CSecurity

Add or update an Architecture section in README.md with Mermaid diagrams scaled to app complexity

  • 16 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 25, 2026
developmentrustgobashsqlnodedockerkubernetesawsgcpterraform

Works with

  • claude code
  • cli
  • api

Security analysis

C67/100
  • criticalPipes output to a shell interpreter
  • mediumUses curl or wget to download content
  • criticalDownloads and executes remote scripts — classic supply chain attack
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned September 25, 2026

npx -y skills add sgaunet/claude-plugins --skill gen-readme-diagram --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Gen Readme Diagram?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Gen Readme Diagram
[![Security: C — Skills Directory](https://www.skillsdirectory.com/api/skills/sgaunet-gen-readme-diagram/badge)](https://www.skillsdirectory.com/skills/sgaunet-gen-readme-diagram)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: gen-readme-diagram
description: Add or update an Architecture section in README.md with Mermaid diagrams scaled to app complexity
argument-hint: "[--level=auto|none|context|component|full] [--readme=<path>] [--section=<heading>] [--with-d2] [--no-d2] [--no-mise] [--dry-run] [<hints>]"
user-invocable: true
disable-model-invocation: true
allowed-tools: Read, Write, Edit, Grep, Glob, Bash(git:*), Bash(test:*), Bash(wc:*), Bash(grep:*), Bash(command:*), Bash(mkdir:*), Bash(d2:*), Bash(mise:*), Bash(mmdc:*), Task, AskUserQuestion
---

# Generate README Architecture Diagrams

Add or update an `## Architecture` section in the current project's README, containing Mermaid diagrams sized to the application's actual complexity. Mermaid renders natively on GitHub, GitLab and Forgejo, so the section needs no build step and no committed image. Re-running the skill replaces only its own generated block and never disturbs hand-written prose.

## Why This Skill Exists

**Problem**: READMEs describe *how to run* a project but almost never *what it talks to*. A newcomer cannot tell from the README whether the service owns a database, calls three SaaS APIs, or consumes a queue. Drawing that by hand means picking a tool, learning its syntax, and — for anything image-based — committing a binary that silently drifts from reality. Meanwhile `/gen-diagram` produces excellent d2 + SVG output for design docs, but a README wants something that renders inline, for free, forever.

**Solution**: One invocation that:
- Analyzes the repo it is invoked in and **scores its complexity** on a fixed rubric
- Emits a diagram set matched to that score — from **no diagram at all** for a single-purpose library, up to four views for a multi-service system
- Always includes the global/context view: the app as one box, with every external system and every edge labelled
- Splices into the README between generated markers, so re-running is idempotent and hand-written prose survives

## Content Generation Rules

**CRITICAL**: When generating any content (README sections, Mermaid source, .d2 source, prose, or any other output):
- **NEVER** add Claude Code attribution or co-authorship
- **NEVER** include phrases like "Generated by Claude", "Created with Claude Code", or similar
- **NEVER** add "Co-Authored-By: Claude" in commit messages or documentation
- All generated content should appear as if written by a human developer
- Focus on technical accuracy and clear, readable diagrams

## Process (6 Phases)

### Phase 1: Prerequisites Validation

1. **Validate Git repository:**
   ```bash
   git rev-parse --git-dir
   ```
   - If fails: Exit with error "Not a git repository. Run 'git init' first."

2. **Resolve repository root:**
   ```bash
   git rev-parse --show-toplevel
   ```
   Store as `repoRoot`.

3. **Resolve and verify the README target:**
   - Path is `--readme=<path>` if provided, else `<repoRoot>/README.md`.
   ```bash
   test -f <readmePath>
   ```
   - If missing: Exit with error "No README found at <readmePath>. Create one first, or pass --readme=<path>."

4. **Verify skill assets:**
   - Use Read to confirm `${CLAUDE_PLUGIN_ROOT}/assets/gen-readme-diagram/mermaid-cheatsheet.md` exists.
   - If missing: Exit with error "Cheatsheet not found at ${CLAUDE_PLUGIN_ROOT}/assets/gen-readme-diagram/mermaid-cheatsheet.md. Plugin may be corrupted. Reinstall the software-engineering plugin."

5. **Detect optional tooling** (non-blocking, and **no writes in this phase**):
   ```bash
   command -v d2
   command -v mmdc
   command -v mise
   test -f mise.toml && grep -qE '^[[:space:]]*"?d2"?[[:space:]]*=' mise.toml
   ```
   - Store `d2Installed`, `mmdcInstalled`, `miseAvailable`, `d2Pinned`. None is required;
     Mermaid output never depends on a binary.
   - The d2 pin is only relevant when the d2 companion runs. When it does and
     `miseAvailable && !d2Pinned && !--no-mise`, the pin is added in **Phase 5** and
     disclosed in the Phase 4 preview first — `mise use` edits `mise.toml`, a tracked
     project file, so it belongs behind the confirmation gate.

6. **Check README cleanliness** (non-blocking):
   ```bash
   git status --porcelain -- <readmePath>
   ```
   - Non-empty output: store `readmeDirty = true` (drives a Phase 4 warning so the edit stays trivially revertible).

### Phase 2: Argument Parsing

Parse `$ARGUMENTS`. Tokenize on spaces, then partition into flags and a free-text remainder.

**Supported flags:**
- `--level=<auto|none|context|component|full>` — override the computed complexity tier. Default: `auto`.
- `--readme=<path>` — target README. Default: `<repoRoot>/README.md`.
- `--section=<heading>` — heading text this skill owns. Default: `Architecture`.
- `--with-d2` — also generate a d2 source + SVG companion and link it from the section.
- `--no-d2` — never generate the d2 companion, even at tier `full`.
- `--no-mise` — never touch `mise.toml`; rely on whatever `d2` is already on PATH.
- `--dry-run` — print the preview and the would-be block; write nothing.

**Everything else** is joined back with spaces as `hints` — free text steering the analysis, e.g. `/gen-readme-diagram focus on the ingestion path`.

**Conflict resolution:**
- `--with-d2` and `--no-d2` together: `--no-d2` wins.
- `--level=none` suppresses every diagram regardless of the computed score, and implies `--no-d2`.
- `--no-d2` implies `--no-mise`: with no d2 companion there is nothing to pin.

### Phase 3: Context Gathering & Complexity Scoring

1. **Read the cheatsheet** to ground the model in verified Mermaid syntax and the idiomatic templates:
   ```
   Read: ${CLAUDE_PLUGIN_ROOT}/assets/gen-readme-diagram/mermaid-cheatsheet.md
   ```

2. **Launch 3 parallel Explore agents** to analyze the repository.

   **Agent #1: Boundary & External Systems**
   ```
   Task(
     subagent_type: "Explore",
     description: "External systems and boundary",
     prompt: "
       Map this repository's boundary — who calls it and what it calls out to. Return:
       {
         actors: [human or machine callers, e.g. 'end user', 'operator', 'cron', 'upstream service'],
         inbound: [{kind: 'http'|'grpc'|'cli'|'cron'|'queue-consumer'|'library-api', detail: '...'}],
         datastores: [{name: 'PostgreSQL', purpose: 'orders, customers'}],
         thirdParty: [{name: 'Stripe', protocol: 'REST', purpose: 'charge card'}],
         brokers: [{name: 'Kafka', topics: ['order.created']}],
         objectStores: [{name: 'S3', purpose: 'invoices'}],
         authProviders: [names]
       }

       Detection strategy:
       - Dependency manifests: go.mod, package.json, requirements.txt, pyproject.toml, Cargo.toml, Gemfile, composer.json
       - Client construction: sql.Open, pgxpool, redis.NewClient, kafka.NewWriter, stripe.New, boto3.client, new S3Client
       - Config surface: sample dotenv templates, config structs, and environment lookups naming hosts, URLs or DSNs
       - Inbound surface: route registrations, *.proto services, CLI arg parsers, cron/schedule declarations, queue subscribe calls
       - Do NOT count test doubles, linters, build tools or dev dependencies as external systems.

       Return concise JSON, no prose.
     "
   )
   ```

   **Agent #2: Internal Structure**
   ```
   Task(
     subagent_type: "Explore",
     description: "Internal structure and scale",
     prompt: "
       Describe this repository's internal structure and size. Return:
       {
         language: dominant language,
         shape: 'library' | 'cli' | 'service' | 'multi-service' | 'monorepo' | 'script',
         entryPoints: [{path: 'cmd/api', servesTraffic: true|false}],
         modules: [top-level internal packages or directories that hold real logic],
         layering: short description of how modules depend on each other,
         sourceFileCount: integer (exclude vendor/, node_modules/, testdata/, generated files),
         deployables: integer (how many independently deployable processes)
       }

       Detection strategy:
       - Entry points: cmd/*/main.go, main.go, main.py, __main__.py, src/index.{ts,js}, bin/*, [project.scripts]
       - Modules: internal/, pkg/, src/, app/, lib/ subdirectories — ignore docs/, scripts/, testdata/, examples/
       - Deployables: count app services in docker-compose*.yml, Deployments in k8s/, or traffic-serving cmd/ dirs
       - servesTraffic: true when the entry point starts a server or consumes a queue, false for one-shot CLIs

       Return concise JSON, no prose.
     "
   )
   ```

   **Agent #3: Behaviour & Data**
   ```
   Task(
     subagent_type: "Explore",
     description: "Primary flow and data model",
     prompt: "
       Identify the single most important end-to-end flow and the persistent data model. Return:
       {
         primaryFlow: {
           name: 'e.g. place an order',
           steps: [{from: 'participant', to: 'participant', message: 'what is sent', response: 'what comes back'}],
           branches: [{condition: '...', outcome: '...'}]
         },
         entities: [{name: 'ORDER', fields: [{name, type, key: 'PK'|'FK'|null}]}],
         relations: [{from: 'CUSTOMER', to: 'ORDER', cardinality: 'one-to-many', label: 'places'}],
         infra: {docker: bool, compose: bool, kubernetes: bool, helm: bool, terraform: bool}
       }

       Detection strategy:
       - Primary flow: the most-referenced HTTP handler or command; follow it through service into store
       - Entities: migrations/*.sql, schema.sql, ORM models (gorm/sqlalchemy/prisma/ActiveRecord), sqlc queries
       - Relations: FOREIGN KEY constraints, ORM relationship declarations
       - infra: presence of Dockerfile, docker-compose*.yml, k8s/ or manifests/, helm/ or Chart.yaml, *.tf
       - Return entities: [] and relations: [] if no persistent schema exists. Do not invent one.

       Return concise JSON, no prose.
     "
   )
   ```

   **Why parallel?** The three analyses are independent and complete in roughly the time of the slowest one. Wait for all 3 agents before proceeding.

3. **Score complexity** using the rubric in `## Complexity Rubric` below. Store `score` and the derived `tier`.

4. **Apply `--level`** when it is not `auto`: it replaces `tier` outright. Record that the tier was overridden so Phase 4 can say so.

5. **Honour `hints`**: if the user supplied free text, weight the diagram content toward it (e.g. "focus on the ingestion path" selects the ingestion flow as `primaryFlow` rather than the most-referenced handler).

### Phase 4: Confirmation Preview

Build the preview message:

```
📐 README Architecture Section

README:       <relative path>  (<"new section" | "update in place" | "append to existing section">)
Section:      ## <section>
Complexity:   <tier> (score <N>/17)<" — overridden by --level" if applicable>
Diagrams:     <N>
  • System context   (flowchart LR, <N> nodes)
  • Component view   (flowchart TB, <N> nodes)
  • Primary flow     (sequenceDiagram, <N> participants)
  • Data model       (erDiagram, <N> entities)
Anchor:       <"between existing markers" | "end of ## <heading>" | "before ## Installation" | "end of file">
d2 companion: <"yes → docs/diagrams/architecture.d2 + .svg" | "no">
d2 tooling:   <"mise.toml → pin d2 0.7.1 (new)" | "mise.toml already pins d2" | "PATH d2 <version>" | "n/a — Mermaid only">

Signals detected:
  Actors:       <list>
  Inbound:      <list>
  Externals:    <list, or "none">
  Entry points: <list>
  Modules:      <list>
  Entities:     <count>

<CONDITIONAL WARNINGS>
```

Printing the detected signals is deliberate: a wrong analysis is far cheaper to catch here than in a diff.

**Conditional warnings:**

If `readmeDirty`:
```
⚠️  WARNING: <readme> has uncommitted changes
    Commit or stash them first so this edit is easy to review and revert.
```

If existing markers were found:
```
ℹ️  Replacing the existing generated block (lines <A>-<B>).
    Everything outside the markers is preserved byte-for-byte.
```

If the target section exists but has no markers:
```
⚠️  Section "## <section>" exists without generator markers.
    The diagrams will be appended to the end of that section.
    Existing prose in the section is preserved above them.
```

If `tier = none`:
```
ℹ️  No diagram warranted
    <shape> with <N> external system(s) and <N> module(s) — a box-and-arrow
    diagram would restate the prose. Writing an orientation paragraph only.
    Force one with: --level=context
```

If d2 companion requested but `d2Installed = false`:
```
ℹ️  d2 binary not found — the Mermaid diagrams are unaffected
    Preferred — pins the version for this repo, local dev and CI alike:
      • mise use d2@0.7.1     # adds d2 to mise.toml [tools] and installs it
    Without mise:
      • macOS:  brew install d2
      • Linux:  curl -fsSL https://d2lang.com/install.sh | sh -s --
      • Verify: d2 --version
```

If the d2 companion will run and `miseAvailable && !d2Pinned && !--no-mise`:
```
ℹ️  mise.toml will gain a d2 pin
    Adding:  d2 = "0.7.1"   (under [tools])
    <"mise.toml will be created" | "existing pins are preserved">
    This keeps the committed SVG reproducible across machines and CI.
    Skip with --no-mise.
```

If `mmdcInstalled = false`:
```
ℹ️  mmdc not found — Mermaid blocks get static checks only, not a render test
    Optional: npm i -g @mermaid-js/mermaid-cli
```

**Confirmation logic:**

If `--dry-run`:
```
[DRY RUN MODE - No files will be written]
```
Proceed straight to Phase 6 to print the preview and the would-be block. Do **not** write.

Otherwise:
```
Use AskUserQuestion:
  Question: "Update \"## <section>\" in <readme> with <N> Mermaid diagram(s)?"
  Options:
    - "Yes, write" (proceed to Phase 5)
    - "Show the full block first" (print the complete block, then ask again)
    - "No, cancel" (exit with "Operation cancelled by user")
```

At tier `full` with `d2Installed = true` and neither `--with-d2` nor `--no-d2` given, add a second question:
```
Use AskUserQuestion:
  Question: "Also generate a detailed d2 + SVG companion in docs/diagrams/?"
  Options:
    - "Yes, add the d2 companion" (set withD2 = true)
    - "No, Mermaid only" (set withD2 = false)
```

### Phase 5: Generation (README Splice)

1. **Compose the block content.** Follow the templates and rules in the cheatsheet. Structure:

   ````markdown
   <!-- BEGIN GENERATED: architecture-diagrams -->
   <!-- Regenerate with: /gen-readme-diagram -->

   <1-3 sentences: what the system is, where its boundary sits, what it depends on.>

   ### System Context

   <one sentence naming what the reader should take away>

   ```mermaid
   flowchart LR
     ...
   ```

   [If tier >= component:]
   ### Components

   <one sentence>

   ```mermaid
   flowchart TB
     ...
   ```

   [If tier = full:]
   ### <Primary flow name>

   <one sentence>

   ```mermaid
   sequenceDiagram
     ...
   ```

   [If tier = full AND entities >= 3 with relations:]
   ### Data Model

   <one sentence>

   ```mermaid
   erDiagram
     ...
   ```

   [If withD2:]
   A detailed, printable view lives in [`docs/diagrams/architecture.d2`](docs/diagrams/architecture.d2):

   ![Architecture](docs/diagrams/architecture.svg)

   <!-- END GENERATED: architecture-diagrams -->
   ````

   At tier `none` the block contains only the orientation paragraph and no `###` subheadings.

   Content rules, in addition to the cheatsheet's:
   - The System Context diagram renders the application as **exactly one** node.
   - Never draw a system that the agents did not actually find.
   - Sub-heading level is one below the host section (`###` under an `##`). If `--section` resolves to an H1-only README, shift accordingly.

2. **Splice into the README** following `## README Splice Contract` below. Use **Edit**, not Write, so the change lands as a reviewable surgical diff.

3. **Generate the d2 companion** when `withD2`:
   - Read `${CLAUDE_PLUGIN_ROOT}/assets/gen-diagram/d2-cheatsheet.md` for verified d2 syntax and icon URLs — do not improvise d2 from memory.
   ```bash
   mkdir -p "<repoRoot>/docs/diagrams"
   ```
   - Write `docs/diagrams/architecture.d2` modelling the same systems at container granularity.
   - **Pin d2 in `mise.toml`** when `miseAvailable && !d2Pinned && !--no-mise`, run from `repoRoot`:
     ```bash
     mise use d2@0.7.1
     ```
     Idempotent: records `d2 = "0.7.1"` under `[tools]`, creates `mise.toml` when absent,
     leaves every other pin untouched, and installs the binary so the render can follow.
     On success set `d2Installed = true` and `misePinWritten = true`. On failure treat it as
     a soft failure — report the stderr and carry on; a first run may need `mise trust`.
   - Render (route through mise when the pin was just added and d2 is not yet on PATH):
     ```bash
     d2 docs/diagrams/architecture.d2 docs/diagrams/architecture.svg
     # or: mise exec -- d2 docs/diagrams/architecture.d2 docs/diagrams/architecture.svg
     ```
   - A non-zero exit is a **soft failure**: report it in Phase 6 with `⚠️`, keep the `.d2` source, and drop the `![Architecture](...)` image line from the block (leave the source link) so the README never points at a missing file.

### Phase 6: Validation & Success Report

1. **Static Mermaid checks (always run).** A malformed block renders as a red error box, which is worse than no diagram. Verify every generated block:
   - Balanced `subgraph` / `end`; every `alt` / `else` / `opt` / `loop` / `par` / `critical` / `break` closed with `end`.
   - **No node id is a reserved word**: `end`, `graph`, `subgraph`, `class`, `classDef`, `click`, `style`, `linkStyle`, `direction`, `default`, or bare `o` / `x`. A lowercase `end` id silently breaks the whole flowchart.
   - Labels containing `()`, `[]`, `{}`, `:`, `;`, `,`, `#`, `"`, `/` or `-->` are quoted. Line breaks are `<br/>`, never `\n`.
   - `sequenceDiagram`: every lifeline `participant`- or `actor`-declared before first use; `activate`/`deactivate` balanced.
   - `erDiagram`: cardinality tokens well formed (`||--o{`, `}o--||`, `||--|{`); every relationship carries a label.
   - Every `flowchart` declares a direction (`LR` or `TB`).
   - Fences are exactly ` ```mermaid ` — lowercase, no attributes.
   - **No hardcoded light-mode fills**: any `classDef` sets `fill`, `stroke` and `color` together, or the diagram has no styling at all. Otherwise labels vanish in dark mode.

   Fix any violation and re-check before writing. Do not ship a block that fails these.

2. **Optional render check** when `mmdcInstalled` and not `--dry-run`:
   ```bash
   mmdc -i <scratch>.mmd -o <scratch>.svg -q
   ```
   Run once per block using a scratch file. Report parser errors; treat as a soft failure since the source is already written.

3. **Verify the result:**
   ```bash
   test -f <readme> && wc -l <readme>
   grep -c '^[`]\{3\}mermaid$' <readme>   # count mermaid fences
   grep -c 'GENERATED: architecture-diagrams' <readme>
   ```
   The marker count must be exactly 2 (one BEGIN, one END). Anything else means the splice went wrong — report it loudly.

4. **Success report (normal execution):**
   ```
   ✅ README architecture section updated

   Files:
     ✓ <readme> (<N> lines, +<A>/-<B>)
     ✓ docs/diagrams/architecture.d2 (<N> lines)      # only if withD2
     ✓ docs/diagrams/architecture.svg                 # only if render succeeded
     ✓ mise.toml (d2 = "0.7.1")                       # only if misePinWritten

   Section:      ## <section> (<"created" | "updated in place">)
   Complexity:   <tier> (score <N>/17)
   Diagrams:     <N> (<comma-separated names>)
   Validation:   <"static checks passed (8/8)" + ", mmdc render OK" | ", mmdc not installed — render not verified">

   Next steps:

     1. Review the diff:
        git diff -- <readme>

     2. Preview the rendering:
        • Push the branch and open the README on GitHub/GitLab/Forgejo
        • Or paste a block into https://mermaid.live/

     3. Check both themes:
        Toggle light/dark on the forge — labels must stay legible

     4. Revert if unhappy:
        git checkout -- <readme>

     5. Regenerate after the architecture changes:
        /gen-readme-diagram

     6. Need icons, themes, or more than 4 views:
        /gen-diagram --type=c4
   ```

5. **Success report (dry-run):**
   ```
   ✅ [DRY RUN] Preview only — no files written

   Would update:
     • <readme> (<"new ## <section>" | "replace generated block, lines <A>-<B>">)
     • docs/diagrams/architecture.d2 + .svg          # only if withD2 && d2Installed

   --- Preview of the generated block ---
   <full block content>
   --- end preview ---

   Run again without --dry-run to write.
   ```

6. **If `tier = none`**, the report replaces the `Diagrams:` line with:
   ```
   Diagrams:     none — orientation paragraph only
                 Force a context diagram with: /gen-readme-diagram --level=context
   ```

7. **If the d2 render failed**, append:
   ```

   ⚠️  d2 render failed (.d2 source was written, image link omitted from the README):
        <stderr from d2>
        Try manually: d2 docs/diagrams/architecture.d2 docs/diagrams/architecture.svg
   ```

## Complexity Rubric

Scoring is deterministic so that repeated runs on an unchanged repo land on the same tier.

```
+1  per external system (datastore / third-party API / broker / object store)   cap +5
+1  per entry point beyond the first                                            cap +3
+1  if top-level internal modules >= 4
+1  more if top-level internal modules >= 8
+1  if source files > 50
+1  more if source files > 200
+2  if multiple deployable services (>1 app service in compose/k8s, or >1 traffic-serving entry point)
+1  if IaC present (*.tf, helm/, k8s/)
+1  if a schema with >= 3 related entities is discoverable
+1  if async messaging is present (queue, topic, broker)
                                                                 maximum score 17
```

| Score | Tier | Diagram set |
|-------|------|-------------|
| 0, and no external systems | `none` | No diagram — orientation prose only |
| 1-3 | `context` | System context (`flowchart LR`) |
| 4-7 | `component` | + Component view (`flowchart TB` with subgraphs) |
| >= 8 | `full` | + Primary flow (`sequenceDiagram`), + Data model (`erDiagram`, only when >= 3 related entities) |

**Tier `none` is a legitimate outcome, not a failure.** For a single-purpose library or a
script, a two-box diagram carries no information a sentence does not. Say so, and offer
`--level=context` for callers who want one anyway.

**The context diagram is non-negotiable at every tier >= `context`**: the application as a
single node, actors on one side, external systems on the other, every edge labelled with
protocol and purpose (`"HTTPS: submit order"`, `"TCP 5432: read/write"`).

**Hard caps**: <= 4 diagrams, <= 15 nodes per diagram, every edge labelled, and no diagram
that restates another's content. Past those limits, point the reader at `/gen-diagram`.

## README Splice Contract

The generated content always lives between a marker pair:

```
<!-- BEGIN GENERATED: architecture-diagrams -->
<!-- Regenerate with: /gen-readme-diagram -->
...
<!-- END GENERATED: architecture-diagrams -->
```

**Anchor resolution — first match wins:**

1. **Markers already present** → replace everything strictly between them. Fully
   idempotent, and it keeps working if the user has moved the block elsewhere in the file.
2. **Target section present** → append the block at the **end** of that section, i.e. just
   before the next heading at the same level, or end of file. All existing prose in the
   section is preserved above the block. The section is matched case-insensitively against
   `--section`, else `Architecture`, `Architecture Overview`, `Design`, `How It Works`.
3. **No target section** → insert a new `## <section>` heading plus the block:
   - before the first of `## Installation`, `## Getting Started`, `## Quick Start`, `## Usage`;
   - else before the first of `## Contributing`, `## Development`, `## License`;
   - else append at end of file.

   Architecture belongs after the pitch and badges, before the how-to-run.

**Safety rules — each of these is a real bug source:**

- Never modify a single byte outside the marker block.
- **Track fenced regions when locating headings.** A `## ` line inside a ``` fence is not a
  heading. A README that documents Markdown will otherwise be spliced mid-code-block.
- Match only ATX headings at line start; ignore `#` inside inline code or links.
- Preserve the file's existing line endings and trailing-newline convention.
- Emit exactly one marker pair. If the file somehow already contains more than one BEGIN,
  abort with an error rather than guessing which to replace.
- Use `Edit` rather than `Write` so the result is a minimal, reviewable diff.

## Tool Provisioning (mise)

The Mermaid diagrams need no toolchain at all — that is the point of this skill. The
**optional d2 companion** does need the `d2` binary, and it is pinned through
[mise](https://mise.jdx.dev) so the committed SVG is reproducible on any machine and in CI.

**Pinned version: `d2@0.7.1`.**

```bash
mise use d2@0.7.1
```

- Records `d2 = "0.7.1"` under `[tools]` in the repo-root `mise.toml`, creating the file if
  the repo has none and preserving every existing pin if it does
- Installs the binary, so the render can follow in the same run
- Idempotent — a no-op once the pin matches

Rules this skill follows:
- **Only when the d2 companion actually runs.** A Mermaid-only run never touches `mise.toml`.
- **Detect in Phase 1, write in Phase 5**, behind the confirmation gate. Never under `--dry-run`.
- **Never rewrite an existing pin** — if `mise.toml` already lists d2 at any version, that
  version wins.
- **Opt out with `--no-mise`** (implied by `--no-d2`) for repos managing tooling another way.
- **Soft-fail only** — a failed `mise use` never blocks the README update.

`/gen-diagram` pins the same version through the same mechanism; see its
`## Tool Provisioning (mise)` section for the CI side.

## Integration with Other Skills

- **Before `/gen-readme-diagram`**: none required. A README must exist.
- **After `/gen-readme-diagram`**:
  - `/commit` to commit the README change with a conventional message.
  - `/upd-project-description` benefits from the richer README when deriving description and topics.
  - `/gen-claude` will pick up `docs/diagrams/` on its next run if the d2 companion was generated.
- **Division of labour with `/gen-diagram`**:
  - `/gen-readme-diagram` owns **README-embedded Mermaid** — inline, zero-toolchain, capped at 4 views.
  - `/gen-diagram` owns **d2 + SVG in `docs/diagrams/`** — icons, themes, layout engines, unlimited depth.
- **Companion agent**: `diagram-architect` handles ongoing edits to `.d2` files and deeper diagram work.

## Examples

```bash
# Analyze the repo, pick the tier automatically, update README.md
/gen-readme-diagram

# Preview without writing anything
/gen-readme-diagram --dry-run

# Force a context diagram even for a small library
/gen-readme-diagram --level=context

# Full treatment plus a d2 + SVG companion
/gen-readme-diagram --level=full --with-d2

# Steer the analysis toward a specific path
/gen-readme-diagram focus on the event ingestion pipeline

# Own a differently named section in a non-default file
/gen-readme-diagram --section="Design" --readme=docs/OVERVIEW.md

# Mermaid only, never touch docs/diagrams/ or mise.toml
/gen-readme-diagram --no-d2

# Full treatment with a d2 companion, but leave mise.toml alone
/gen-readme-diagram --level=full --with-d2 --no-mise
```

## Limitations & Caveats

- **Not every renderer supports Mermaid**: npm, PyPI and crates.io README viewers show the block as plain text. Forgejo/Gitea need Mermaid enabled in `app.ini`. If the project publishes to a package registry, the generated prose says the diagrams render on the repository page.
- **No icon catalog**: Mermaid has no vendor icons. Use `/gen-diagram` when the diagram needs AWS/GCP/vendor logos.
- **The d2 companion edits `mise.toml`**: it pins `d2 = "0.7.1"` so the SVG is reproducible. Disclosed in the preview and skippable with `--no-mise`. A Mermaid-only run never touches it.
- **Repo analysis is best-effort**: the Explore agents infer external systems from manifests and client construction. Dynamically configured dependencies get missed — review the `Signals detected` block in the preview.
- **Diagrams drift**: nothing keeps the section in sync with the code. Re-run after architectural changes; the marker contract makes that a clean no-op when nothing moved.
- **Four-diagram cap**: past four views a README stops being a README. Split into `docs/` with `/gen-diagram`.
- **Sequence diagrams are one flow**: the skill picks a single primary path, not the whole API surface.

## Error Recovery

**If the block renders as a red error box on the forge:**
1. Copy the block into https://mermaid.live/ — it reports the exact parser error and line.
2. Most common cause: a node id that is a reserved word, especially `end`. Rename to `end_node`.
3. Second most common: unquoted punctuation in a label. Wrap it: `api["/v1/orders (public)"]`.
4. Third: an unbalanced `subgraph` / `end` pair.

**If labels are invisible in dark mode:**
1. Remove the `classDef` styling entirely — the host renderer's defaults are theme-aware.
2. Or set `fill`, `stroke` and `color` together on every `classDef`.

**If the splice landed in the wrong place:**
1. `git checkout -- <readme>` to revert.
2. Move the marker pair by hand to where the block belongs, then re-run — rule 1 of the
   splice contract replaces markers wherever they sit.
3. Or pass `--section=<heading>` to target a specific section.

**If the README ends up with duplicate marker pairs:**
1. Delete all but one pair by hand.
2. Re-run. The skill aborts rather than guessing when it sees more than one BEGIN.

**If `mise use d2@0.7.1` fails:**
1. Untrusted config is the usual cause: `mise trust` in the repo root, then retry.
2. Unknown version — check the registry: `mise ls-remote d2`.
3. Offline or locked down: re-run with `--no-mise`, or `--no-d2` to skip the companion
   entirely. The Mermaid section is written either way.

**If the analysis invented or missed a dependency:**
1. Re-run with `--dry-run` and read the `Signals detected` block.
2. Pass `hints` to steer it, e.g. `/gen-readme-diagram the redis dependency is only for rate limiting`.
3. Or accept the block and correct the Mermaid by hand — a later re-run will overwrite it, so
   move hand-edits outside the markers if they must survive.

## Additional Resources

- Mermaid documentation: https://mermaid.js.org/
- Mermaid live editor (debug parser errors): https://mermaid.live/
- Flowchart syntax: https://mermaid.js.org/syntax/flowchart.html
- Sequence diagram syntax: https://mermaid.js.org/syntax/sequenceDiagram.html
- ER diagram syntax: https://mermaid.js.org/syntax/entityRelationshipDiagram.html
- GitHub Mermaid support: https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-diagrams
- GitLab Mermaid support: https://docs.gitlab.com/ee/user/markdown.html#mermaid
- mise (tool version manager): https://mise.jdx.dev/
- mise registry (d2 backend): https://mise.jdx.dev/registry.html
- Cheatsheet asset: `${CLAUDE_PLUGIN_ROOT}/assets/gen-readme-diagram/mermaid-cheatsheet.md`
- Companion command: `/gen-diagram` (d2 + SVG for deeper diagrams)
- Companion agent: `diagram-architect`

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.