crayon-c4
v0.2.0
Published
Generate a CRAYON-C4 architecture model (JSON) from a Next.js, React, .NET, or Java repository. Re-runnable, merge-safe, configurable via .crayon/config.json.
Downloads
50
Maintainers
Readme
crayon-c4
Generate a CRAYON-C4 architecture model from your code — then import it into the web app, where a non-destructive merge keeps your manual curation (descriptions, renames, colours, layout) while the diagram catches up to the latest code.
Use it
npx crayon-c4 .Run it at your repo root. It detects the stack (Next.js / React / .NET / Java — Maven or Gradle), analyzes the code, and writes:
crayon-c4-project.json— the model file (import this into the web app)crayon-c4-provenance.json— re-run sidecar that makes merges rename-safecrayon-c4-enrichment.json— optional directives for a downstream description filler
✓ Detected: Next.js
✓ Wrote crayon-c4-project.json (4 systems · 7 containers · 23 components · 31 relationships)No configuration is required. The same code always produces the same output (deterministic).
Scoping to specific apps
By default every Next.js app / .NET solution under the repo becomes a system. In a monorepo (or a repo that vendors sample apps), narrow the analysis with --root — repeat it for several:
npx crayon-c4 . --root apps/web --root services/billingRoots can also be set once in the project config (static.roots). Either way, only files under the named roots are analyzed, so unrelated sub-apps never appear as phantom systems.
Set up settings without writing JSON — crayon-c4 init
A big repo can generate a diagram with 200 boxes, which communicates nothing. init measures what you'd get, proposes the test/sample projects worth dropping, and writes .crayon/config.json for you — no AI, no editor:
npx crayon-c4 init . # measure + show proposals (writes nothing)
npx crayon-c4 init . --yes # apply the proposals3 of 5 diagram(s) exceed 20 elements: Domain Library — Components (67), Web UI — Components (50), API — Components (36)
Proposed exclusions (test / sample projects):
- Acme.QueryApi.Tests
- Acme.Tests
Detected projects you may exclude:
Acme.Publisher (Container, 11 child element(s))
Acme.QueryApi (Container, 10 child element(s))
…It re-measures after writing, so you see the effect immediately — and tells you what's still over budget. Iterate by editing the file (it carries a $schema, so editors autocomplete it) and re-running init.
| flag | meaning |
|---|---|
| --yes | apply the proposed exclusions instead of just printing them |
| --exclude "A,B" | exclude exactly these instead (--exclude "" for none) |
| --granularity folder\|file | how detailed component diagrams are (see below) |
| --budget N | elements per diagram to aim for (default 20) |
| --dry-run | print the config that would be written |
Updating is safe: init merges — it never drops a key you set by hand, and re-running it changes nothing.
Project settings — .crayon/config.json
Per-project settings live in your repo at .crayon/config.json (the legacy root-level crayon-extract.config.json still works; .crayon wins when both exist). They travel with the repo, so every machine/editor that generates the model behaves the same. Everything is optional:
{
"schema": 1,
// Steer the AI passes (Enrich / Model / Fill with AI) for THIS project.
"prompts": {
"append": "Describe everything in payments-domain terms, in English.",
"enrichment": "Prefer short, business-facing summaries.",
"modeling": "Model the invoice flow first.",
"scoped": ""
},
// Keep clutter projects off the diagrams, and bundle many small projects
// into one meaningful container. Patterns are anchored globs matched against
// the project's name, its source path, and (for whole apps in a monorepo)
// its repo-relative root.
"projects": {
"exclude": ["*.Tests", "*-fixtures", "packages/*"],
"bundles": [
{ "name": "Shared packages", "match": ["Acme.Common*"], "tech": ".NET" }
]
},
// The same two rules one level down, plus how detailed a component IS.
"components": {
// "folder" (default): a FOLDER is one component, its files become Code
// (still shown at --depth code). "file": every source file is a component.
// Next.js / React only — .NET and Java components are namespaces/packages,
// which already group like folders, so this has no effect there.
"granularity": "folder",
"exclude": ["*.stories", "legacy/*"],
"bundles": [
{ "name": "C4 Model", "match": ["c4", "canvas", "diagram"] }
]
},
// Name the entry points that deserve a FULL F4 flow diagram: an API endpoint,
// a button/screen component, a controller. Each match gets a traced diagram
// at METHOD level (TS/JS): every called function is its own activity, edges
// follow the call sites in source order, fetch() calls jump to the matching
// route handler, lanes are the containers, one kind:"call" connection per hop
// (Simon Brown style, no return lines), and an error boundary event appears
// wherever that step's code actually has a catch.
"flows": {
"entryPoints": [
{ "match": "src/app/api/checkout/**", "name": "Checkout endpoint" },
{ "match": "src/components/BuyButton.tsx", "name": "Buy click" }
],
"maxDepth": 4
},
"static": { "roots": [], "exclude": [] }
}prompts— project-scoped instructions for the AI passes.appendapplies to every pass; the named fields add pass-specific guidance. Editor-level settings (e.g. the VS CodecrayonC4.promptAppend) are appended after these.projects.exclude— a matched project (system or container) disappears from the model together with its components and every relationship touching it. The run report lists what was excluded — nothing is hidden silently.projects.bundles— matched containers (per parent system) collapse into ONE container namedname; their components move into it and all edges re-point to it (deduped). The bundle keeps a stable id, so re-runs merge cleanly.components.granularity— the biggest readability lever for Next.js / React, where a component would otherwise be one per source file."folder"(the default) makes a folder the component and demotes its files to Code, so--depth componentshows folders and--depth codestill reaches every file — nothing is lost."file"restores one component per file. No effect on .NET / Java, whose components are namespaces / packages already.components.exclude/components.bundles— exactly theprojectsrules, applied to components. Matched against the component's name, source path, and folder path. Usebundlesto merge related modules into one meaningful box when a component diagram is still too dense.flows.entryPoints— each matched element becomes a fully traced F4 diagram (replacing the default sketch flow for that entry), at method level: TS/JS follows imported-symbol call sites in source order (BuyButton → HTTP POST /api/checkout → logOrder() → chargeOrder() → taxFor()); C#/Java follows constructor, static, and typed-local instance calls between the extracted classes (PaymentController → new Invoice() → TaxRule.rateFor()), up tomaxDepthhops. Boundary events appear only where the step's own source handles errors.
Shaping never changes the ids of surviving elements, so your manual curation survives re-runs exactly as before.
Options (all optional)
| Flag | Meaning | Default |
|------|---------|---------|
| [path] | repo to analyze | . |
| --root <path> | scope analysis to a specific app/solution root (repeat for several) | whole repo |
| --out <file> | model output path | <path>/crayon-c4-project.json |
| --provenance <file> | provenance sidecar path | <path>/crayon-c4-provenance.json |
| --starting <file> | starting model to reconcile against | — |
| --exclude <globs> | extra comma-separated exclusion patterns | engine defaults |
| --config <file> | extractor config | discovered (.crayon/config.json) |
| --file-cap <n> | max files analyzed | engine default |
| --apply | write the merged result (vs report only) | off |
| --dry-run | report only, write nothing | off |
| --json | machine-readable summary | human text |
Exit codes
0 success · 2 usage/config · 3 no supported stack (nothing written) · 4 invalid --starting model · 5 output failed validation (nothing written).
Validate the output
The model file conforms to the published JSON Schema (schema/crayon-c4.schema.json, Draft 2020-12):
npx ajv-cli validate -s schema/crayon-c4.schema.json -d crayon-c4-project.jsonLicense
Free to use, for commercial and non-commercial work — see the bundled LICENSE. The source code is proprietary (not open source). The models it generates from your code are yours, unrestricted. The CRAYON-C4 web app offers a free tier with a subset of its functionality; the VS Code extension bundles this same engine.
