Turn any
SKILL.mdinto a self-contained decision flowchart HTML.
SkillFlowChart generates clean, deterministic decision flowcharts from natural-language skill definitions. It splits the work where each side excels: AI extracts semantics, a script computes geometry — so every render of the same input is pixel-identical.
- How It Works
- Quick Start
- nodes.json Schema
- Themes
- Examples
- Project Structure
- Design Principles
- Contributing
- License
SKILL.md ──AI extracts──▶ nodes.json ──script renders──▶ HTML
(semantics) (structured) (deterministic) (SVG)
| Stage | Who | Why |
|---|---|---|
| Read SKILL.md → nodes.json | AI (LLM) | Natural language is unstable; AI understands context |
| nodes.json → HTML | Script (Python) | Coordinate math must be deterministic and reproducible |
The AI never outputs coordinates or SVG. The script never guesses semantics. The only interface between them is the nodes.json schema.
- Python 3.8+ (standard library only, zero dependencies)
- Any LLM to extract
nodes.jsonfrom yourSKILL.md
# 1. Ask your AI to read SKILL.md and generate nodes.json
# (extraction rules are documented in SKILL.md)
# 2. Run the script
python3 scripts/flowchart.py nodes.json --out flowchart.html
# 3. Open the HTML in any browser
open flowchart.htmlpython3 scripts/flowchart.py <nodes.json> [--out <output.html>] [--theme light|dark|transparent] [--json-out <debug.json>]{
"title": "My Skill",
"subtitle": "Optional description",
"nodes": [
{"id": "entry", "type": "entry", "label": "Start", "role": "ai"},
{"id": "check", "type": "decision", "label": "Valid?", "role": "decision"},
{"id": "exit", "type": "terminal", "label": "Exit", "role": "terminal"},
{"id": "process", "type": "process", "label": "Run", "role": "script"},
{"id": "report", "type": "output", "label": "Generate Report", "role": "output"}
],
"edges": [
{"from": "entry", "to": "check", "label": "", "side": "bottom"},
{"from": "check", "to": "exit", "label": "No", "side": "left"},
{"from": "check", "to": "process", "label": "Yes", "side": "bottom"},
{"from": "process", "to": "report", "label": "", "side": "bottom"}
],
"legend": []
}| type | shape | description |
|---|---|---|
entry |
rounded rect | flow start point |
decision |
diamond | branch point (yes/no, mode switch) |
process |
rounded rect | processing step |
output |
rounded rect | report / file output |
terminal |
rounded rect | exit / error termination |
| role | description |
|---|---|
ai |
AI inference / LLM call |
output |
report / file output |
decision |
decision point |
script |
script execution |
terminal |
termination / error |
One node = one role. If a step involves multiple types of work (e.g. script baseline + AI analysis), split it into separate nodes.
The AI must explicitly label each edge's side — the script never guesses direction.
| side | meaning | layout behavior |
|---|---|---|
bottom |
main flow down | target at next level, inherits x from source |
left |
decision left branch / fork left | decision → same level horizontal; process → next level fork |
right |
decision right branch / fork right | same as left, mirrored |
"" |
unlabeled (same as bottom) |
inherits upstream |
Decision left/right → same level, horizontal connector.
Process left/right → next level, orthogonal fork (no diagonal lines).
Three built-in themes:
| theme | background | label handling |
|---|---|---|
light (default) |
white | centered with white halo |
dark |
#0a0a0f |
centered with dark halo |
transparent |
none | vertical edge labels offset to one side |
python3 scripts/flowchart.py nodes.json --theme dark --out dark.htmlSee docs/halucatch-nodes.json for a complete real-world example, and the generated outputs:
SkillFlowChart/
├── SKILL.md # Skill definition (AI entry point + extraction rules)
├── scripts/
│ └── flowchart.py # Core: nodes.json → SVG + HTML
├── docs/
│ ├── halucatch-nodes.json # Example input
│ ├── halucatch-light.html # Example output (light)
│ ├── halucatch-dark.html # Example output (dark)
│ └── halucatch-transparent.html # Example output (transparent)
├── tests/
│ └── simple.json # Minimal test case
└── README.md
- Structured relay — layout logic never depends on the LLM; same input always produces identical output
- Zero dependencies — pure Python standard library, no
pip installneeded - Self-contained HTML — single file output, no external CSS/JS references
- No diagonal lines — all connectors are horizontal or vertical (orthogonal routing)
- Platform-agnostic — works with any LLM (ChatGPT, Claude, Gemini, local models, etc.)
- Fork the repo
- Edit
SKILL.md(extraction rules) orscripts/flowchart.py(layout/rendering) - Test with
tests/simple.jsonanddocs/halucatch-nodes.json - Submit a pull request
MIT