- TypeScript 94.4%
- JavaScript 3.5%
- CSS 2%
- HTML 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Keep live architecture editing, MCP tools, and a publishable CLI together on master. |
||
| demo | ||
| e2e | ||
| fixture | ||
| packages | ||
| scripts | ||
| .gitignore | ||
| .npmrc | ||
| .tool-versions | ||
| AGENTS.md | ||
| biome.json | ||
| LICENSE | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| prompt.md | ||
| README.md | ||
| tsconfig.base.json | ||
| tsconfig.json | ||
| vitest.config.ts | ||
likec4-excalidraw
Excalidraw-based visual editor for LikeC4 architecture projects. MIT licensed.
npm install -g likec4-excalidraw
likec4-excalidraw ./architecture
or without a global install:
npx likec4-excalidraw ./architecture
The command starts a local web server and prints:
LikeC4 Excalidraw editor
Project: /home/user/project/architecture
Listening: http://localhost:4242
Opening that URL launches an Excalidraw canvas backed by the supplied LikeC4 project.
CLI
likec4-excalidraw [architecture-directory]
| Option | Description |
|---|---|
--host <host> |
Bind address. Default: 127.0.0.1 (localhost only unless you pass another host) |
--port <port> |
Preferred port. Default: 4242. Falls back to a free port if busy |
--open |
Open the editor in a browser |
--readonly |
Disable scene writes and generated DSL export |
--help |
Show help |
--version |
Show version |
Default architecture directory is ..
MCP server
The editor exposes a project-aware Streamable HTTP MCP endpoint on the same network server:
http://127.0.0.1:4242/mcp
Configure an MCP client with that URL after starting likec4-excalidraw. Pass mcpToken when embedding startServer to require Authorization: Bearer <token>.
Available tools:
get_architecture,get_scene, andget_diagnosticscreate_element,update_element, anddelete_elementcreate_relationshipandcreate_viewvalidateget_canvas_screenshotfor a whole-canvas PNG or a scene-coordinate area
Mutating tools update .likec4/excalidraw.json and the validated editor-owned excalidraw.generated.c4 source.
How it works
Excalidraw canvas
↓
semantic projection
↓
LikeC4 model
↓
validation / DSL export
Excalidraw is the editing surface. LikeC4 remains the semantic model and validator. The editor does not infer an architecture from arbitrary drawing appearance.
Once a shape is promoted to a LikeC4-managed object, identity lives in namespaced customData, not in position, label, or style.
Object states
Managed
Explicitly mapped to a LikeC4 element, relationship, or view. Identity is stored in customData.likec4.
Candidate
Looks like it could become a LikeC4 object (for example an arrow between two managed elements) but has not been promoted. Candidates never silently change the model. Use Convert to LikeC4 element / Convert to LikeC4 relationship.
Decoration
Normal Excalidraw content: notes, freedraw, screenshots, headings, icons. Decorations stay fully usable and are ignored during LikeC4 export.
Semantic vs visual containment
Moving a managed child outside its parent does not rewrite FQN or parent. The editor warns, then offers:
- Move back inside
- Change semantic parent
- Ignore mismatch
Dropping a new candidate inside a managed container may suggest that parent. Silent semantic mutation does not happen.
Persistence
Scene state is stored next to the architecture project:
architecture/
existing-model.c4
.likec4/excalidraw.json
excalidraw.generated.c4
.likec4/excalidraw.json is the Excalidraw presentation: geometry, decorations, unmanaged objects, and semantic references. Schema version is 1.
LikeC4 source files are not rewritten when you drag a shape. Semantic canvas edits are written to the editor-owned excalidraw.generated.c4 file.
Export and source ownership
Semantic canvas edits update excalidraw.generated.c4 live after validation. Existing project files are imported as context and are never destructively rewritten; the editor-owned file contains the merged architecture snapshot.
Export LikeC4 also validates and writes an explicit snapshot. An empty architecture directory is bootstrapped with actor, system, and service kinds plus a Landscape view.
customData.likec4 schema
All metadata is namespaced:
{
"customData": {
"likec4": {
"version": 1,
"role": "element",
"fqn": "cloud.backend.api",
"kind": "service"
}
}
}
Relationships:
{
"customData": {
"likec4": {
"version": 1,
"role": "relationship",
"relationId": "rel_1",
"source": "cloud.frontend",
"target": "cloud.backend.api"
}
}
}
Views / frames:
{
"customData": {
"likec4": {
"version": 1,
"role": "view",
"viewId": "backend"
}
}
}
role may also be candidate. Identity is never inferred from visible text.
Development
Requires Node 22+ and pnpm.
pnpm install
pnpm test
pnpm typecheck
pnpm lint
pnpm build
pnpm --filter likec4-excalidraw start -- ./fixture
pnpm publish:check
pnpm pack
The published package is likec4-excalidraw. Workspace libraries stay private; the CLI build bundles them and copies the app into packages/cli. Run pnpm build before pnpm pack or pnpm --filter likec4-excalidraw publish.
The fixture under fixture/ is a small LikeC4 project used by tests and local smoke runs.
For a larger walkthrough, use demo/:
pnpm --filter likec4-excalidraw start -- ./demo
Current limitations
- Deployment model editing, dynamic views, and advanced predicate editing are deferred.
- Export uses explicit view membership (
include cloud.backend) rather than reconstructinginclude cloud.backend.**. - LikeC4 manual-layout round-trip is not written back. Excalidraw geometry is authoritative inside this app. Layouted coordinates are used only for the initial import when available.
- Duplication is handled after the fact: copy/paste of a managed object becomes a candidate instead of a second identity. Use Add existing element to this view for another presentation of the same FQN.
- The UI follows Excalidraw's own look rather than a separate design system.
Library notes
Current integrations (LikeC4 1.59.x, @excalidraw/excalidraw 0.18.x):
- Load with
LikeC4.fromWorkspace/fromSource - Query with
computedModel(),layoutedModel(),getErrors() - Export prefers
@likec4/coreBuilder +@likec4/generatorswhen available, with a deterministic DSL serializer fallback - Manual LikeC4 layout snapshots exist but are not a stable write API here, so they are read-only via
layoutedModel()