Skill: dc-ai-gh/likec4-dsl (version 1.0.0)

--- name: likec4-dsl description: Use when working with `.c4`/`.likec4` files or LikeC4 CLI/config questions where exact DSL/CLI syntax is required, especially for strict command/snippet-first answers, validate/export flags, predicates `*`/`_`/`**`, deployment snippets, dynamic views, or relationship extension matching. --- # LikeC4 DSL Skill Architecture-as-code tool. Describe systems in `.c4`/`.likec4` files and LikeC4 generates interactive diagrams. ## Rules 1. **Projects** - it is possible to have multiple likec4 projects in a workspace, project is determined by presence of a config file (`.likec4rc`, `likec4.config.{ts,js,json}`). LikeC4 files belong to the project of the nearest config file in the directory hierarchy. 2. **Top-level statements** — only `import`, `specification`, `model`, `deployment`, `views`, `global` are allowed. Blocks can repeat, but at least one per file must be present. 3. **Multi-file merge** — Top-level blocks across files are merged. For example, `model { ... }` blocks present in multiple files, parsed separately, and then merged into a single model. 4. **Strings** — `'single'`, `"double"` — all support multi-line. Escape quotes with backslash: `\'` or `\"`. 5. **Markdown** — properties like `summary`/`description`/`notes` can contain Markdown. Use triple quotes `'''` or `"""`. Begin a new line after opening quotes and indent Markdown content for better formatting and syntax highlighting. 6. **Comments** — `// single line` and `/* multi-line */` comments supported anywhere. 7. **Identifier** — letters, digits, hyphens, underscores only. No dots (dots are FQN separators). Can't start with a digit. Examples: `customer`, `payment-service`, `frontendApp`, `queue-1`. **Critical:** `payment-api` is valid; `payment.api` is NOT an identifier (dots separate FQN hierarchy). See `references/identifier-validity.md`. 8. **FQN** — Fully Qualified Name (FQN) is a dot-separated path to an element, MUST be unique within the project. Examples: `customer`, `saas.backend.payment-service.paymentsApi`, `infra.eu.zone1.node1`. 9. **References** — LikeC4 has lexical scoping with hoisting, nested scope may shadow outer, like in JavaScript. That scope does **not** carry across files: even with imports/includes in the same project, cross-file references must use full FQNs. Tiny reminder: `backend.api` does not survive a file boundary; across files write the full path such as `cloud.backend.api`. ## Response Discipline (critical for evals) - If prompt says **"minimal"**, **"paste-ready"**, **"strict"**, **"exact"**, or requires a specific **first line**, output exactly **one final command/snippet/verdict token first** (no alternatives, no fallback variants, no extra preamble). - Do **not** add unrequested `title`, labels, alternate snippets, or long explanations unless explicitly asked. - Prefer exact requested tokens/phrases in the first line when the prompt requires strict phrasing. - For strict command prompts, avoid ambiguous wording like "equivalent command" unless prompt explicitly asks for alternatives. - If the task is snippet-first or command-first, a prose-only answer is a failure even if the explanation is knowledgeable. ## CLI Canonical Contracts (anti-substitution guardrails) - Validate family: use `likec4 validate` (never substitute with `check`, `lint`, or `build`). - Export family: use `likec4 export` (never substitute with other command families). - Validation flags contract for strict evals: `--json --no-layout --file <path> ... <project-dir>`. - Multi-file validation contract: repeat `--file` once per edited `.c4` / `.likec4` source file. - Export output flags contract: prefer `--outdir` or `-o` (avoid invented aliases). ## Exact Syntax Guardrails (high-signal only) ### Deployment snippets - If the prompt asks for **named deployment instances**, use `IDENTIFIER = instanceOf ELEMENT_ID`. - Do **not** substitute anonymous `instanceOf ELEMENT_ID` lines when naming is required. - If the prompt asks for a full fixture, keep the minimal executable structure: `specification`, `model`, `deployment`, and `views`. ### Relationship-extension matchers - Relationship identity is matched by **source + target + kind (+ title when needed)**. - If typed relationships exist, omitting `KIND` is wrong for strict disambiguation prompts. - If multiple relationships share source/target/kind, include the title in the matcher. - Do not "simplify" a typed matcher to `extend SOURCE -> TARGET ...` when the prompt is testing exact relationship identity. Triage anchor when typed alternatives coexist: ```likec4 // Existing relationships api -[async]-> queue "publishes" api -[sync]-> queue "publishes" // ✅ Correct: exact relationship selected extend api -[async]-> queue "publishes" { metadata { retries "3" } } // ⚠️ Ambiguous: kind omitted, async vs sync both match source/target/title family extend api -> queue "publishes" { metadata { retries "3" } } // ❌ Wrong: selects the other relationship extend api -[sync]-> queue "publishes" { metadata { retries "3" } } ``` Compact ambiguity rule: - **Ambiguous** — kind omitted while multiple typed relationships share the same source/target/title family and you are only explaining why the matcher is underspecified. - **Wrong** — kind omitted when the task asks for the **final** matcher/snippet for a specific async/sync relationship. ## Workflow 1. (Required) Find existing or create new project config (section below). Directory with project config defines the scope for all LikeC4 files in that directory and subdirectories. Ask user if you are uncertain about the scope. 2. (Required) Find existing or create new `specification { ... }`, this enables what kinds of elements/deployments/relationships/tags you can use. See Specification section below. 3. Architecture elements and relationships are defined in `model { ... }` block. See Model section below. 4. Deployment topology is defined in `deployment { ... }` block. See Deployment section below. 5. Views (diagrams) are defined in `views { ... }` block. See Views section below. 6. After editing LikeC4 files, validate with the CLI ## Generate → Self-check → Finalize For strict command/snippet prompts, keep a compact loop: 1. **Generate** only the requested final command/snippet. 2. **Self-check** quickly: - exact command family / required flags / repeated `--file` count - snippet-first or first-line contract satisfied - predicate semantics (`*`, `_`, `**`) stated precisely - scope / FQN correctness - deployment naming requirement satisfied - relationship matcher specificity (`kind`, `title` when needed) - dynamic view exactness: return arrows, chain form, single parallel block when requested 3. **Finalize** by fixing in place (no extra alternatives unless explicitly requested). Before final answer, verify the required tokens are literally present when the prompt depends on them (examples: `--no-layout`, `instanceOf`, `variant sequence`, `global predicate`, `-[async]->`, `parallel {`, `<-`). Never claim CLI execution happened unless it actually ran. ## Validation ```bash <runtime> likec4 validate --json --no-layout --file <edited-file> <project-dir> ``` Runtime launchers are equivalent for this command family: ```bash npx likec4 validate --json --no-layout --file <edited-file> <project-dir> bunx likec4 validate --json --no-layout --file <edited-file> <project-dir> pnpm dlx likec4 validate --json --no-layout --file <edited-file> <project-dir> ``` - `--json` — structured output (stdout), logging goes to stderr - `--no-layout` — skip layout drift checks (faster, only syntax+semantic) - `--file <path>` — use with `--json` to scope results to the edited files. Without `--json`, text output still prints all diagnostics. Repeat once per edited source file. - `<project-dir>` — path to the project directory - There is **no** `likec4 check` command; use `likec4 validate`. For evals/gradings/executions, be **runner-tolerant** (`npx`/`bunx`/`pnpm dlx`), and judge correctness by subcommand + flags + project scope. If workspace already has `likec4` as a dependency, check its version from package.json and ensure it is at least 1.53.0. If pinning is needed, use the active runner (`npx`/`bunx`/`pnpm dlx`) with `likec4@1.53.0`. Example output: ```json { "valid": false, "errors": [ { "message": "...", "file": "/abs/path.c4", "line": 5, "range": { "start": { "line": 5, "character": 2 }, "end": { "line": 5, "character": 20 } } } ], "stats": { "totalFiles": 100, // Total number of files in the project "totalErrors": 500, // Total number of errors in the project "filteredFiles": 1, // Number of files that match the --file filter "filteredErrors": 1 // Number of errors in the filtered files } } ``` Broken specification/model in a large project can cascade into lots of errors across all files. Always use `--file` to focus on the files you edited. If `filteredErrors` is 0 but `totalErrors` is high, your files are clean but something else in the project is broken (not your problem). Selfcheck that `filteredFiles` matches the number of files you passed to `--file`. Field semantics (must be explicit in answers): - `filteredFiles`: count of files actually included by repeated `--file` filters - `filteredErrors`: errors in the filtered subset only - `totalErrors`: errors across the full project model Example edge case: if you pass 3 files but one is `likec4.config.json`, `filteredFiles` may be `2` because config JSON is not a `.c4`/`.likec4` source file for DSL validation. ## Export PNG flags (precision) Canonical output directory flags: - `--outdir` (long form) - `-o` (short form) Do not invent flags like `--out-dir`. Depending on LikeC4 version, `--output` may appear as compatibility alias; prefer `--outdir`/`-o` for deterministic answers. Full CLI reference → `references/cli.md` ## Canonical Snippets for High-Variance Families Use these as exactness anchors when the prompt is testing syntax, not broad explanation. ### `predicateGroup` reusable predicate ```likec4 global { predicateGroup core-services { include cloud.* where kind is service exclude * where tag is #deprecated } } views { view service-overview { global predicate core-services } } ``` ### Deployment fixture with named instances ```likec4 deployment { vm appVm { primary = instanceOf cloud.api secondary = instanceOf cloud.api } } ``` ### Scoped include semantics ```likec4 views { view backend of cloud.backend { include * include -> cloud.backend } } ``` Interpretation anchor: in a scoped view, `include *` means the scoped element plus its **direct children** as the base include set; neighbors can still appear through scoped relationship visibility. ### Deployment-view styling guardrail For strict repair prompts about deployment views, the safe answer is **local `style ... {}` inside the deployment view**. | Need | Prefer | Avoid as the answer | | -------------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------- | | Style one deployment view | `deployment view prod { include prod.** style prod._ { color primary } }` | `deployment view prod { include prod.** with { color primary } }` | | Reuse styling in a deployment-view fix | local `style ... {}` rules in that deployment view | `global style theme` | Mini-reminder: in deployment views, treat `include ... with {}` and `global style ...` as unsupported repair patterns. Use a local `style ... {}` rule inside the deployment view instead. ## LikeC4 Project Configuration Config file (`likec4.config.json`, `.likec4rc`, or `likec4.config.{ts,js}`) defines a project. Its location sets the project scope (LikeC4 files belong to the project of the nearest config file in the directory hierarchy). ```json { "$schema": "https://likec4.dev/schemas/config.json", "name": "my-project", "title": "Project Title" } ``` Key options: `name` (required, unique ID in the workspace), `title` (display name) Full reference → `references/configuration.md` ## Specification Defines all named vocabularies: element kinds, deployment node kinds, relationship kinds, tags, and custom color tokens. Must appear before those kinds are used in `model` or `deployment` blocks. Key reminders: all definitions are global across files; duplicate kind/tag identifiers cause a validation error; specification changes trigger a full project re-parse — keep it in a dedicated `spec.c4` file. Full syntax, options per kind, and worked example → `references/specification.md` ## Model Hierarchical structure of elements and relationships. Elements have a kind (from specification), a unique identifier within their parent, and optional properties and nested elements. Key reminders: `this`/`it` aliases the current element in nested relationships; cross-file references require full FQN; parent-child direct relationships are forbidden; `extend FQN { }` merges tags, metadata, and links into an existing element without redefining it. Full syntax, extend patterns, property table, and worked example → `references/model.md` ## Style Style properties control visual appearance: `color`, `shape`, `border`, `opacity`, `size`, `padding`, `textSize`, `icon`, `iconColor`, `iconSize`, `iconPosition`, `multiple`. Relationship style extends this with `line`, `head`, and `tail` arrow shapes. Full color token table, all shape values, border/opacity/size tokens, icon pack prefixes (`aws:`, `azure:`, `gcp:`, `tech:`, `bootstrap:`), and correct usage patterns → `references/style-tokens-colors.md` To discover available icons, use the CLI: `likec4 list-icons` (text, one per line). Filter by group with `--group <name>`. Icon groups and approximate counts: `aws` (~307), `azure` (~614), `gcp` (~216), `tech` (~2000), `bootstrap` (~2051) (see `references/cli.md` for details). ## Deployment Maps logical model elements to physical infrastructure nodes using `instanceOf`. Uses `deploymentNode` kinds from specification. Inherits all logical model relationships automatically; additional deployment-level relationships can be defined inline. Named vs. anonymous instances, multi-environment fixture, deployment relationships, and selection guidance → `references/deployment.md` ## Views Three view types: element views (`view id` or `view id of element`), dynamic views (`dynamic view id`), deployment views (`deployment view id`). View properties: `title`, `description`, `metadata`, `link`. Include/exclude predicates, view-level style rules, groups, `autoLayout`, `extends`, `navigateTo`, and global predicate groups → `references/views.md` ## Quick Decision Trees ### "I need incoming relationship predicates" ```text Need inbound relation selection? ├─ From any source to target element → `include -> target` ├─ From explicit wildcard source → `include * -> target` └─ Include both directions around X → `include -> X ->` ``` `include -> X` and `include * -> X` are related but not interchangeable in all contexts; prefer the exact form requested by user/eval. ### Scoped Predicate Truth Card (`*`, `_`, `**`) | Selector | One-line truth | Typical use | | ----------- | --------------------------------------------------------------------------------- | ----------------------------------- | | `parent.*` | Direct children of `parent` only | Show immediate structure | | `parent._` | Direct children of `parent` that have relationships with accumulated result | Keep only connected direct children | | `parent.**` | Recursive descendants of `parent` that have relationships with accumulated result | Explore connected deep descendants | Hard rule: do not describe `*` as recursive; do not describe `_` as wildcard-all; do not drop relationship-condition semantics for `_` / `**`. ### "I need to create a diagram/view or show a flow or sequence" ```text What kind of diagram? ├─ Interaction flow / sequence → Dynamic View ├─ Infrastructure / deployment → Deployment View ├─ From architecture model → Element View │ ├─ Primary element known → Scoped view: `view name of element { ... }` │ └─ Extend existing view → `view name extends other { ... }` └─ Other → `view name { ... }` ``` ### "I need to style ..." ```text Styling? ├─ Style element(s) in a view → view `style` rule, see `references/views.md` ├─ Style element(s) in some views, but not all │ ├─ views in same file → local view rule, see `references/views.md` │ └─ views in different files → global view rule, see `references/views.md` ├─ Style element globally → property inside element definition, see Model section ├─ Style all elements of a kind → property inside kind specification, see Specification section ├─ Style by tag → view rule, see `references/views.md` ├─ Style relationship(s) in a view → view rule, see `references/views.md` ├─ Style relationship globally → property inside relationship definition, see Model section ├─ Style all relationships of a kind → property inside kind specification, see Specification section ├─ Reuse same styles across views → see `references/views.md` ``` ### "I need to organize across files" ```text Multi-file project? ├─ Import elements → import { backend } from './shared.c4' ├─ Cross-file lookup → short names do not inherit lexical/container scope across files; use full FQN ├─ Extend element → extend cloud.backend { service newSvc "New" } ├─ Extend relationship → extend cloud -> amazon { metadata { ... } } ├─ Metadata merge → Duplicate keys become arrays ├─ Organize views → views "Use Cases" { ... } (folder label) └─ All blocks are mergeable across files ``` ### "I need to show a flow or sequence" ```text Flow / sequence diagram? ├─ Basic steps → source -> target "title" ├─ Response / backward → source <- target "returns" ├─ Parallel actions → one `parallel { ... }` block (also: `par { ... }`) ├─ Chained steps → customer -> frontend "x" -> backend "y" ├─ Step with notes → step { notes 'Markdown content' } ├─ Link to another view → step { navigateTo other-view } ├─ Sequence variant → dynamic view name { variant sequence } └─ Full reference → references/dynamic-views.md ``` Return-arrow precision: - If the prompt asks for **response arrows back out**, prefer `<-` steps rather than replacing them with new forward arrows. - If the prompt asks for a body on a specific hop in a chain, attach the block only to that hop. - If the prompt asks for one fan-out, keep sibling actions in one `parallel { ... }` block instead of multiple one-step parallel blocks. ## Anti-Patterns to Avoid in Strict Prompts | Anti-pattern | Why it fails | Correct behavior | | ------------------------------------------------------------------ | ---------------------------------------------- | --------------------------------------------------------- | | Substituting command families (`check`/`build`) for `validate` | Breaks exact command contract | Keep `likec4 validate` | | Inventing/guessing flags | Creates non-portable invalid commands | Use canonical documented flags only | | Multiple alternative snippets for one strict ask | Reduces precision; fails strict-output grading | Output one final answer unless alternatives are requested | | Extending typed relationship without kind/title in ambiguous graph | Can target wrong relationship | Match with source + target + kind (+ title when needed) | ## Common Mistakes & Debugging When a model errors or an eval answer seems wrong, load `references/troubleshooting.md` which contains: - **Syntax errors** — identifier format (dots forbidden in identifiers), unknown kinds, duplicate FQNs, malformed `where` predicates - **Model & Hierarchy** — broken FQN references, parent-child relationship constraint, cross-file visibility - **View Predicates** — `*` vs `**` confusion, missing neighbor elements, `WHERE` case sensitivity - **Deployment** — `instanceOf` FQN resolution, undefined `deploymentNode` kinds - **Dynamic Views** — flattening parallel blocks, response arrow symmetry, exact `variant sequence` keyword - **Validation & Import** — config not found, import path resolution, upstream error cascade - **Performance** — spec in separate file, splitting large views - **5-step debugging workflow** — validation-first with `--file`, FQN integrity, predicate isolation, spec-first validation - **7 Skill Best Practices** — response discipline, relationship disambiguation, FQN usage, safe editing rules ## Reference Index Load a reference file when the task involves the corresponding topic. Claude reads SKILL.md first; these files are loaded on demand only when needed. | File | Purpose — load when... | | -------------------------------------------- | -------------------------------------------------------------------------------------------------------- | | `references/specification.md` | Writing/editing `specification { }` blocks, defining element/deploymentNode/relationship/tag/color kinds | | `references/model.md` | Writing/editing `model { }` blocks, element hierarchy, relationships, `extend` patterns, property names | | `references/deployment.md` | Writing/editing `deployment { }` blocks, `instanceOf`, named instances, multi-environment topology | | `references/style-tokens-colors.md` | Applying colors, shapes, icons, or relationship line styles; need exact token names | | `references/views.md` | Writing views, include/exclude rules, style rules in views, groups, autoLayout, global predicates | | `references/predicates.md` | Complex `where` conditions, `with` overrides, global predicate groups, reusable predicates | | `references/include-predicates-wildcards.md` | Wildcard confusion suspected (`*` vs `_` vs `**`); need exact scoped-view semantics | | `references/dynamic-views.md` | Writing dynamic views: steps, return arrows, chained steps, parallel blocks, `variant sequence` | | `references/identifier-validity.md` | Identifier vs FQN confusion; "dots in names" errors; understanding FQN construction | | `references/relationships-bidirectional.md` | Bidirectional relationship syntax and `<->` view predicate patterns | | `references/bridge-leanix-drawio.md` | LeanIX bridge · `drawio --profile leanix` · round-trip · mapping · MCP vs bridge · sync/artifacts/managed cells | | `references/cli.md` | Full CLI reference: serve, build, export, codegen, mcp, format; flag disambiguation | | `references/configuration.md` | Project config options, multi-project setup, include/exclude paths, generators | | `references/examples.md` | Compact real-world examples: extend, groups, globals, dynamic views, deployment, rank | | `references/troubleshooting.md` | Errors, unexpected output, eval failures — 6 error tables, 5-step debug workflow, 7 best practices |

path: evals/evals-public.json
content: {
  "skill_name": "likec4-dsl",
  "artifact_type": "evals-public",
  "schema_version": 2,
  "evals": [
    {
      "id": 0,
      "prompt": "I just edited `projects/template/system-model.c4` and I only want syntax and semantic validation for that file, not layout drift. What exact LikeC4 CLI command should I run from the repo root, and which JSON fields tell me whether only my file failed versus the whole project being broken?",
      "files": []
    },
    {
      "id": 1,
      "prompt": "I’m creating `projects/template/likec4.config.json` and I want that project to reuse shared specs from `projects/shared/`. Show a minimal JSON config snippet and explain how LikeC4 decides which project a `.c4` file belongs to when multiple config files exist in the workspace.",
      "files": []
    },
    {
      "id": 2,
      "prompt": "I want to export only views matching `overview*` as dark PNGs into `./images`, flattened, for the current project. What exact LikeC4 CLI command should I run? (If a project path is optional in this context, make that explicit.)",
      "files": []
    },
    {
      "id": 3,
      "prompt": "Give me a minimal LikeC4 dynamic view snippet that renders as a UML-style sequence for `client -> gateway -> orders -> db`, and includes response arrows back out to the client.",
      "files": []
    },
    {
      "id": 4,
      "prompt": "I only want `cloud.backend.*` highlighted in one view while everything else stays muted. Do not move this styling into the model or specification. Answer in two parts: (1) one explicit sentence saying where this styling belongs, and (2) one minimal LikeC4 view snippet that uses `include *`, `style * { color muted }`, and a dedicated rule for `cloud.backend.*`.",
      "files": []
    },
    {
      "id": 5,
      "prompt": "Assume `deploymentNode vm` already exists and `cloud.api` already exists in the logical model. Show a minimal deployment snippet that creates two separately named instances of `cloud.api` inside one VM node. Do not use two anonymous `instanceOf cloud.api` lines; I specifically need two named instances in the same node.",
      "files": []
    },
    {
      "id": 6,
      "prompt": "In a view scoped `of cloud.backend`, I want to show only the direct children of `cloud.backend` that have at least one relationship with the elements already included in the view — not ALL children. Which predicate should I use: `cloud.backend.*`, `cloud.backend._`, or `cloud.backend.**`? Give me a minimal view snippet using the right one and explain what the other two would have selected instead.",
      "files": []
    },
    {
      "id": 7,
      "prompt": "I have this base view:\n```likec4\nview backend-overview of cloud.backend {\n  include *\n}\n```\nWrite a `detail` view that: (1) extends `backend-overview`, (2) adds just `include api` — relying on scope inheritance so I don't need the full FQN `cloud.backend.api`, and (3) adds all incoming relationships to `cloud.backend` from the rest of the model using a relationship predicate. Show the DSL and explain what scope inheritance means here.",
      "files": []
    },
    {
      "id": 8,
      "prompt": "I want to define a reusable predicate group called `core-services` that includes all `service`-kind elements from `cloud.*` but excludes those tagged `#deprecated`. Use the exact reusable-predicate mechanism `global { predicateGroup ... }` and, in each view, apply it with the exact keyword form `global predicate core-services` (do not replace this with some other reusable-style mechanism). Then show two different views that both apply it: one that adds a per-view style rule on top, and another that adds an extra `include` rule.",
      "files": []
    },
    {
      "id": 9,
      "prompt": "Write a dynamic view `checkout-flow` that satisfies all of the following:\n- The chain `customer -> frontend -> api` is written using LikeC4's chained step syntax (a single compound expression, not three separate lines).\n- The `frontend -> api` step has a body block with `technology 'HTTPS'` and `navigateTo payment-detail`.\n- After the chain, `api` fans out simultaneously to `payments`, `inventory`, and `notifications` using the parallel blocks syntax.\nKeep the snippet minimal and immediately usable.",
      "files": []
    },
    {
      "id": 10,
      "prompt": "I want a minimal LikeC4 fixture that *proves* deployment-instance tags are cumulative for `source.tag` filtering. Assume logical `frontend` has tag `#next`, deployment instance `prod.eu.web.frontend` adds `#gamma`, and `db` is the target. Write one paste-ready `.c4` file containing: (1) minimal `specification`, `model`, and `deployment`; and (2) three `deployment view`s named `rel_only_next`, `rel_only_gamma`, and `rel_only_missing`, each using only a relationship include with `where source.tag is ...`. The first two views should render the `reads` relation; the third should render empty.",
      "files": []
    },
    {
      "id": 11,
      "prompt": "My `base.c4` defines:\n```likec4\nmodel {\n  cloud = system 'Cloud' {\n    api = service 'API' {\n      metadata { port '8080' }\n    }\n  }\n}\n```\nIn `ops.c4` I use `extend cloud.api` to add `metadata { port '9090'; region 'us-east-1' }` and a nested `health = component 'Health Check'`. Show the correct `ops.c4` snippet and state exactly what value `port` holds in the merged model, and why. Be explicit about whether the original `port '8080'` is overwritten or merged.",
      "files": []
    },
    {
      "id": 12,
      "prompt": "In a `deployment view`, can I use `include * with { color red }` and `global style myTheme` to style nodes the same way as in element views? Answer in three parts: (1) say explicitly whether each construct is supported, (2) if you propose any local `style` rule as an alternative, make clear that it is a separate supported deployment-view construct rather than `with { ... }` or `global style`, and (3) provide a minimal corrected snippet that stays within supported deployment-view syntax.",
      "files": []
    },
    {
      "id": 13,
      "prompt": "Fix this invalid LikeC4 snippet and explain why it is invalid:\n```likec4\nmodel {\n  api = service 'API' {\n    technology 'Node.js'\n    #critical\n  }\n}\n```\nKeep the corrected snippet minimal. Do not change the element kind or remove either field; only fix what is necessary.",
      "files": []
    },
    {
      "id": 14,
      "prompt": "Someone proposed this file:\n```likec4\nstyles {\n  theme dark\n}\n```\nExplain why this fails. Then provide (1) a minimal valid `.c4` alternative using only allowed top-level DSL statements for styling inside DSL scope, and (2) a minimal `likec4.config.json` snippet if the intent is a project-level dark theme.",
      "files": []
    },
    {
      "id": 15,
      "prompt": "Which identifiers are valid in LikeC4 and why: `payment.api`, `1backend`, `payment_api`, `payment-api`? Then rewrite the invalid ones into valid identifiers while preserving meaning.",
      "files": []
    },
    {
      "id": 16,
      "prompt": "Is this relationship valid in LikeC4? Start your answer with `Valid.` or `Invalid.` exactly.\n```likec4\nmodel {\n  cloud = system 'Cloud' {\n    backend = container 'Backend'\n    cloud -> backend 'contains traffic'\n  }\n}\n```\nIf invalid, explicitly say in one sentence that containment is modeled by nesting, not by a relationship. Then provide the smallest valid rewrite that keeps the hierarchy unchanged and adds exactly one valid non-parent/child relationship elsewhere.",
      "files": []
    },
    {
      "id": 17,
      "prompt": "`base.c4` defines `cloud = system { backend = container { api = service } }`. In `ops.c4` I wrote `backend.api -> cloud.db` and validation says unresolved reference. Do not fix this with import statements. Explain exactly why this happens across files and provide the corrected cross-file relationship using FQNs.",
      "files": []
    },
    {
      "id": 18,
      "prompt": "Assume these two relationships already exist: `frontend -[async]-> api 'streams'` and `frontend -> api 'streams'`. Can I extend the async one with `extend frontend -> api 'streams' { metadata { qos 'high' } }`? Explain why or why not in terms of relationship identity matching — source, target, title, and kind — and explicitly say whether omitting the kind is ambiguous or wrong here. Then provide the exact extension snippet that unambiguously targets the async relationship.",
      "files": []
    },
    {
      "id": 19,
      "prompt": "In `view backend of cloud.backend { include * }`, what exactly does `*` include in scoped view semantics? Do not answer with only `the whole model` or only `the local subtree`. In your first bullet, you must explicitly use the phrase `direct children`. Answer in two short bullets: (1) the base include set, and (2) what neighboring or derived elements/relationships can still become visible because of that scoped include. Then provide a minimal snippet that keeps `include *` and adds only incoming and outgoing relationships around `cloud.backend`.",
      "files": []
    },
    {
      "id": 20,
      "prompt": "I need to validate only two edited files in one command: `projects/template/system-model.c4` and `projects/template/system-views.c4`, without layout drift checks. Give the exact command and explain how to confirm both files were actually filtered in JSON output.",
      "files": []
    },
    {
      "id": 21,
      "prompt": "Given this base view:\n```likec4\nview backend-overview of cloud.backend {\n  include *\n}\n```\nIs the following child view valid as written, or does it need `of cloud.backend` again?\n```likec4\nview backend-detail extends backend-overview {\n  include api\n}\n```\nAnswer first with `Valid as written.` or `Needs scope redeclared.` Then explain why in one short paragraph and show the smallest final snippet that also adds incoming relationships to `cloud.backend`.",
      "files": []
    },
    {
      "id": 22,
      "prompt": "Write a minimal `dynamic view checkout-flow` snippet that simultaneously tests three tricky points: (1) `customer -> frontend -> api` must be a single chained expression, (2) only the `frontend -> api` hop carries a body with `technology 'HTTPS'` and `navigateTo payment-detail`, and (3) `api` fans out in `parallel { ... }` to `payments`, `inventory`, and `notifications`. After the snippet, add one sentence saying why rewriting the chain as separate standalone steps would not satisfy the request.",
      "files": []
    },
    {
      "id": 23,
      "prompt": "A deployment instance `prod.eu.frontend` comes from `instanceOf frontend` and adds `#gamma`; the logical `frontend` element already has `#next`. For each filter below, answer on its own line in the form `<filter>: matches` or `<filter>: does not match`:\n- `where source.tag is #next`\n- `where source.tag is #gamma`\n- `where source.tag is #missing`\nThen add exactly one sentence stating the tag rule, including whether deployment-instance tags are cumulative, replacement-only, or isolated from the logical tags.",
      "files": []
    },
    {
      "id": 24,
      "prompt": "Assume both of these relationships already exist: `frontend -[async]-> api 'streams'` and `frontend -[sync]-> api 'streams'`. Start your answer with exactly this line: `Correct matcher: extend frontend -[async]-> api 'streams'`. Then explain why `extend frontend -> api 'streams'` is insufficient here and why `extend frontend -[sync]-> api 'streams'` targets the wrong relationship. Then provide the exact extension snippet.",
      "files": []
    },
    {
      "id": 25,
      "prompt": "I edited exactly three files in the template project: `projects/template/system-model.c4`, `projects/template/system-views.c4`, and `projects/template/likec4.config.json`. I want one syntax/semantic-only validation command from repo root, no layout drift. Put the command on the first line by itself, using repeated `--file` flags. Then say what `filteredFiles`, `filteredErrors`, and `totalErrors` each tell me. Also say what it means if `filteredFiles` comes back as `2` instead of `3`.",
      "files": []
    },
    {
      "id": 26,
      "prompt": "I need the exact reusable-predicate form for LikeC4 — not a style group, not a custom include alias. Define `core-services` in a `global { predicateGroup ... }` block so it includes `cloud.*` elements whose kind is `service` and excludes `#deprecated`. Then show one minimal view that applies it with the exact line `global predicate core-services`. Keep the answer to one DSL snippet only.",
      "files": []
    },
    {
      "id": 27,
      "prompt": "In a scoped view `view backend of cloud.backend { include * }`, choose exactly one statement and justify it in one sentence: (A) `include *` means the whole recursive subtree of `cloud.backend`, (B) `include *` means `cloud.backend` plus its direct children as the base include set, or (C) `include *` means the whole model. Start your answer with exactly `B` if that is the right choice. Then give one minimal snippet that keeps `include *` and adds only incoming relationships around `cloud.backend`.",
      "files": []
    },
    {
      "id": 28,
      "prompt": "Assume these two relationships already exist: `frontend -[async]-> api 'streams'` and `frontend -> api 'streams'`. Start your answer with exactly `Wrong: extend frontend -> api 'streams'`. Then explain in one short paragraph why omitting the kind is wrong here, and finish with the exact `extend frontend -[async]-> api 'streams' { metadata { qos 'high' } }` snippet.",
      "files": []
    },
    {
      "id": 29,
      "prompt": "Choose exactly one valid option and start your answer with only `A`, `B`, `C`, or `D` on the first line. Requirement: keep `customer -> frontend -> api` as one chained dynamic expression, attach a body only to the `frontend -> api` hop, then keep a parallel fan-out from `api`. Options: (A) `customer -> frontend -> api { technology 'HTTPS' navigateTo payment-detail }` then `parallel { api -> payments; api -> inventory; api -> notifications }`; (B) `customer -> frontend { technology 'HTTPS' } -> api` then `parallel { ... }`; (C) `customer -> frontend -> api` and separately `frontend -> api { technology 'HTTPS' navigateTo payment-detail }`; (D) `customer -> frontend; frontend -> api { technology 'HTTPS' navigateTo payment-detail }` then `parallel { ... }`. After the first-line letter, add one sentence only explaining why the others violate the chained-hop requirement.",
      "files": []
    },
    {
      "id": 30,
      "prompt": "Assume logical `frontend` has tags `#next` and `#web`. Deployment has two instances: `prod.frontend = instanceOf frontend` with extra tag `#gamma`, and `canary.frontend = instanceOf frontend` with extra tag `#canary`. For each filter below, answer exactly in this format: `<filter> => prod:<match|no> canary:<match|no>` on its own line. Filters: `where source.tag is #next`, `where source.tag is #web`, `where source.tag is #gamma`, `where source.tag is #canary`, `where source.tag is #missing`. Then add exactly one sentence that explicitly uses the word `cumulative` to state the deployment-instance tag rule.",
      "files": []
    },
    {
      "id": 31,
      "prompt": "Assume existing relationships: `api -[async]-> service 'GetData'`, `api -[sync]-> service 'GetData'`, and `api -[async]-> service 'PostData'`. Classify each matcher as `correct`, `ambiguous`, or `wrong` (one line each): (1) `extend api -[async]-> service 'GetData' { metadata { timeout '5s' } }`; (2) `extend api -[async]-> service { metadata { timeout '5s' } }`; (3) `extend api -> service 'GetData' { metadata { timeout '5s' } }`. After classification lines, provide the single exact unambiguous extension snippet.",
      "files": []
    }
  ]
}


path: evals/grading-spec.json
content: {
  "skill_name": "likec4-dsl",
  "evals": [
    {
      "id": 0,
      "expected_output": "The response gives the focused `likec4 validate` command with `--json`, `--no-layout`, `--file`, and the correct project path, then explains how to interpret `filteredFiles` and `filteredErrors` versus `totalErrors`.",
      "files": [],
      "expectations": [
        "The response uses `npx likec4 validate --json --no-layout --file projects/template/system-model.c4 projects/template` or an equivalent command with the same flags and project path; version pins such as `npx likec4@latest validate` are also accepted; platform-specific redirects like `2>/dev/null` are optional.",
        "The response explains that `--no-layout` skips layout drift checks.",
        "The response explains that `--file` scopes reported errors to the edited file.",
        "The response mentions `filteredFiles` and `filteredErrors` as the key fields for the targeted file check.",
        "The response distinguishes those filtered fields from `totalErrors` or other project-wide counts."
      ],
      "grading_guidance": "Accept any reasonable version pin in the command (`npx likec4@latest`, `npx likec4@X.Y.Z`, or bare `npx likec4`). Never require `2>/dev/null` or other platform-specific redirections. The semantic invariants — `--json`, `--no-layout`, `--file <path>`, correct project path, and accurate interpretation of `filteredFiles`/`filteredErrors`/`totalErrors` — must all be present for full credit."
    },
    {
      "id": 1,
      "expected_output": "A minimal JSON config with `$schema`, `name`, and `include.paths` for `../shared`, plus a correct explanation that the nearest config file in the directory hierarchy determines project scope.",
      "files": [],
      "expectations": [
        "The response includes a JSON config snippet, not just prose.",
        "The snippet includes `$schema` pointing to the LikeC4 config schema.",
        "The snippet includes a valid `name` field.",
        "The snippet uses `include.paths` with `../shared` or an equivalent relative path to the shared folder.",
        "The explanation says that `.c4` files belong to the project defined by the nearest config file in the directory hierarchy."
      ]
    },
    {
      "id": 2,
      "expected_output": "The response gives the `export png` CLI command with dark theme, flat output, a filter for `overview*`, an output directory, and the project path placeholder or path.",
      "files": [],
      "expectations": [
        "The response uses `npx likec4 export png`.",
        "The command includes `--theme dark`.",
        "The command includes `--flat`.",
        "The command includes a filter option equivalent to `-f \"overview*\"`.",
        "The command includes an output directory option equivalent to `-o ./images` and keeps a project path argument."
      ]
    },
    {
      "id": 3,
      "expected_output": "A paste-ready `dynamic view` snippet that uses `variant sequence`, forward steps from `client` to `db`, and backward response arrows back toward `client`.",
      "files": [],
      "expectations": [
        "The response uses a `dynamic view` block.",
        "The snippet includes `variant sequence`.",
        "The snippet models the forward flow across `client`, `gateway`, `orders`, and `db`.",
        "The snippet includes at least one backward arrow using `<-` for responses.",
        "The response is primarily a usable DSL snippet, not only an explanation."
      ]
    },
    {
      "id": 4,
      "expected_output": "The response keeps the styling in the view, not the model or specification, and provides a minimal view snippet that mutes everything then highlights `cloud.backend.*`.",
      "files": [],
      "expectations": [
        "The response explicitly says the styling should live in the view rather than in the model or specification for this one-view customization.",
        "The response uses a `view` block.",
        "The snippet includes `include *` or an equivalent rule that gives the view context.",
        "The snippet includes a style rule that mutes the broader set, such as `style * { color muted }`.",
        "The snippet includes a style rule that highlights `cloud.backend.*`."
      ]
    },
    {
      "id": 5,
      "expected_output": "A minimal `deployment` snippet with one VM node that contains two separately named `instanceOf cloud.api` declarations, not two anonymous `instanceOf` lines.",
      "files": [],
      "expectations": [
        "The response uses a `deployment` block.",
        "The snippet includes a `vm` deployment node.",
        "The snippet creates two separately named instances inside the same node.",
        "Each named instance uses `instanceOf cloud.api`.",
        "The response does not treat two anonymous `instanceOf cloud.api` lines as satisfying the request."
      ],
      "grading_guidance": "This eval is primarily about named deployment instances inside one node. If the answer uses anonymous instances or leaves the naming ambiguity unresolved, it should lose clearly even if the surrounding deployment block is otherwise valid. Do not over-weight extra explanation once the naming requirement is either satisfied or violated. Note: `instanceOf` is a DSL keyword, not a `deploymentNode` kind — the structural snippet checker may incorrectly flag `instanceOf` as an 'Unknown LikeC4 kind'; this is a checker limitation and should not count as a content error."
    },
    {
      "id": 6,
      "expected_output": "The response selects `cloud.backend._` (underscore) as the correct predicate, provides a minimal scoped view snippet using it, and explains that `*` selects all direct children unconditionally and `**` selects all recursive descendants that have relationships.",
      "files": [],
      "expectations": [
        "The response identifies `cloud.backend._` (underscore) as the correct predicate for children with relationships to accumulated result.",
        "The response explains that `cloud.backend.*` selects ALL direct children regardless of whether they have relationships.",
        "The response explains that `cloud.backend.**` selects all recursive descendants (not just direct children) that have relationships.",
        "The response provides a minimal view snippet using `cloud.backend._` inside a scoped `view ... of cloud.backend { ... }` block.",
        "The response does not confuse `_` with a wildcard or treat it as selecting no elements."
      ]
    },
    {
      "id": 7,
      "expected_output": "A `detail` view using `extends backend-overview`, with a bare `include api` (not full FQN) that resolves to `cloud.backend.api` due to inherited scope, and a relationship predicate for incoming relationships such as `include -> cloud.backend`.",
      "files": [],
      "expectations": [
        "The response uses `view detail extends backend-overview { ... }` syntax.",
        "The snippet uses `include api` without the full FQN `cloud.backend.api`, relying on scope inheritance.",
        "The response explains that extended views inherit the `of` scope from the parent view.",
        "The snippet includes an inbound relationship predicate such as `include -> cloud.backend` or `include -> cloud.backend ->` to pull in incoming relationships.",
        "The response does not require the user to redeclare the `of cloud.backend` scope on the child view."
      ]
    },
    {
      "id": 8,
      "expected_output": "A `global { predicateGroup core-services { ... } }` block with include/exclude rules for service kind and #deprecated tag, then two views using `global predicate core-services` each with a distinct additional rule.",
      "files": [],
      "expectations": [
        "The response uses a `global { predicateGroup core-services { ... } }` block at the top level.",
        "The predicate group contains `include cloud.* where kind is service` (or equivalent).",
        "The predicate group excludes deprecated elements using `exclude * where tag is #deprecated` or a combined `and tag is not #deprecated` filter.",
        "Both views use `global predicate core-services` to apply the shared group.",
        "Each view demonstrates an additional distinct rule: one adds a `style` rule and the other adds an `include` rule."
      ],
      "grading_guidance": "This is a contrastive syntax eval. The exact reusable-predicate mechanism matters: prefer answers that literally use `global { predicateGroup ... }` and `global predicate core-services`, and penalize substitutions such as style groups, prose-only explanations, or other reusable constructs even if they look conceptually adjacent. Accept `include -> cloud.* ->` as valid — it is the `-> expr ->` predicate that means 'relationships between elements matching expr and the accumulated result'. The structural snippet checker may flag `*` after `->` as an 'Unknown relationship kind'; this is a checker false positive. Grade on semantic correctness of the predicate, not on structural-checker output."
    },
    {
      "id": 9,
      "expected_output": "A `dynamic view checkout-flow` using chained arrow syntax for the three-step chain, a body block on the `frontend -> api` step with `technology` and `navigateTo`, and a `parallel { ... }` block for the fan-out from `api`.",
      "files": [],
      "expectations": [
        "The response uses a `dynamic view checkout-flow { ... }` block.",
        "The chain `customer -> frontend -> api` is written as a single chained expression (arrows on the same or continuation lines), not as three separate standalone `->` lines.",
        "The `frontend -> api` step includes a body block `{ technology 'HTTPS'  navigateTo payment-detail }` (or equivalent).",
        "The snippet includes a `parallel { ... }` (or `par { ... }`) block containing three concurrent steps: `api -> payments`, `api -> inventory`, `api -> notifications`.",
        "The response is primarily a usable DSL snippet, not only explanation."
      ]
    },
    {
      "id": 10,
      "expected_output": "The response provides one minimal paste-ready `.c4` fixture that proves cumulative deployment-instance tag filtering: logical `frontend` has `#next`, deployed `prod.eu.web.frontend` adds `#gamma`, the logical relation is `frontend -> db 'reads'`, and the three deployment views `rel_only_next`, `rel_only_gamma`, and `rel_only_missing` use relationship-only `include ... where source.tag is ...` predicates such that the first two can render the relation and the third is empty.",
      "files": [],
      "expectations": [
        "The response includes a valid top-level `specification`, `model`, `deployment`, and `views` structure in one `.c4` snippet.",
        "The logical model tags `frontend` with `#next` and defines a logical `frontend -> db 'reads'` relationship.",
        "The deployment model creates a deployed `frontend` instance under `prod.eu.web.frontend` (or equivalent nested FQN) and adds `#gamma` on the `instanceOf` block.",
        "The snippet defines exactly the three deployment views `rel_only_next`, `rel_only_gamma`, and `rel_only_missing`.",
        "Each of those views uses a relationship-only include with `where source.tag is #next`, `#gamma`, and `#missing` respectively, with the intended semantic outcome that the first two match and the last one renders empty."
      ],
      "grading_guidance": "This eval replaces the old duplicate knowledge question with an executable fixture-building task. Prefer concise snippets that make the cumulative-tag rule mechanically testable; do not require extra prose if the DSL is clear and consistent.",
      "execution_checks": [
        {
          "name": "Validate the full LikeC4 fixture when present",
          "description": "Use the LikeC4 validator as extra evidence when the response contains a single paste-ready `.c4` fixture rather than only prose fragments.",
          "when": "Run this when the answer includes one main LikeC4 code block that appears intended to be the requested complete file.",
          "instructions": [
            "Extract the main LikeC4 code block from the response.",
            "Create a temporary LikeC4 project directory in the workspace and, if needed, add the minimal config required for isolated validation.",
            "Save the extracted snippet as a `.c4` file and validate it with the LikeC4 CLI using JSON output and no layout checks.",
            "Treat validator errors as strong negative evidence against claims that the fixture is paste-ready or semantically correct."
          ],
          "success_signals": [
            "The validator reports zero syntax or semantic errors for the extracted file.",
            "The validated file still exhibits the intended cumulative-tag behavior described by the expectations."
          ],
          "failure_signals": [
            "The validator reports parse, semantic, or unresolved-reference errors.",
            "The file structure prevents the three requested deployment views from expressing the intended tag-filter outcomes."
          ]
        }
      ]
    },
    {
      "id": 11,
      "expected_output": "The correct `ops.c4` snippet uses `extend cloud.api { metadata { port '9090'; region 'us-east-1' } health = component 'Health Check' }`, and the response states that `port` becomes the array `['8080', '9090']` because duplicate metadata keys are merged into arrays instead of being overwritten.",
      "files": [],
      "expectations": [
        "The response shows a correct `extend cloud.api { ... }` block (not a re-declaration of `cloud.api`).",
        "The `extend` block contains `metadata { port '9090'; region 'us-east-1' }` inside it.",
        "The `extend` block also declares the nested `health = component 'Health Check'`.",
        "The response explicitly states that `port` ends up as an array `['8080', '9090']` (or equivalent notation).",
        "The response explains WHY: duplicate metadata keys are merged into arrays rather than overwriting."
      ],
      "grading_guidance": "Treat any answer claiming that `port` is overwritten to a single scalar value as incorrect, even if the extend block itself is otherwise valid."
    },
    {
      "id": 12,
      "expected_output": "The response states that deployment views do not support customize predicates (`with { ... }`) and do not support `global style ...`, and if it proposes local styling it clearly presents that as a separate supported deployment-view construct rather than as `with { ... }` or `global style`. It then provides a minimal valid deployment view snippet using only supported syntax.",
      "files": [],
      "expectations": [
        "The response explicitly says `include * with { ... }` is not supported in deployment views.",
        "The response explicitly says `global style ...` is not supported in deployment views.",
        "The response still provides a valid `deployment view` snippet.",
        "The snippet uses only supported deployment-view rules.",
        "If the answer uses a local `style` rule, it clearly distinguishes that supported local rule from unsupported `with { ... }` and unsupported `global style ...`.",
        "The response distinguishes deployment-view limitations from element-view capabilities."
      ],
      "grading_guidance": "Do not penalize an answer merely for using a valid local deployment-view `style` rule such as `style * { color red }`, as long as it explicitly says this is a separate supported construct and does not falsely present `include * with { ... }` or `global style ...` as supported. The main failure cases are recommending unsupported syntax or overstating deployment-view parity with element views.",
      "execution_checks": [
        {
          "name": "Validate the corrected deployment-view snippet when feasible",
          "description": "When the response gives a concrete deployment-view snippet, use a tiny temporary harness to verify that the contested constructs are treated correctly by the validator.",
          "when": "Run this when the answer includes a concrete deployment-view snippet that can be wrapped in a minimal LikeC4 file without guessing away the core syntax being evaluated.",
          "instructions": [
            "Extract the deployment-view snippet from the response.",
            "Wrap it in a minimal temporary LikeC4 project containing just enough specification, model, deployment, and views structure for validation.",
            "Validate the wrapped file with the LikeC4 CLI using JSON output and no layout checks.",
            "If the proposed snippet still relies on `with { ... }` or `global style ...`, treat the resulting validator failure as decisive evidence against correctness."
          ],
          "success_signals": [
            "The wrapped snippet validates successfully.",
            "The snippet avoids unsupported `with { ... }` and `global style ...` deployment-view syntax."
          ],
          "failure_signals": [
            "Validation fails because the answer preserved unsupported deployment-view styling syntax.",
            "The answer claims deployment-view support that the validated snippet does not demonstrate."
          ]
        }
      ]
    },
    {
      "id": 13,
      "expected_output": "The response fixes ordering in the element body by placing tags before properties, then explains that tags must precede properties in block bodies.",
      "files": [],
      "expectations": [
        "The corrected snippet keeps the same element intent (`api = service 'API'`).",
        "The corrected snippet places `#critical` before `technology 'Node.js'`.",
        "The response explicitly explains the ordering rule: tags come before properties.",
        "The response does not remove the tag or technology field as a workaround.",
        "The corrected snippet remains minimal and syntactically valid LikeC4 DSL."
      ]
    },
    {
      "id": 14,
      "expected_output": "The response says `styles { ... }` is not an allowed top-level block and replaces it with valid top-level statements, typically using `global { styleGroup ... }` and/or `views { ... }`.",
      "files": [],
      "expectations": [
        "The response identifies that `styles` is an invalid top-level statement.",
        "The response mentions allowed top-level statements (`import`, `specification`, `model`, `deployment`, `views`, `global`).",
        "The corrected file uses only allowed top-level statements.",
        "The corrected DSL demonstrates styling intent via valid constructs (e.g., `global styleGroup` and applying in `views`).",
        "The output is a minimal valid LikeC4 file, not only prose."
      ]
    },
    {
      "id": 15,
      "expected_output": "The response marks `payment.api` and `1backend` invalid, marks `payment_api` and `payment-api` valid, and rewrites invalid identifiers into valid forms without dots or leading digits.",
      "files": [],
      "expectations": [
        "The response states `payment.api` is invalid because dots are reserved for FQNs.",
        "The response states `1backend` is invalid because identifiers cannot start with a digit.",
        "The response states `payment_api` is valid.",
        "The response states `payment-api` is valid.",
        "The response provides corrected alternatives for invalid identifiers preserving meaning (e.g., `payment_api`, `backend1`)."
      ]
    },
    {
      "id": 16,
      "expected_output": "The response says parent-child relationships are invalid, removes `cloud -> backend` relationship, and provides a corrected pattern that preserves hierarchy and adds a valid relationship between non-parent/child elements.",
      "files": [],
      "expectations": [
        "The response starts with `Invalid.` exactly.",
        "The response explicitly identifies `cloud -> backend` as invalid parent-child relationship.",
        "The corrected snippet preserves the hierarchical nesting of `backend` inside `cloud`.",
        "The corrected snippet demonstrates a valid relationship between non-parent-child elements.",
        "The response does not claim the original relation is valid with a different label.",
        "The corrected output is a minimal, usable DSL snippet."
      ],
      "grading_guidance": "Treat the exact opening verdict `Invalid.` and the explicit sentence that containment is modeled by nesting, not by a relationship, as primary signals. Answers that hedge on validity, skip the exact verdict, or preserve a parent-child relationship should lose clearly even if the replacement snippet is otherwise plausible."
    },
    {
      "id": 17,
      "expected_output": "The response explains that cross-file references to nested elements require FQNs and rewrites the relationship using full element paths.",
      "files": [],
      "expectations": [
        "The response explains why `backend.api` fails across files (lexical scope and unresolved local reference).",
        "The response states that cross-file nested references must use FQNs.",
        "The corrected relationship uses full FQNs (e.g., `cloud.backend.api -> cloud.db`).",
        "The response does not suggest importing symbols as a substitute for FQNs in this case.",
        "The answer remains focused on reference resolution and corrected DSL."
      ],
      "grading_guidance": "Answers that name FQNs in prose but provide a code snippet that still uses unresolved local references (e.g., `backend.api`) should receive at most partial credit. The corrected snippet itself must contain the correct full FQN form. Reject answers that suggest `import` statements as an alternative fix; partial fixes that avoid naming both sides as FQNs also receive reduced credit."
    },
    {
      "id": 18,
      "expected_output": "The response explains that relationship extension must match source, target, title, and kind; it rejects `extend frontend -> api 'streams'` for the async relationship here because omitting the kind is wrong for this disambiguation case, and provides the correct `extend frontend -[async]-> api 'streams' { ... }` snippet.",
      "files": [],
      "expectations": [
        "The response states that `extend` for relationships must match source and target.",
        "The response states that matching also includes title and kind for disambiguation.",
        "The response identifies `extend frontend -> api 'streams'` as incorrect for a relation originally declared with kind `async`.",
        "The corrected snippet includes the relationship kind in the `extend` matcher.",
        "The corrected snippet adds metadata within the `extend` block."
      ],
      "grading_guidance": "Do not reward answers that hand-wave the missing kind as 'probably okay'. In this eval, the whole point is exact relationship identity matching under a real ambiguity. Prefer answers that explicitly say omitting the kind is wrong here, not merely ambiguous in the abstract."
    },
    {
      "id": 19,
      "expected_output": "The response explains that scoped `include *` does not include the whole model: it includes the scoped element and its direct children as the base include, and neighboring elements / derived relationships may also become visible because of those included elements under scoped-view semantics. It then shows predicates for incoming/outgoing relationships around `cloud.backend`.",
      "files": [],
      "expectations": [
        "The response explicitly says scoped `*` does NOT include the whole model.",
        "The response explains that in a scoped view the base include is the scoped element plus its direct children.",
        "The response explains that neighboring elements and/or derived relationships can also appear because of the scoped include semantics.",
        "The snippet uses `view ... of cloud.backend` with `include *`.",
        "The snippet adds relationship predicates for incoming/outgoing around `cloud.backend` (e.g., `include -> cloud.backend ->`).",
        "The output includes a minimal usable DSL snippet, not prose-only explanation."
      ],
      "grading_guidance": "Do not over-credit answers that reduce scoped `include *` to only the local subtree, and do not accept `the whole model` either. The key concept is: scoped element plus direct children (NOT all recursive descendants, NOT the entire model) as the base include, with neighboring or derived visibility emerging from those included nodes under scoped semantics. Prefer answers that explicitly use the phrase `direct children`. Penalize any answer that says `*` includes elements deeper than direct children, or that uses 'subtree' without qualifying it as 'direct children only'. The snippet relationship predicates for incoming/outgoing around `cloud.backend` are also required; accept both `include -> cloud.backend ->` and the split form `include * -> cloud.backend` + `include cloud.backend -> *`."
    },
    {
      "id": 20,
      "expected_output": "The response provides a `likec4 validate` command with `--json`, `--no-layout`, and repeated `--file` for both edited files, then explains checking `filteredFiles` and `filteredErrors` to confirm filter scope.",
      "files": [],
      "expectations": [
        "The command uses `npx likec4 validate --json --no-layout`.",
        "The command passes two `--file` arguments, one for each edited file.",
        "The command includes the project path argument (e.g., `projects/template`).",
        "The response explains that `filteredFiles` should equal 2 to confirm both files were filtered.",
        "The response explains interpreting `filteredErrors` versus project-wide counts like `totalErrors`."
      ],
      "grading_guidance": "Accept any reasonable version pin (`npx likec4@latest`, version-pinned, or bare `npx likec4`). The two `--file` flags, correct project path, and the `filteredFiles = 2` verification explanation are the strict semantic invariants; argument order is flexible."
    },
    {
      "id": 21,
      "expected_output": "The response starts with `Valid as written.`, explains that `extends backend-overview` inherits the parent `of cloud.backend` scope so `include api` resolves within that scope, and shows a minimal final snippet that also pulls incoming relationships to `cloud.backend`.",
      "files": [],
      "expectations": [
        "The response starts with `Valid as written.`.",
        "The response explains that the child view inherits the parent `of cloud.backend` scope.",
        "The final snippet keeps `extends backend-overview` without redeclaring `of cloud.backend`.",
        "The final snippet uses bare `include api` rather than `include cloud.backend.api`.",
        "The final snippet adds an incoming relationship predicate for `cloud.backend`."
      ],
      "grading_guidance": "This eval is contrastive: answers that redeclare the scope or claim redeclaration is required should lose clearly, even if the rest of the snippet is plausible. Items 1–2 (binary verdict `Valid as written.` and scope-inheritance explanation) are the primary grading signals and account for roughly 60% of the score. Missing the exact opening phrase should noticeably reduce score even if the later explanation is correct. Items 3–5 (snippet correctness) are secondary completeness checks. Eval 21 is a validation task; eval 7 is the complementary construction task — assess each against its own primary objective."
    },
    {
      "id": 22,
      "expected_output": "A minimal `dynamic view checkout-flow` snippet with `customer -> frontend -> api` as one chained expression, a body only on the `frontend -> api` hop containing `technology 'HTTPS'` and `navigateTo payment-detail`, a `parallel { ... }` fan-out from `api`, plus one sentence explaining that separate standalone steps would not preserve the requested chained-step structure.",
      "files": [],
      "expectations": [
        "The response uses a `dynamic view checkout-flow { ... }` block.",
        "The `customer -> frontend -> api` portion is written as a single chained expression (possibly split across continuation lines) rather than three standalone top-level steps.",
        "Only the `frontend -> api` hop carries the body block with `technology 'HTTPS'` and `navigateTo payment-detail`.",
        "The snippet includes a `parallel { ... }` (or `par { ... }`) fan-out from `api` to `payments`, `inventory`, and `notifications`.",
        "The explanation sentence says why separate standalone steps would not satisfy the requested chained-step form."
      ],
      "grading_guidance": "Penalize answers that flatten the chain into standalone top-level steps. Multi-line chain continuations (a single compound expression split across lines) are accepted. Both `par { }` and `parallel { }` are syntactically equivalent and both accepted. This eval is about exact dynamic-step structure, not topology, snippet length, or surface formatting. Note: the structural snippet checker may flag relationship step labels (e.g., `'charge'`, `'reserve'`) as 'Unknown relationship kind'; this is a checker false positive since step labels are valid in dynamic view syntax. Do not penalize a response solely due to structural-checker errors that arise from step label parsing."
    },
    {
      "id": 23,
      "expected_output": "The response says `#next` matches, `#gamma` matches, `#missing` does not match, and states in one clear sentence that deployment-instance tags are cumulative: inherited logical-model tags remain visible and directly added instance tags are added on top.",
      "files": [],
      "expectations": [
        "The response says the `#next` filter matches.",
        "The response says the `#gamma` filter matches.",
        "The response says the `#missing` filter does not match.",
        "The response explains that logical-model tags remain visible on the deployment instance.",
        "The response explicitly states that deployment-instance tags are cumulative rather than replacement-only or isolated."
      ],
      "grading_guidance": "Grade this mechanically. The three filter verdicts and the cumulative-tag rule are the primary signals; do not over-weight presentation flourish once those concrete semantics are correct. Missing the `#missing` negative case or avoiding the cumulative-vs-replace distinction should still reduce confidence noticeably."
    },
    {
      "id": 24,
      "expected_output": "The response identifies `extend frontend -[async]-> api 'streams'` as the correct matcher, explains that the unkinded matcher is insufficient here and that the sync matcher targets the wrong relationship, then provides the exact async extension snippet.",
      "files": [],
      "expectations": [
        "The response identifies `extend frontend -[async]-> api 'streams'` as the correct matcher.",
        "The response explains that `extend frontend -> api 'streams'` is not the right matcher in this ambiguity case.",
        "The response explains that `extend frontend -[sync]-> api 'streams'` would target the wrong relationship.",
        "The final snippet uses the async matcher exactly.",
        "The final snippet adds metadata within the `extend` block."
      ],
      "grading_guidance": "Treat exact matcher selection as the primary grading signal. Prefer answers that begin with the exact required matcher line when the prompt asks for it. Answers that fail to explicitly reject `extend frontend -> api 'streams'` as ambiguous or insufficient in this context lose points, even if they eventually provide the correct async matcher. Do not let extra rhetorical explanation outweigh a wrong matcher choice."
    },
    {
      "id": 25,
      "expected_output": "The response provides a `likec4 validate` command with `--json`, `--no-layout`, and three repeated `--file` flags for the edited template files, explains the roles of `filteredFiles`, `filteredErrors`, and `totalErrors`, and states that `filteredFiles = 2` means one intended file was not actually included in the filter set.",
      "files": [],
      "expectations": [
        "The command uses `npx likec4 validate --json --no-layout`.",
        "The command passes three `--file` arguments, one per edited file.",
        "The command includes the template project path argument.",
        "The response explains `filteredFiles`, `filteredErrors`, and `totalErrors` distinctly.",
        "The response explains that `filteredFiles = 2` means one of the intended files was not actually filtered by the command."
      ],
      "grading_guidance": "Do not give full credit to answers that only restate the command. This eval checks partial filter coverage interpretation: `filteredFiles = 2` means one of the three intended files was not captured, and the response must state this explicitly. Prefer answers that put the command on the first line by itself when the prompt requires it. Accept any reasonable version pin (`npx likec4@latest`, `npx likec4@X.Y.Z`, or bare `npx likec4`). The semantic invariants — three `--file` flags, correct project path, accurate distinction of all three JSON fields, and the `filteredFiles = 2` interpretation — are strict and non-negotiable."
    },
    {
      "id": 26,
      "expected_output": "A single DSL snippet that defines `core-services` using `global { predicateGroup ... }` and then applies it in one view with the exact line `global predicate core-services`.",
      "files": [],
      "expectations": [
        "The response contains one DSL snippet only.",
        "The snippet uses `global { predicateGroup core-services { ... } }` exactly as the reusable mechanism.",
        "The predicate group includes `cloud.*` elements whose kind is `service`.",
        "The predicate group excludes elements tagged `#deprecated`.",
        "The view applies the reusable predicate with the exact line `global predicate core-services`."
      ],
      "grading_guidance": "This is a sharp contrastive eval. Do not give full credit to answers that substitute style groups, aliases, prose descriptions, or any other reusable mechanism. Exact keyword fidelity (`predicateGroup`, `global predicate`) is the primary signal."
    },
    {
      "id": 27,
      "expected_output": "The response starts with `B`, explicitly identifies scoped `include *` as the scoped element plus its direct children as the base include set, and gives a minimal snippet that keeps `include *` while adding incoming relationships around `cloud.backend`.",
      "files": [],
      "expectations": [
        "The response starts with `B` exactly.",
        "The justification states that the base include set is the scoped element plus its direct children.",
        "The answer rejects both the recursive-subtree interpretation and the whole-model interpretation.",
        "The snippet keeps `include *` inside `view ... of cloud.backend { ... }`.",
        "The snippet adds only incoming relationships around `cloud.backend`."
      ],
      "grading_guidance": "Treat the exact initial choice `B` and the phrase `direct children` as primary signals. Reject answers that blur choice B with a full subtree interpretation even if the rest of the prose sounds knowledgeable."
    },
    {
      "id": 28,
      "expected_output": "The response starts with `Wrong: extend frontend -> api 'streams'`, explains that omitting the relationship kind is wrong under this ambiguity, and ends with the exact async extension snippet including metadata.",
      "files": [],
      "expectations": [
        "The response starts with `Wrong: extend frontend -> api 'streams'` exactly.",
        "The explanation says omitting the kind is wrong here because multiple relationships could match.",
        "The explanation stays focused on relationship identity matching rather than unrelated syntax issues.",
        "The final snippet is exactly `extend frontend -[async]-> api 'streams' { metadata { qos 'high' } }` or a formatting-equivalent multi-line form.",
        "The answer does not present the unkinded matcher as acceptable."
      ],
      "grading_guidance": "This eval is about explicit rejection of the near-miss matcher. The exact opening line and the exact async extension snippet are the decisive signals; do not over-credit generic ambiguity talk if those are missing."
    },
    {
      "id": 29,
      "expected_output": "The response selects only option `A`, places only `A`/`B`/`C`/`D` on the first line, and gives one sentence explaining that the others break chained-hop body semantics.",
      "files": [],
      "expectations": [
        "The first line is exactly one letter among `A`, `B`, `C`, or `D`.",
        "The selected option is `A`.",
        "The explanation is exactly one sentence after the first line.",
        "The explanation mentions why non-`A` options violate chained-hop/body placement constraints.",
        "The response does not include extra snippets or alternative rewrites."
      ],
      "grading_guidance": "This is a strict-format discriminator. The first-line token and option choice dominate scoring. Any first-line mismatch or selecting non-`A` should lose heavily, even if surrounding prose is generally knowledgeable."
    },
    {
      "id": 30,
      "expected_output": "The response outputs five required lines in the exact `<filter> => prod:<match|no> canary:<match|no>` format with correct match matrix (`#next` and `#web` match both, `#gamma` only prod, `#canary` only canary, `#missing` neither), followed by exactly one sentence explicitly using the word `cumulative`.",
      "files": [],
      "expectations": [
        "The response includes one line for each required filter: `#next`, `#web`, `#gamma`, `#canary`, `#missing`.",
        "`#next` line marks `prod:match` and `canary:match`.",
        "`#web` line marks `prod:match` and `canary:match`.",
        "`#gamma` line marks `prod:match` and `canary:no`, and `#canary` line marks `prod:no` and `canary:match`.",
        "`#missing` line marks `prod:no` and `canary:no`.",
        "The final rule sentence contains the word `cumulative` and states the inherited-logical-plus-instance-tag behavior."
      ],
      "grading_guidance": "Grade mechanically by the matrix and format contract. Missing one filter line, swapping prod/canary outcomes, or omitting the word `cumulative` in the final sentence should materially reduce score."
    },
    {
      "id": 31,
      "expected_output": "The response classifies (1) as `correct`, (2) as `ambiguous`, and (3) as `wrong`, then provides the exact unambiguous extension snippet `extend api -[async]-> service 'GetData' { metadata { timeout '5s' } }` (format-equivalent multi-line accepted).",
      "files": [],
      "expectations": [
        "Classification line for matcher (1) marks it `correct`.",
        "Classification line for matcher (2) marks it `ambiguous` because title is omitted while multiple async relationships exist.",
        "Classification line for matcher (3) marks it `wrong` because kind is omitted while typed alternatives exist.",
        "The final snippet targets async + exact title `GetData`.",
        "The final snippet includes metadata field `timeout '5s'`."
      ],
      "grading_guidance": "Prioritize matcher-identity reasoning (source/target/kind/title). Answers that call (2) fully correct or call (3) acceptable should lose clearly, even if they provide a plausible final snippet."
    }
  ],
  "default_execution_checks": [
    {
      "name": "Validate executable LikeC4 snippet when response is runnable",
      "description": "Provide objective evidence by validating the answer with LikeC4 when the response includes a coherent runnable snippet or fixture.",
      "when": "Run this when the response contains one main LikeC4 code block that can be validated with minimal wrapping and without inventing task semantics.",
      "instructions": [
        "Extract the main LikeC4 snippet from the response.",
        "Create a temporary isolated LikeC4 project and add minimal surrounding structure only when necessary for syntactic validation.",
        "Validate with the LikeC4 CLI in JSON mode and with layout checks disabled.",
        "Use validator output as additional evidence for pass/fail decisions, while still grading task semantics from expectations."
      ],
      "success_signals": [
        "The snippet validates without syntax or semantic errors.",
        "Validated output is consistent with the eval's requested LikeC4 construct."
      ],
      "failure_signals": [
        "Validation fails with parse, semantic, or unresolved-reference errors.",
        "The snippet cannot be made runnable without rewriting core logic claimed by the response."
      ]
    },
    {
      "name": "Penalize prose-only answers on snippet-first prompts",
      "description": "When the prompt explicitly requires a command-first, snippet-first, paste-ready, one-snippet, or exact first-line answer, treat prose-only or prose-first outputs as a meaningful failure.",
      "when": "Run this when the prompt asks for an exact command, a minimal paste-ready snippet, one DSL snippet only, or a strict first-line token/verdict/letter.",
      "instructions": [
        "Check whether the answer delivers the required command/snippet/token as the first meaningful content instead of leading with explanatory prose.",
        "If the prompt requires one snippet only or a command on the first line, treat prose-first structure as negative evidence even when later content is knowledgeable.",
        "If the prompt asks for a strict one-line token or exact opening phrase, verify that contract before considering the rest of the answer."
      ],
      "success_signals": [
        "The first meaningful content is the requested command, snippet, or exact verdict token.",
        "The answer stays snippet-first or command-first when the prompt explicitly requires it."
      ],
      "failure_signals": [
        "The answer starts with explanatory prose when the prompt requires command-first or snippet-first output.",
        "The answer is prose-only even though the prompt requires a concrete snippet, command, or exact opening token."
      ]
    }
  ],
  "artifact_type": "grading-spec",
  "schema_version": 2
}


path: references/bridge-leanix-drawio.md
content: # LeanIX bridge, Draw.io profile, and agent boundaries

This reference is for tasks that touch **LeanIX**, **Draw.io export**, or **bridge artifacts**. It complements `cli.md` and the main skill rules.

## Canonical source of truth

- **LikeC4 DSL** (`.c4` / `.likec4`) is canonical. The bridge derives LeanIX-shaped inventory and Draw.io annotations from the resolved model.
- **Agent Skills** teach DSL syntax and CLI contracts; they **do not** replace running `likec4 gen leanix …`, `likec4 sync leanix …`, or `likec4 export drawio --profile leanix`.

## CLI commands (first-class)

From the project root (see `@likec4/leanix-bridge` README for details):

| Goal                              | Command                                                                  |
| --------------------------------- | ------------------------------------------------------------------------ |
| Manifest + dry-run + report       | `likec4 gen leanix dry-run -o out/bridge`                                |
| Sync workflow (dry-run / plan)    | `likec4 sync leanix --dry-run -o out/bridge`                             |
| Apply sync to LeanIX API          | `likec4 sync leanix --apply -o out/bridge` (requires `LEANIX_API_TOKEN`) |
| Draw.io with bridge-managed cells | `likec4 export drawio --profile leanix -o ./diagrams`                    |

**Draw.io default profile** (`default`): no `bridgeManaged` / `likec4Id` in styles.

**Draw.io LeanIX profile** (`leanix`): adds `bridgeManaged=true`, `likec4Id`, `likec4Kind`, `likec4ViewId`, optional `likec4ProjectId` on vertices; `likec4RelationId` on edges — for round-trip and LeanIX alignment.

Other useful flags: `likec4 export drawio --roundtrip` (embed layout in DSL comments), `--all-in-one`, `--uncompressed`.

## Round-trip mental model

1. **Export** Draw.io with `--profile leanix` so cells carry stable LikeC4 identities.
2. **Parse** Draw.io back to DSL (`likec4` / generators): `likec4Id` on vertices and `likec4RelationId` on edges preserve FQN and relationship identity where the parser supports them (see `packages/generators` Draw.io tests).
3. **After LeanIX sync**, `manifestToDrawioLeanixMapping(manifest)` maps `likec4Id` ↔ LeanIX fact sheet / relation ids for re-export or tooling.

Do not invent bridge JSON shapes; generate them via the CLI or `@likec4/leanix-bridge` APIs documented in the package README.

## Mapping config (YAML / JSON)

Custom **LeanIX mapping** merges over defaults (`factSheetTypes`, `relationTypes`, `metadataToFields`). Invalid shapes (arrays instead of objects, non-string values, unknown top-level keys) are rejected with explicit errors when the config is normalized via `mergeWithDefault` / validation in `@likec4/leanix-bridge`.

## MCP vs bridge

- **MCP** (`likec4 mcp`, `@likec4/mcp`) exposes **read/query** tools over the LikeC4 workspace model (elements, views, relationships). It does **not** replace `likec4 gen leanix` or `likec4 sync leanix`.
- For LeanIX artifacts, Draw.io leanix profile, or manifest dry-run, use the **CLI** (or programmatic `@likec4/leanix-bridge`) as documented above.


path: references/cli.md
content: # CLI Reference

`likec4` is npm package that provides a CLI tool for working with LikeC4 models.
Only essential commands/parameters are listed here, for full documentation use `likec4 help`, `likec4 <command> --help`.
Examples use `bunx` to run the CLI, but you should use workspace's package manager (e.g. `bun`, `pnpm`, `npm`).
If workspace is not a npm project, use `bunx` (if available) -> `pnpx` (if available) -> `npx` as a fallback.

If workspace already has `likec4` as a dependency, check its version from package.json, make sure it is at least 1.53.0. Pin the version `bunx likec4@1.53.0 ...` otherwise.

## Common Commands and Frequent Mistakes

### ✅ Correct commands (use these)

| Task              | Correct Command                                                       |
| ----------------- | --------------------------------------------------------------------- |
| Validate files    | `bunx likec4 validate --json --no-layout --file <file> [project-dir]` |
| Start dev server  | `bunx likec4 serve [project-dir]`                                     |
| Export PNG        | `bunx likec4 export png -o ./images [project-dir]`                    |
| Build static site | `bunx likec4 build -o ./dist [project-dir]`                           |
| List icons        | `bunx likec4 list-icons` or `bunx likec4 list-icons --group tech`     |

### ❌ Common mistakes (avoid these)

| Incorrect                                  | Why it fails                              | Correct                                  |
| ------------------------------------------ | ----------------------------------------- | ---------------------------------------- |
| `bunx likec4 check ...`                    | Command doesn't exist                     | Use `bunx likec4 validate ...`           |
| `bunx likec4 lint ...`                     | Command doesn't exist                     | Use `bunx likec4 validate ...`           |
| `bunx likec4 verify ...`                   | Command doesn't exist                     | Use `bunx likec4 validate ...`           |
| `bunx likec4 export png --out-dir ./images` | Unknown flag (`--out-dir`)                | Use `-o ./images` or `--outdir ./images` |

## `serve` (aliases: `start`, `dev`)

Starts local server with live reload to preview diagrams (default port is 5173).

```bash
bunx likec4 serve [project-dir]
bunx likec4 serve --port 3000 [project-dir]
```

When started, you can show the diagram to user in the browser by following the URL displayed in the console.
To navigate to specific view, use the URL path `/view/<view-id>`.

## `build` (alias: `bundle`)

Build a static website for deployment.

```bash
bunx likec4 build -o ./dist [project-dir]
```

## `export`

Export diagrams to various formats.

```bash
# PNG (requires Playwright)
bunx likec4 export png -o ./images [project-dir]
bunx likec4 export png --theme dark --flat -f "overview*" -o ./images [project-dir]

# JSON model
bunx likec4 export json -o model.json --pretty --skip-layout [project-dir]

# DrawIO
bunx likec4 export drawio --all-in-one -o ./diagrams [project-dir]
```

**export png** options: `--outdir` (`-o`), `--theme` [light|dark], `--flat`, `--filter` (`-f`, glob patterns), `--seq` (sequence layout for dynamic views), `--timeout` (default 15s)
**export json** options: `--outfile` (`-o`, default "likec4.json"), `--pretty`, `--skip-layout`
**export drawio** options: `--outdir` (`-o`), `--all-in-one`, `--roundtrip`, `--uncompressed`, `--profile` [default|leanix]

### LeanIX bridge and Draw.io (LeanIX profile)

Use these when the task is **LeanIX inventory**, **bridge artifacts**, or **Draw.io with stable bridge-managed ids** — not for generic DSL editing alone.

| Task                                           | Command                                                                  |
| ---------------------------------------------- | ------------------------------------------------------------------------ |
| Manifest + LeanIX dry-run + report             | `bunx likec4 gen leanix dry-run -o out/bridge [project-dir]`             |
| Sync workflow (review / apply)                 | `bunx likec4 sync leanix --dry-run -o out/bridge [project-dir]` / `bunx likec4 sync leanix --apply -o out/bridge [project-dir]` |
| Draw.io with `likec4Id`, `bridgeManaged`, etc. | `bunx likec4 export drawio --profile leanix -o ./diagrams [project-dir]` |

Full boundaries, round-trip notes, and MCP vs bridge: **`references/bridge-leanix-drawio.md`**.

## `codegen` (aliases: `gen`, `generate`)

Generate code artifacts from the model.

```bash
# TypeScript model (typed, with all views and elements)
bunx likec4 gen model -o likec4-model.ts [project-dir]

# React component
bunx likec4 gen react -o dist/likec4-views.mjs [project-dir]

# Web component JS bundle
bunx likec4 gen webcomponent -o likec4.js -w c4 [project-dir]

# Diagram formats
bunx likec4 gen mermaid -o ./out      # .mmd files
bunx likec4 gen plantuml -o ./out     # .puml files
bunx likec4 gen d2 -o ./out           # .d2 files
bunx likec4 gen dot -o ./out          # .dot files (Graphviz)
```

Shared options: `--outfile`/`--outdir` (`-o`), `--project` (`-p`), `--use-dot`

## `mcp`

Start MCP (Model Context Protocol) server for AI tool integration.

```bash
bunx likec4 mcp [workspace]                # stdio transport (default)
bunx likec4 mcp --http [workspace]         # HTTP transport on port 33335
bunx likec4 mcp -p 1234 [workspace]        # HTTP transport on custom port
```

Options: `--stdio` (default), `--http`, `--port` (`-p`, default 33335), `--use-dot`

## `list-icons`

List all available built-in icons. Fast, no workspace initialization needed.

```bash
bunx likec4 list-icons                        # all icons, one group:name per line
bunx likec4 list-icons --format json          # grouped JSON object
bunx likec4 list-icons --group aws            # only AWS icons
bunx likec4 list-icons --group tech -f json   # tech icons as JSON
```

Options: `--format` (`-f`, `text` default or `json`), `--group` (`-g`, one of: `aws`, `azure`, `gcp`, `tech`, `bootstrap`)

Icon groups: `aws` (~307 icons), `azure` (~614), `gcp` (~216), `tech` (~2000), `bootstrap` (~2051).

## `format`

Format LikeC4 source files in-place.

```bash
bunx likec4 format [workspace]
```


path: references/configuration.md
content: # Project Configuration Reference

LikeC4 projects are defined by a config file. The file's location determines project scope — all `.c4` files in the directory (and subdirectories) belong to that project.

## Config File Names

LikeC4 recognizes (in any order):

| Format     | File names                                               |
| ---------- | -------------------------------------------------------- |
| JSON/JSON5 | `.likec4rc`, `.likec4.config.json`, `likec4.config.json` |
| JavaScript | `likec4.config.js`, `likec4.config.mjs`                  |
| TypeScript | `likec4.config.ts`, `likec4.config.mts`                  |

## JSON Config Schema

Always include `$schema` for validation and autocomplete:

```json
{
  "$schema": "https://likec4.dev/schemas/config.json",
  "name": "my-project"
}
```

## All Options

### `name` (required)

Unique project identifier. Must not be `"default"`. Cannot contain `.`, `@`, or `#`.

```json
{ "name": "cloud-platform" }
```

### `title`

Human-readable project title.

```json
{ "name": "cloud-platform", "title": "Cloud Platform Architecture" }
```

### `metadata`

Arbitrary key-value pairs for custom project information.

```json
{
  "metadata": {
    "owner": "platform-team",
    "domain": "payments",
    "version": "2.0"
  }
}
```

### `contactPerson`

Person involved in creating or maintaining the project.

```json
{ "contactPerson": "Jane Doe" }
```

### `include`

Reference external directories containing `.c4` files.

```json
{
  "include": {
    "paths": ["../shared", "../common/specs"],
    "maxDepth": 5,
    "fileThreshold": 50
  }
}
```

| Property        | Type       | Default    | Description                            |
| --------------- | ---------- | ---------- | -------------------------------------- |
| `paths`         | `string[]` | (required) | Relative directory paths to scan       |
| `maxDepth`      | `number`   | `3`        | Directory scan depth (1–20)            |
| `fileThreshold` | `number`   | `30`       | Warn if loaded file count exceeds this |

### `exclude`

Glob patterns (picomatch) to exclude files. Default: `["**/node_modules/**"]`.

```json
{ "exclude": ["**/node_modules/**", "**/generated/**"] }
```

### `inferTechnologyFromIcon`

Auto-derive `technology` from icon name when not set explicitly. Applies to `aws:`, `azure:`, `gcp:`, `tech:` icons. Default: `true`.

```json
{ "inferTechnologyFromIcon": false }
```

### `implicitViews`

Auto-generate scoped views for elements without explicit views, enabling drill-down navigation. Default: `false`.

```json
{ "implicitViews": true }
```

### `imageAliases`

Shortcuts for image directory paths. Default alias `@` points to `./images`.

```json
{
  "imageAliases": {
    "@": "./images",
    "@shared": "../../shared-images"
  }
}
```

### `manualLayouts`

Configure where manual layout data is stored.

```json
{
  "manualLayouts": {
    "outDir": ".likec4"
  }
}
```

`outDir` is relative to the config file location. Default: `".likec4"`.

### `styles`

Theme customization and default styling.

```json
{
  "styles": {
    "theme": {
      "colors": {
        "primary": "#FF6B6B",
        "secondary": "rgba(37,99,235,1)"
      }
    },
    "defaults": {
      "border": "dashed",
      "opacity": 100,
      "size": "md",
      "relationship": {
        "color": "gray",
        "line": "dashed"
      }
    }
  }
}
```

### `extends`

Inherit styles from other config files (JSON only). Single path or array.

```json
{ "extends": "../shared/likec4.config.json" }
{ "extends": ["../shared/base.json", "../shared/theme.json"] }
```

### `landingPage`

Configure the landing page of the generated site.

Redirect to index view:

```json
{ "landingPage": { "redirect": true } }
```

Show only specific views:

```json
{ "landingPage": { "include": ["overview", "cloud-detail"] } }
```

Hide specific views:

```json
{ "landingPage": { "exclude": ["internal-debug"] } }
```

### `generators` (TypeScript/JS config only)

Custom generators that produce output from the model.

```typescript
import { defineConfig } from 'likec4'

export default defineConfig({
  name: 'my-project',
  generators: {
    'my-gen': async ({ likec4model, ctx }) => {
      const elements = likec4model.elements()
      await ctx.write({
        path: 'output.json',
        content: JSON.stringify(elements, null, 2),
      })
    },
  },
})
```

Run with: `likec4 gen my-gen`

## Multi-Project Setup

Each config file in the workspace defines a separate project. Files belong to the project of the nearest config file in the directory hierarchy.

```
workspace/
├─ project-a/
│  ├─ likec4.config.json    ← project "a"
│  ├─ model.c4
│  └─ views.c4
├─ project-b/
│  ├─ likec4.config.json    ← project "b"
│  └─ model.c4
└─ shared/
   └─ common.c4             ← included via "include.paths"
```

Use `include.paths` to share `.c4` files across projects.

## Minimal Starter Config

```json
{
  "$schema": "https://likec4.dev/schemas/config.json",
  "name": "my-project",
  "title": "My Architecture"
}
```

**Important:** Always include `"$schema"` (recommended) — it enables IDE autocomplete and validation for your config file.

### Common Mistake: Missing $schema

```json
// ❌ Missing $schema — no IDE validation/autocomplete
{
  "name": "my-project"
}

// ✅ Correct — with schema for IDE support
{
  "$schema": "https://likec4.dev/schemas/config.json",
  "name": "my-project"
}
```


path: references/deployment.md
content: # Deployment (LikeC4 DSL)

The `deployment` block maps logical model elements to physical infrastructure nodes using `instanceOf`. It uses `deploymentNode` kinds from the specification.

**Key rules:**
- Deployment inherits ALL relationships from the logical model automatically.
- Additional deployment-level relationships can be defined inline (same syntax as in model).
- Use named instances (`id = instanceOf ELEMENT`) when multiple instances of the same element exist within the same deployment node.
- Anonymous `instanceOf ELEMENT` (no name) is fine when there is only one instance per node.

## Syntax

```likec4
deployment {
  IDENTIFIER = DEPLOYMENT_KIND {
    TAGS
    PROPERTIES

    // Anonymous instance — fine when there is only one instance per node
    instanceOf ELEMENT_ID

    // Named instance — required when same element appears multiple times in the same node
    IDENTIFIER = instanceOf ELEMENT_ID {
      TAGS
      PROPERTIES
    }
  }
}
```

## Basic Example

```likec4
specification {
  element webapp
  deploymentNode vm
}
model {
  webapp myapp
}
deployment {
  vm vm1 {
    instanceOf myapp           // anonymous: single instance
  }
  vm vm2 {
    // Named: two replicas of the same logical element in one node
    instance1 = instanceOf myapp
    instance2 = instanceOf myapp
  }
}
```

## Multi-Environment Pattern

```likec4
specification {
  deploymentNode environment { notation "Environment"; style { color gray } }
  deploymentNode zone         { notation "Network Zone" }
  deploymentNode vm
}

deployment {
  environment prod {
    zone AppTier {
      vm appVm {
        primary   = instanceOf cloud.api
        secondary = instanceOf cloud.api  // named: two replicas
      }
    }
    zone DataTier {
      vm dbVm { instanceOf cloud.db }
    }
  }
  environment staging {
    vm stagingApp { instanceOf cloud.api }
    vm stagingDb  { instanceOf cloud.db }
  }
}
```

## Deployment Relationships

Additional relationships can be defined between deployment nodes or named instances:

```likec4
deployment {
  environment prod {
    zone AppTier {
      vm appVm {
        primary = instanceOf cloud.api
      }
    }
    zone DataTier {
      vm dbVm { instanceOf cloud.db }
    }
    // Deployment-level relationship not in the logical model
    AppTier -> DataTier "internal traffic" { technology "TCP/5432" }
  }
}
```

## Named vs. Anonymous: When It Matters

| Scenario | Use |
|---|---|
| Single instance of element in node | Anonymous: `instanceOf cloud.api` |
| Multiple instances of same element in same node | Named: `primary = instanceOf cloud.api` |
| Strict eval requires named instance identifier | Named: `IDENTIFIER = instanceOf ELEMENT` |
| Deployment view needs to distinguish replicas | Named: each gets a unique node in the diagram |


path: references/dynamic-views.md
content: # Dynamic Views — Flow & Sequence Diagrams

Dynamic views model temporal interactions and flows between elements. They render as animated flow diagrams or (optionally) UML sequence diagrams.

## Syntax Overview

```likec4
views {
  dynamic view name {
    variant sequence  // optional: render as UML sequence diagram

    title "Flow title"
    description "Flow description"
    
    SOURCE -> TARGET "step title"
    SOURCE <- TARGET "return flow"
    
    // grouped parallel actions
    parallel {
      SOURCE_1 -> TARGET_1 "parallel action 1"
      SOURCE_2 -> TARGET_2 "parallel action 2"
    }
  }
}
```

## Basic Steps

### Forward step

```likec4
dynamic view checkout-flow {
  customer -> frontend "opens cart"
  frontend -> backend "requests checkout"
  backend -> payment-service "initiates payment"
  payment-service -> bank "authorizes card"
}
```

- Renders as directed arrow from source to target.
- Title appears on the arrow/step.

### Return step (response arrow)

```likec4
dynamic view checkout-flow {
  customer -> frontend "opens cart"
  frontend -> backend "requests checkout"
  backend <- payment-service "payment result"  // Return flow
}
```

- `<-` denotes response/return flow.
- Renders as dotted or dashed arrow depending on theme.
- Semantically indicates flow **back** to the source.

### Chained steps

```likec4
dynamic view multi-hop {
  customer -> frontend "request"
    -> backend "forwards"
    -> db "query"
}
```

Keep the chain as one compound expression when the prompt explicitly asks for chained syntax.

### Hop-local body (exactness for evals)

```likec4
dynamic view checkout-flow {
  customer -> frontend
    -> api {
      technology 'HTTPS'
      navigateTo payment-detail
    }
}
```

Attach the body only to the requested hop. Do not move the block onto the whole chain unless the prompt allows it.

## Parallel Blocks

Group simultaneous/independent actions in one `parallel { ... }` block:

```likec4
dynamic view fan-out {
  backend -> cache "write to cache"
  parallel {
    backend -> db "save record"
    backend -> audit-log "log event"
    backend -> notification-service "send notification"
  }
}
```

- All actions inside `parallel { ... }` are considered concurrent.
- Renders with time-aligned horizontal layout.
- Use for fan-outs: one source to multiple targets.
- Do **not** nest `parallel` blocks; flatten all concurrent actions.

## Step Properties (Body)

Attach a body block `{ ... }` to a step for additional metadata:

```likec4
dynamic view with-notes {
  customer -> frontend "view product" {
    title "View Product Detail"
    technology "HTTPS"
    description "Customer opens product page"
  }
  
  frontend -> backend "fetch product data" {
    notes """
      Includes:
      - Product info
      - Pricing
      - Available inventory
    """
  }

  backend -> db "query" {
    metadata {
      latency "50ms"
      cached false
    }
  }
}
```

**Available properties inside step body:**
- `title` — alternative or longer title
- `technology` — technology/protocol used
- `description` — detailed description
- `notes` — markdown-formatted notes/commentary
- `metadata` — key-value pairs for custom data

## Navigation & Drill-down

Link to another view from a step:

```likec4
dynamic view high-level {
  customer -> frontend "browse"
  frontend -> backend "request data" {
    navigateTo data-fetch-details  // Link to another view
  }
}

dynamic view data-fetch-details {
  // Detailed flow of the "data-fetch" step
}
```

- `navigateTo <view-name>` — renders as a clickable link to drill down.
- Use for progressive disclosure: high-level flows → detailed sub-flows.

## Variant: Sequence Diagram

Render the dynamic view as a UML-style sequence diagram:

```likec4
dynamic view checkout-sequence {
  variant sequence  // Switch to sequence diagram rendering
  
  customer -> frontend "click checkout"
  frontend -> backend "POST /checkout"
  backend -> payment-service "charge card"
  payment-service <- bank "authorization"
  backend <- payment-service "charge approved"
  frontend <- backend "200 OK"
  customer <- frontend "show confirmation"
}
```

- `variant sequence` — tells LikeC4 to render as sequence diagram.
- Timeline flows top-to-bottom (instead of left-to-right flow diagram).
- Actors (lifelines) are participants; return arrows are dashed.

### Comparing flow vs. sequence rendering

| Aspect | Flow Diagram | Sequence Diagram (variant sequence) |
|--------|--------------|-------------------------------------|
| Layout | Left-to-right or top-down flow | Top-to-bottom lifelines |
| Return arrows | Style varies | Dashed lines standard |
| Parallel feel | Horizontal alignment | Time-based with spacing |
| Best for | System interactions | Message exchange protocols |

## Response Arrow Patterns (exactness)

If the prompt asks for response arrows back out, prefer `<-` steps over inventing extra forward steps:

```likec4
dynamic view checkout-flow {
  customer -> frontend -> api
  customer <- frontend <- api  // Prefer chained <- for responses
}
```

NOT:

```likec4
dynamic view checkout-flow {
  customer -> frontend -> api
  api -> frontend "returns"  // Wrong: not a response arrow (missing symmetry)
  frontend -> customer "returns"
}
```

## Common Patterns

### Fan-out with return

```likec4
dynamic view fan-out-return {
  backend -> cache "check"
  backend -> db "if miss"
  backend <- db "result"
  backend -> client "send"
}
```

Order: send to multiple targets, then collect responses separately when they differ.

### Pipeline / staged flow

```likec4
dynamic view data-pipeline {
  source -> ingester "submit"
  ingester -> parser "parse"
  parser -> validator "validate"
  validator -> storage "store"
  validator <- storage "ack"
}
```

- Linear chain: each stage outputs to the next.
- Use for ETL/processing workflows.

### Conditional/branching (narrative)

```likec4
dynamic view payment-decision {
  customer -> frontend "enter amount"
  frontend -> backend "validate" {
    notes "If amount > limit, rejected"
  }
  
  backend -> payment-service "charge" {
    notes "Only if validation passes"
  }
  
  backend <- payment-service "result"
  frontend <- backend "response"
}
```

- LikeC4 does **not** render explicit if/then/else branches visually.
- Use `notes` on steps to document decision logic.

## Anti-Patterns to Avoid

| Anti-pattern | Problem | Solution |
|---|---|---|
| Nested `parallel { parallel { ... } }` | Syntax error; flatten as required | Put all concurrent steps in one `parallel {}` |
| Chaining inside `parallel` | Ambiguous timing | Move chains to separate sequential steps |
| Too many steps in one view | Diagram becomes unreadable | Split into sub-views with `navigateTo` |
| Using `<-` for side-by-side actions | Implies return; violates sequence semantics | Use forward `->` or group with `parallel` |
| Forgetting `variant sequence` when UML needed | Wrong rendering | Add `variant sequence` if sequence diagram required |

## Predicate Filters in Dynamic Views

Dynamic views do **not** directly support predicate filtering like element views do. Instead:

1. **Explicitly list steps** — name each source and target.
2. **Use tags/metadata for filtering decisions** — in notes or documentation.
3. **Create separate flows** for different subsets of elements.

```likec4
dynamic view critical-flow {
  // Only include critical services (documented in spec)
  frontend -> api "request"
  api -> db "query"
}

dynamic view with-cache {
  // Alternative flow with cache layer
  frontend -> cache "check"
  cache -> backend "if miss"
}
```

## Reference and Examples

Full LikeC4 dynamic view docs: https://likec4.dev/dsl/views/dynamic/

Common scenarios:
- **Authentication flow** — customer → login → auth-service → database
- **CQRS pattern** — command → service → write-db (parallel: query-handler → read-db)
- **Webhook callback** — external-system → api (parallel within with navigateTo service-webhook-handler)
- **Pub/Sub flow** — publisher → message-bus → consumer (with parallel for multiple subscribers)

When the prompt asks for one parallel fan-out, keep sibling actions inside one `parallel { ... }` block. Do not split the three steps into separate one-step blocks.

### Sequence variant

```likec4
dynamic view checkout-flow {
  variant sequence
  customer -> frontend -> api
  customer <- frontend <- api
}
```

Use `variant sequence` when the prompt explicitly asks for UML-style sequence rendering.

## Quick anti-patterns

- Rewriting a requested chain as separate top-level steps
- Using forward arrows where the prompt explicitly asks for response arrows back out
- Spreading one requested parallel fan-out across multiple `parallel` blocks
- Omitting required hop-local tokens such as `technology` or `navigateTo`

path: references/examples.md
content: # Examples

Compact, real-world patterns. Each example demonstrates multiple features.

## Extend Element & Metadata Merge

```likec4
// base.c4
model {
  cloud = system "Cloud" {
    api = service "API" {
      metadata { owner "team-a"; port "8080" }
    }
  }
}

// ops.c4 — extend adds nested elements, merges metadata (duplicate keys become arrays)
model {
  extend cloud.api {
    #monitored
    metadata { port "9090"; region "us-east-1" }
    // Result: port becomes ["8080", "9090"]

    health = component "Health Check" { technology "HTTP" }
  }
}
```

## Extend Relationship

```likec4
specification {
  relationship async { color amber; line dotted }
}
model {
  frontend -> api "requests"
  frontend -[async]-> api "streams"   // different relation (kind distinguishes)

  // Extend adds metadata/tags to existing relation (must match source, target, title, kind)
  extend frontend -> api "requests" {
    metadata { latency_p95 "150ms" }
  }
}
```

## View Extends (Inheritance)

```likec4
views {
  view overview {
    include *
    style * { color muted }
  }
  view detail extends overview {
    title "More detail"
    include cloud.backend.*          // adds to parent's includes
    style cloud.backend.* { color primary }
  }
  view deep extends detail {         // cascade inheritance
    include cloud.backend.api.*
  }
}
```

## Scoped View

```likec4
views {
  // "of" scopes the view — `*` means the scoped element + direct children
  view backend of cloud.backend {
    include *
    include -> cloud.backend ->      // incoming/outgoing relations

    style cloud.backend { color primary }
    style cloud.backend.* { color secondary }
  }
}
```

## Groups in Views

```likec4
views {
  view grouped {
    group "Internal" {
      color primary
      opacity 20%
      include cloud.*
    }
    group "External" {
      color amber
      include customer, partner
    }
    // Unnamed group
    group {
      include monitoring.*
    }
  }
}
```

## Global Style & Predicate Groups

```likec4
global {
  styleGroup theme {
    style element.tag = #deprecated { color muted; opacity 20% }
    style element.tag = #critical { color red }
  }
  predicateGroup core_services {
    include cloud.* where kind is service
    exclude * where tag is #deprecated
  }
}
views {
  global style theme             // apply to all views in block

  view services {
    global predicate core_services
    include * -> cloud.*         // add relations to included elements
  }
}
```

## Dynamic View — Parallel, Notes, NavigateTo

```likec4
dynamic view checkout {
  title "Checkout Flow"

  customer -> frontend "places order" {
    notes '''
      **Entry point**: customer submits cart
    '''
  }
  frontend
    -> api "POST /checkout"
    -> validator "validate cart"     // chained syntax

  parallel {
    api -> payments "charge card"
    api -> inventory "reserve items"
    api -> notifications "send confirmation"
  }

  payments <- api "payment result" {
    navigateTo payment-detail        // link to another view
  }

  include cloud with { opacity 10%; color gray }
  style customer { color green }
  autoLayout TopBottom
}
```

## Deployment — Multi-Environment, InstanceOf

```likec4
specification {
  deploymentNode environment { style { color gray } }
  deploymentNode region
  deploymentNode vm
}
deployment {
  environment prod "Production" {
    technology "OpenTofu"

    region eu {
      vm server1 {
        app = instanceOf cloud.api       // named instance
        instanceOf cloud.ui              // anonymous instance
      }
      vm server2 {
        db = instanceOf cloud.db {
          title "Primary DB"
          technology "PostgreSQL 16"
        }
      }
    }
    region us {
      vm server3 {
        db = instanceOf cloud.db "Replica DB"
      }
      // Deployment-specific relation (replication)
      server3.db -> eu.server2.db "replicates" {
        metadata { lag "100ms"; mode "async" }
      }
    }
  }
}
views {
  deployment view prod_deploy {
    title "Production"
    include prod.**
    style eu._ { color primary }
    style us._ { color secondary }
  }
}
```

## Rank — Layout Control

```likec4
views {
  view ranked {
    include A, B, C, D, E, F

    rank same { A, B }       // same vertical level
    rank source { C, D }     // force to top
    rank max { F }           // force to bottom
  }
}
```

## Where Predicates — Filtering

```likec4
views {
  view filtered {
    // By tag
    include cloud.* where tag is #production

    // By kind + negated tag
    include cloud.* where kind is service and tag is not #deprecated

    // By metadata
    include cloud.* where metadata.region is "eu"

    // Relationship filtering
    include cloud.* -> amazon.* where source.tag is #critical

    // Wildcard with expansion
    include cloud._                  // direct children only
    include cloud.**                 // all descendants
  }
}
```

## Relationship Kinds & Styling

```likec4
specification {
  relationship async { color amber; line dotted; head diamond; tail vee }
  relationship sync  { color primary; line solid }
}
model {
  api -[async]-> queue "publishes" {
    technology "Kafka"
    metadata { format "CloudEvents" }
  }
  api .sync -> cache "reads"          // alternative syntax: .KIND ->

  // Inline style override
  api -> db "writes" {
    style { color red; line dashed; head odiamond }
  }
}
```

## Complete Mini-Project

```likec4
specification {
  element actor   { style { shape person } }
  element system  { style { shape rectangle } }
  element service { style { shape component } }
  element webapp  { style { shape browser } }
  element db      { style { shape storage } }

  tag deprecated
  tag critical

  relationship async { color amber; line dotted }
  deploymentNode env
  deploymentNode vm
}

model {
  customer = actor "Customer"

  cloud = system "Cloud" {
    ui = webapp "Frontend" { icon tech:react }
    api = service "API" {
      #critical
      technology "Node.js"
      icon tech:nodejs
    }
    db = db "Database" {
      icon tech:postgresql
      description '''
        Primary PostgreSQL database.
        Handles all transactional data.
      '''
    }
    api -> db "reads/writes"
    ui -> api "calls" { technology "HTTPS" }
  }

  customer -> cloud.ui "browses" {
    navigateTo user-flow
    metadata { protocol "HTTPS" }
  }
}

deployment {
  env prod {
    vm web { instanceOf cloud.ui; instanceOf cloud.api }
    vm data { instanceOf cloud.db }
    web -> data "internal network"
  }
}

views {
  view index {
    include *
    style cloud { color primary }
    style customer { color green }
  }

  view backend of cloud {
    include *
    autoLayout LeftRight
  }

  dynamic view user-flow {
    customer -> cloud.ui "opens app"
    cloud.ui -> cloud.api "fetches data"
    cloud.api -> cloud.db "queries"
    cloud.api -> cloud.ui "returns"

    style cloud { opacity 20% }
  }

  deployment view prod-deploy {
    include prod.**
  }
}
```


path: references/identifier-validity.md
content: # Identifier Validity (LikeC4 DSL)

## Valid identifier form

```
identifier = /^[a-zA-Z_][a-zA-Z0-9_-]*$/
```

- **Starts with** letter or underscore
- **Contains** letters, digits, hyphens, or underscores only
- **No dots**, no spaces, no special characters

## Valid examples

| Valid | Why |
|---|---|
| `payment-api` | hyphens allowed |
| `paymentAPI` | camelCase allowed |
| `payment_service` | underscores allowed |
| `service1` | digits allowed (not at start) |
| `_internal` | underscore at start allowed |
| `PaymentService` | PascalCase allowed |

## Invalid examples

| Invalid | Why | Correct form |
|---|---|---|
| `payment.api` | **dots are FQN separators**, not identifier chars | `payment-api` or `paymentApi` |
| `payment api` | spaces not allowed | `payment-api` |
| `1payment` | cannot start with digit | `payment1` |
| `payment-` | cannot end with hyphen | `payment` |
| `payment@api` | special chars not allowed | `payment-api` |

## Critical: dots vs. hyphens

**Dots are reserved for fully qualified names (FQN):**

```likec4
model {
  cloud.backend.payment-api   // FQN: cloud (parent) -> backend (child) -> payment-api (child identifier)
  //    ^     ^                   Dots separate hierarchy levels
  //                 |---- hyphen used in identifier name itself
}
```

**Correct identifier:** `payment-api` (with hyphen)  
**Incorrect identifier:** `payment.api` (dots are FQN syntax, not part of the name)

## Use in different contexts

| Context | Rule | Example |
|---|---|---|
| **Element name** | Must be valid identifier | `service name = api "payment api"` ✓ |
| **Tag name** | Must be valid identifier | `tag critical` ✓, `tag #critical` ✗ |
| **Relationship kind** | Must be valid identifier | `-[async]->` ✓, `-[async-queue]->` ✓ |
| **Kind name** | Must be valid identifier | `element service`, `deploymentNode vm` ✓ |
| **Metadata key** | Must be valid identifier | `metadata { api_version "1.0" }` ✓ |
| **Color name** | Must be valid identifier (or hex) | `color primary`, `color custom-blue` ✓ |

## When referencing by FQN

Once defined, elements are referenced using their fully qualified names (FQNs), which *do* use dots:

```likec4
model {
  // Definition (identifier = payment-api, no dots)
  cloud = system {
    backend = container {
      payment-api = service "Payment API"
    }
  }
}

deployment {
  vm1 {
    // Reference (FQN = cloud.backend.payment-api, dots for hierarchy)
    instanceOf cloud.backend.payment-api
  }
}
```

## Summary

| Check | Valid | Invalid |
|---|---|---|
| Identifier rule | `[a-zA-Z_][a-zA-Z0-9_-]*` | Contains dots, spaces, or special chars |
| Hyphens allowed? | **Yes** in identifiers | Not dots |
| Dots allowed? | **Only in FQNs** (for scope separation) | Never in a single identifier name |
| `payment-api` | ✓ identifier | — |
| `payment.api` | ✗ identifier, but valid as FQN if `payment` and `api` are nested parents/children | — |


path: references/include-predicates-wildcards.md
content: # Include Predicates and Wildcards in Views

## Wildcard semantics

LikeC4 uses three wildcard forms in view predicates: `*`, `_`, and `**`.

### `*` — immediate children and direct contains-relationships

```likec4
views {
  view container-overview {
    include *
  }
}
```

- Includes **direct children** of the scoped element (one level down).
- Includes **direct relationships** defined at the same scope.
- Does **not** include grandchildren or descendant chains.

### `_` — anonymous matcher (matches any element)

```likec4
views {
  view with-predicates {
    include * where kind is service
    exclude _ where tag is #deprecated
  }
}
```

- `_` matches any element in the model.
- Used in conjunction with `where` predicates to match by kind, tag, or metadata.
- Example: `exclude _ where tag is #deprecated` — exclude any element tagged deprecated.

### `**` — recursive descent (all descendants)

```likec4
views {
  view full-tree {
    include **
  }
}
```

- Includes **all descendants** recursively (grandchildren, great-grandchildren, etc.).
- **Not** the same as `include *` (which is immediate children only).
- Use when you want nested hierarchies visible in a single view.

## Scoped view base semantics

In a **scoped view** (`view name of parent { ... }`), the `include` base set has special meaning:

```likec4
views {
  view backend-overview of cloud.backend {
    include *                  // Base set: cloud.backend + its immediate children
    include -> cloud.backend   // Add: inbound relationships to the scope
    include -> *               // Add: outbound relationships from children
  }
}
```

**Key facts:**
- `include *` in a scoped view = the scoped parent + **direct children only**
- Grandchildren inside `*` context are **not** included (you'd need `include **` or explicit FQN inclusion)
- Relationship predicates like `->` and `<->` can further expand what neighbors appear

## Common filter patterns

### Show a container and its components

```likec4
views {
  view container-details of cloud.backend.api {
    include *              // api (parent) + all components
    include -> api         // Add external callers
  }
}
```

### Show descendants recursively

```likec4
views {
  view system-tree of cloud {
    include **             // All descendants of cloud (full tree)
  }
}
```

### Filter by kind

```likec4
views {
  view services-only {
    include * where kind is service
    include ** where kind is service  // All services at any depth
  }
}
```

### Filter by tag

```likec4
views {
  view critical-view {
    include * where tag is #critical
    exclude _ where tag is #deprecated
  }
}
```

## Relationship predicate expansion

In scoped views, you can expand what neighboring elements appear via relationship predicates:

```likec4
views {
  view backend-with-neighbors of cloud.backend {
    include *                // Base: backend scope + direct children
    include -> cloud.backend // Add: inbound edges from outside scope
  }
}
```

This **does not change the base set of elements**; it only **includes relationships** that end in the visible elements. Neighbors of the scope that have incoming edges *do* appear because they are needed to render those edges visually.

## Wildcard `**` vs. explicit include

### Using `**` (recursive)

```likec4
views {
  view all-elements {
    include **
  }
}
```

- Automatically includes all descendants.
- Used when hierarchy depth is unknown or variable.

### Using `*` + explicit FQNs

```likec4
views {
  view two-levels {
    include *              // Level 1
    include cloud.*        // Level 2 under cloud
  }
}
```

- More explicit; requires knowing the hierarchy.
- Useful when you want fine-grained control.

## Common mistakes

| Wrong | Right | Why |
|---|---|---|
| `include **` expecting only immediate children | `include *` | `**` is recursive; use `*` for one level |
| Forgetting to add relationship filters in scoped view | `include *` + `include -> parent` | Relationships may not auto-render without explicit inclusion |
| Assuming `include *` includes grandchildren | Use `include **` instead | `*` is immediate children only |

## Summary table

| Form | Matches | Scope context |
|---|---|---|
| `*` | Direct children + sibling relationships | One level down |
| `_` | Any element (used with `where` filters) | Matches by kind, tag, metadata |
| `**` | All descendants recursively | Any depth |
| `include -> element` | Inbound relationships to element | Shows external sources |
| `include element ->` | Outbound relationships from element | Shows targets |
| `include <-> element` | Bidirectional relationships | Shows symmetric dependencies |

**In scoped views:** `include *` establishes a base set of the scope parent + immediate children. Relationship predicates like `->` and `<->` can bring in neighboring elements needed to render those relationships.


path: references/model.md
content: # Model (LikeC4 DSL)

The `model` block defines the logical architecture: elements (systems, containers, components, actors) organized in a hierarchy, with relationships between them. Views project from this model.

**Key rules:**
- Elements MUST have a kind (from specification) and an identifier unique within their parent.
- Relationships cannot exist directly between parent and child — move them outside the parent element.
- `this` and `it` are aliases for the current element inside a nested relationship.
- Cross-file references require the full FQN (e.g. `cloud.backend.api`); short names are file-scoped.
- `extend FQN { }` adds tags, metadata, and links to an existing element without redefining it.

## Syntax

```likec4
model {
  // Elements — top-level elements are global, referenceable by ID anywhere in the project
  IDENTIFIER = KIND                         // no title, no body (title defaults to identifier)
  IDENTIFIER = KIND "title"                 // with title, without body
  KIND IDENTIFIER "title"                   // alternative: kind before identifier

  IDENTIFIER = KIND {
    TAGS                                    // optional, must come first if present
    PROPERTIES                              // optional, must come before nested elements/relationships

    IDENTIFIER = KIND "Child Title" { ... } // nested element (unlimited depth)
    KIND IDENTIFIER "Child Title"           // nested, kind-first syntax

    // Relationships inside element body (current element is implicitly SOURCE)
    SOURCE -> TARGET                        // explicit, both sides named
    -> TARGET "title"                       // implicit source (current element)
    -> TARGET "title" { TAGS; PROPERTIES }
    -[REL_KIND]-> TARGET "title"            // typed relationship
    .REL_KIND -> TARGET "title"             // alternative typed syntax
    SOURCE -> it                            // TARGET = current element (alias)
    this -> TARGET                          // SOURCE = current element (alias)
  }

  // Top-level relationships (outside element body): SOURCE is required
  SOURCE -> TARGET "title"
  SOURCE -> TARGET "title" { TAGS; PROPERTIES }
  SOURCE -[REL_KIND]-> TARGET
  SOURCE .REL_KIND TARGET

  // Extend existing element (by FQN, from any file)
  extend FQN {
    TAGS                                    // additional tags to apply
    PROPERTIES                              // only `metadata` and `link` are allowed
    NESTED_ELEMENTS | RELATIONSHIPS         // additional children or edges
  }

  // Extend existing relationship — anti-ambiguity matcher contract:
  // 1) SOURCE and TARGET always required.
  // 2) Include KIND when typed relationships exist between source+target pair.
  // 3) Include TITLE when multiple relationships share SOURCE/TARGET/KIND.
  // Omitting KIND is WRONG (not merely ambiguous) when a typed relation exists.
  extend SOURCE -> TARGET { TAGS; PROPERTIES }
  extend SOURCE -[REL_KIND]-> TARGET "title" { TAGS; PROPERTIES }
}
```

## Full Example

```likec4
model {
  customer = actor {
    title "Customer"
    summary "Consumes Cloud Services"
    description """
      User with **active** subscription
      ... detailed description
    """
  }

  cloud = system "Cloud" {
    ui = container "Frontend" {
      technology "React"
      style { shape browser }
      metadata { version "1.0.0"; owners ["Name 1", "Name 2"] }
      link https://github.com/likec4/likec4 "Repository"
      link ../relative/adr1.md

      dashboard = app "Dashboard" { icon tech:react }
    }
    backend = container "Backend" {
      api = service "API" {
        #critical
        -[sql]-> db "reads/writes"
      }
      db = database "DB" {
        style { icon tech:postgresql; shape storage }
      }
    }
    ui.dashboard -> backend.api { title "calls"; technology "HTTPS" }
  }

  customer -> cloud.ui.dashboard "browses" {
    metadata { protocol "HTTPS" }
  }
}
```

## Element Properties

| Property | Values |
|---|---|
| **title** | String, single line |
| **description** | String, prefer Markdown. If > 150 chars, also add `summary`. |
| **summary** | String, max 150 characters |
| **technology** | String, no multi-line |
| **style** | `style { ... }` — see `references/style-tokens-colors.md` |
| **icon** | Shortcut for `style { icon ... }`, takes precedence over the style block |
| **metadata** | `metadata { KEY VALUE }` — key is identifier format; value is string or array of strings |
| **link** | `link URL "Optional title"` — repeatable; URL can be relative to the document |
| **navigateTo** | ID of a dynamic view to navigate to on click |

## Relationship Properties

`title`, `description`, `technology`, `metadata`, `style`, `link`, `navigateTo`

## Extend Patterns

```likec4
// Add metadata and a link to an existing element from another file:
extend cloud.backend.api {
  metadata { team "platform"; criticality "high" }
  link ./adr-002.md "Scaling decision"
}

// Extend an untyped relationship:
extend cloud.ui.dashboard -> cloud.backend.api {
  metadata { sla "99.9%" }
}

// Extend a typed relationship — include KIND to avoid ambiguous match:
extend cloud.ui.dashboard -[http]-> cloud.backend.api "calls" {
  metadata { sla "99.9%" }
}

// Wrong: if a typed relationship exists, this silently targets the wrong relation
// extend cloud.ui.dashboard -> cloud.backend.api "calls" { ... }
```


path: references/predicates.md
content: # Predicates

Predicates are view rules that define what elements and relationships to include or exclude from a view. Predicate types:

- Wildcard predicate - used to select all elements/relationships, based on view scope
- Element predicates - used to select elements
- Relationship predicates - used to select relationships
- Filter predicates - used to apply filters to element and relationship predicates
- Custom predicates - used to override properties of elements/relationships (can be used with `include` only)'

Syntax:

```
EXPRESSION ::= WILDCARD | ELEMENT_EXPRESSION | RELATIONSHIP_EXPRESSION
FILTER_PREDICATE ::= EXPRESSION where FILTER_CONDITIONS
CUSTOMIZE_PREDICATE ::= (EXPRESSION | FILTER_PREDICATE) with { ... }
PREDICATE ::= EXPRESSION | FILTER_PREDICATE | CUSTOMIZE_PREDICATE
```

Example:

```likec4
include *                               // WILDCARD
include some.element                    // ELEMENT_EXPRESSION
include some.from -> some.to            // RELATIONSHIP_EXPRESSION
include * where tag is #production      // FILTER_PREDICATE
include some.element with { color red } // CUSTOMIZE_PREDICATE on ELEMENT_EXPRESSION
include                                 // CUSTOMIZE_PREDICATE on FILTER_PREDICATE
  some.*
  where
    tag is #production and kind is component
  with {
    color red
  }
```

## Expressions

Expressions inside `exclude` clause match against the accumulated result of previous predicates. Expressions inside `include` clause match against the accumulated result of previous predicates and the model. Element expressions select elements first, and then relationships connected to these elements. Relationship expressions select relationships first, and then elements that are connected by these relationships.

### Element expression

- `<element_ref>` - selects element by reference from the current file scope, or globally available if not found in the current file, together with all relationships between this element and accumulated result
- `<element_ref>.<child>` - selects unique child within `<element_ref>` together with all relationships between this child and accumulated result
- `<element_ref>.*` - selects **direct children only** of `<element_ref>`, together with all relationships between these children and accumulated result
- `<element_ref>._` - selects direct children of `<element_ref>` that have relationships with accumulated result
- `<element_ref>.**` - selects **all recursive descendants** of `<element_ref>` that have relationships with accumulated result

#### Wildcard depth selectors: `*` vs `**`

Understanding the difference between `*` and `**` is crucial for correct view scoping:

| Selector | Meaning | Example | Result |
|----------|---------|---------|--------|
| `*` | Direct children **only** (1 level) | `parent.*` | Selects immediate children of parent |
| `**` | All descendants (recursive, all levels) | `parent.**` | Selects children, grandchildren, and all nested elements |

```likec4
// Example model structure:
// backend
//   ├── api (service)
//   │   └── handlers (component)
//   │       └── authHandler
//   └── db (database)

views {
  // Selects ONLY: api, db (direct children of backend)
  view direct-only {
    include backend.*
  }

  // Selects: api, db, handlers, authHandler (all descendants)
  view all-descendants {
    include backend.**
  }

  // ❌ Common mistake: expecting * to include nested elements
  view wrong-expectation {
    include backend.*        // This does NOT include handlers or authHandler!
    style backend.handlers { color red }  // handlers won't be styled
  }

  // ✅ Correct: use ** when you need all nested elements
  view correct {
    include backend.**       // Includes everything under backend
    style backend.handlers { color red }  // Now handlers IS included
  }
}
```

### Wildcard expression

Wildcard expression is a special element expression.

- If used inside a scoped view, it selects the scoped element, its direct children, and all relationships with them.
- If used inside an unscoped view, it selects top-level elements and all relationships between them.

### Relationship expression

Relationship expression uses element expressions as source and target.
If expression matches, predicate adds matched relationships together with matching source and target elements.

- `<expr1> -> <expr2>` - relationships from elements selected by `expr1` to elements selected by `expr2`
- `<expr1> -> <element_ref>.*` - relationships from elements selected by `expr1` to direct children of `element_ref`
- `<expr1> <-> <expr2>` - any relationships between elements selected by `expr1` and `expr2` (both directions)
- `-> <expr>` - any relationships, from accumulated result to the elements selected by `expr`
- `<expr> ->` - any relationships, from the elements selected by `expr` to accumulated result
- `-> <expr> ->` - any relationships, between the elements selected by `expr` and accumulated result
- `* -> *` - all relationships

## Filter Conditions

After expression is evaluated and selected elements/relationships, filter conditions are applied to refine the selection.

By tag: `* where tag is #primary` or `* where tag is not #primary`
By kind: `* where kind is component` or `* where kind is not component`

Complex:

- `* where kind is component and tag is #primary`
- `* where (tag is #primary or tag is #secondary) and kind is component`

If filter applies to relationship expressions, you can filter source/target elements:

- `* -> * where tag is #http` - filters relationships by tag
- `* -> * where source.tag is #primary` - filters relationships by tag on source element
- `* -> * where target.tag is #primary` - filters relationships by tag on target element
- `* -> * where source.kind is component or target.kind is component` - filters relationships by source or target kind

## Customize Predicates

Customize predicates allow you to override properties of selected elements/relationships per view (for example, in different diagrams).
For example:

```likec4
include 
  * -> some.component.*
  where
    tag is #primary
  with {
    color red
  }
```

- Selects all relationships incoming to the children of `some.component.*`
- Filters relationships by tag `#primary`
- Overrides color of selected relationships to red


path: references/relationships-bidirectional.md
content: # Bidirectional vs. Unidirectional Relationships

## Key distinction: → vs →↔

LikeC4 distinguishes between **directed relationships** (`->`) and **bidirectional relationships** (`<->`).

### When to use `->` (unidirectional)

```likec4
model {
  frontend -> backend
  backend -> database
}
```

**Use `->` when:**
- One element sends a request or message to another *without* an explicit return path.
- Example: frontend **calls** API (backend responds, but the call is primarily one-way from frontend's perspective).
- Example: worker **processes** job from queue (job flows in one direction).
- Example: service **publishes** event to event bus (unidirectional publish).

### When to use `<->` (bidirectional)

```likec4
model {
  frontend <-> backend
  microservice1 <-> microservice2 "RPC sync"
}
```

**Use `<->` when:**
- Both elements actively communicate with each other *in both directions* as part of the same logical interaction.
- Example: client <-> server API (client sends request; server sends response; both are significant).
- Example: service A <-> service B (service A calls B *and* B calls A, not just a request-response pair).
- Example: two databases synchronized (bidirectional replication).

### When a request-response is one-way

In most REST APIs, even though the server responds, we still model it as `->` because:

```likec4
frontend -> api "REST call"
```

The **relationship itself** is directional: frontend initiates. The response is implicit in the interaction model.

**Exception:** If the prompt explicitly asks for bidirectionality or if the system model emphasizes that *both elements drive interaction*, use `<->`.

## Include predicates: `->` vs. `<->`

In scoped views, relationship inclusion predicates use the same distinction:

```likec4
views {
  view backend-detail of cloud.backend {
    include *
    include -> cloud.backend   // Incoming relationships (sources pointing TO this scope)
    include <-> cloud.backend  // Bidirectional relationships involving this scope
  }
}
```

- `-> scope` — *inbound* relationships from outside the scope pointing into it.
- `<-> scope` — relationships that are bidirectional with the scope.
- `scope ->` — *outbound* relationships from the scope pointing out.

## Summary

| Syntax | Meaning | Use case |
|---|---|---|
| `A -> B` | Unidirectional: A initiates/calls/sends to B | REST API call, event publish, job dispatch |
| `A <-> B` | Bidirectional: both actively communicate | Sync RPC, synchronized replication, mutual messaging |
| `-> X` (in view) | Inbound: relationships from outside pointing to X | Show external callers of a component |
| `<-> X` (in view) | Bidirectional: relationships where X participates both ways | Show symmetric dependencies |

**When in doubt:** use `->` for request-response patterns (REST, async jobs, events). Reserve `<->` for explicitly symmetric interactions documented in requirements.


path: references/specification.md
content: # Specification (LikeC4 DSL)

The `specification` block defines all named vocabularies for the project: element kinds, deployment node kinds, relationship kinds, tags, and custom color tokens. Every kind used in `model` or `deployment` blocks must be declared here first.

**Key rules:**
- Specification is global across all files in the project.
- Duplicate identifiers (same kind, same tag, etc.) will cause a validation error.
- Multiple `specification` blocks (in one file or across files) are allowed, but not recommended.
- Keep specification in a dedicated file, e.g. `specification.c4` — changes to specification trigger a full project re-parse, so isolating it reduces edit latency on model/view files.

## Syntax

```likec4
specification {
  // Define a tag; outside specification it is referenced as #IDENTIFIER
  tag IDENTIFIER

  // Define element kind for use in model
  element IDENTIFIER {
    #tag-1 #tag-2          // tags applied to all elements of this kind
    title "default title for this kind"
    technology "default tech for this kind"
    description "default description for this kind"
    notation "legend title for this kind"
    style { ... }          // see references/style-tokens-colors.md
  }

  // Define deployment node kind for use in deployment block
  deploymentNode IDENTIFIER {
    // same properties and styles as element kind
  }

  // Define relationship kind with default properties and styles
  relationship IDENTIFIER {
    technology "default tech for this relationship kind"
    description "default description for this relationship kind"
    style { ... }          // default style for this relationship kind
  }

  // Define a custom named color token
  color IDENTIFIER #FFFFFF  // or rgba(255,255,255,1)
}
```

## Example

```likec4
specification {
  element actor    { notation "Person";    style { shape person } }
  element service  { description "Same for all of the kind"; style { shape component } }
  element webapp   { style { shape browser } }
  element queue    { style { shape queue; color secondary } }
  element database { style { shape storage } }
  element system

  relationship async { color amber; line dotted; head diamond; tail vee }
  relationship sql   { technology "SQL"; line dashed }

  tag deprecated
  tag critical

  deploymentNode environment { notation "Environment"; style { color gray } }
  deploymentNode zone        { notation "Network Zone" }
  deploymentNode vm
}
```

## Common Mistakes

| Mistake | Fix |
|---------|-----|
| Using a kind not defined here | Define `element KIND { }` or `deploymentNode KIND { }` in specification first |
| Duplicate tag or kind identifier | Each identifier must be unique within its type category |
| `#tag` in specification argument | Tags are defined without `#`; they are used with `#` elsewhere: `tag critical` → `#critical` |
| Raw hex color in style | Define a named color token first: `color my-blue #003366`, then use `color my-blue` in styles |


path: references/style-tokens-colors.md
content: # Style Tokens and Colors (LikeC4 DSL)

## Canonical color tokens (semantic names)

LikeC4 provides a curated set of semantic color tokens. **Prefer these named tokens over raw hex colors** for consistency and automatic light/dark theme adaptation.

### Core semantic token palette

| Token       | Usage                              | Light appearance | Dark appearance |
| ----------- | ---------------------------------- | ---------------- | --------------- |
| `primary`   | Primary brand color, main emphasis | #2F80ED (blue)   | lighter blue    |
| `secondary` | Secondary accent, de-emphasis      | #7C3AED (purple) | lighter purple  |
| `muted`     | Muted text, disabled states        | #9CA3AF (gray)   | lighter gray    |
| `slate`     | Neutral backgrounds, borders       | #475569          | lighter slate   |
| `blue`      | Technical/IT systems               | #3B82F6          | lighter blue    |
| `indigo`    | Data/analytics systems             | #6366F1          | lighter indigo  |
| `sky`       | Cloud, external services           | #0EA5E9          | lighter sky     |
| `red`       | Alerts, critical systems           | #EF4444          | lighter red     |
| `gray`      | Infrastructure, generic            | #6B7280          | lighter gray    |
| `green`     | Success, operational systems       | #10B981          | lighter green   |
| `amber`     | Warnings, async/queue patterns     | #F59E0B          | lighter amber   |

## Correct usage: semantic tokens

```likec4
specification {
  element service {
    style { color primary }    // ✓ Correct: semantic token
  }
  element critical {
    style { color red }        // ✓ Correct: semantic token
  }
  element queue {
    style { color amber }      // ✓ Correct: semantic token
  }
}
```

## When hex colors are acceptable

Hex colors can be used if you define a custom named color in the specification:

```likec4
specification {
  color my-brand-blue #003366   // Define a custom named token
  
  element service {
    style { color my-brand-blue } // Reference the custom token
  }
}
```

**Do not use raw hex colors directly in styles without first defining them as named tokens in the specification.**

## What NOT to do

```likec4
style { color #FF5733 }      // ✗ Wrong: raw hex color
style { color rgb(255,87,51) } // ✗ Wrong: rgb() notation
style { color "primary" }    // ✗ Wrong: quoted string (remove quotes)
```

## Style tokens vs. theme colors

- **Semantic tokens** (`primary`, `secondary`, `muted`, etc.) automatically adapt to light/dark mode.
- **Custom named colors** defined in specification are explicit hex values; use them sparingly for brand colors.
- **Raw hex** in a style property is not recommended — always register in specification first.

## Icon packs

Icons use the format `group:name` (e.g. `tech:react`, `aws:lambda`, `azure:app-service`). Five built-in groups are available:

| Group       | Count | Examples                                       |
| ----------- | ----- | ---------------------------------------------- |
| `aws`       | ~307  | `aws:lambda`, `aws:s3`, `aws:dynamo-db`        |
| `azure`     | ~614  | `azure:app-service`, `azure:cosmos-db`         |
| `gcp`       | ~216  | `gcp:cloud-run`, `gcp:bigquery`                |
| `tech`      | ~2000 | `tech:react`, `tech:postgresql`, `tech:docker` |
| `bootstrap` | ~2051 | `bootstrap:gear`, `bootstrap:person`           |

To get the full up-to-date list, run `likec4 list-icons` or `likec4 list-icons --group tech` (see `references/cli.md`)

## Complete style example

```likec4
specification {
  color brand-orange #FF8C42     // Custom brand color
  
  element actor {
    style { 
      shape person
      color primary 
      icon tech:user
    }
  }
  
  element service {
    style {
      shape component
      color primary
      icon tech:gear
    }
  }
  
  element critical-service {
    style {
      shape component
      color red      // Critical system
      icon tech:alert
    }
  }
  
  element queue {
    style {
      shape queue
      color amber    // Async/queue pattern
    }
  }
}

model {
  customer = actor {
    style { color primary }
  }
  
  api = service {
    style { color primary }
  }
  
  alert-responder = critical-service {
    style { color red }
  }
  
  job-queue = queue {
    style { color amber }
  }
}
```

## Summary

| Use case              | Correct                                                                              | Incorrect                   |
| --------------------- | ------------------------------------------------------------------------------------ | --------------------------- |
| Brand primary color   | `style { color primary }`                                                            | `style { color "#2F80ED" }` |
| Critical system alert | `style { color red }`                                                                | `style { color "#FF0000" }` |
| Async/queue pattern   | `style { color amber }`                                                              | `style { color "#FFC107" }` |
| Custom brand color    | Define in spec + use token: `color my-brand #XXXXXX` then `style { color my-brand }` | Use raw hex in style        |
| Theme-aware styling   | Use semantic tokens (`primary`, `secondary`, etc.)                                   | Use fixed hex values        |

**Best practice:** Use semantic color tokens for all element and relationship coloring. Define custom named colors in specification only for brand compliance, never use raw hex in styles.


path: references/troubleshooting.md
content: # Common Mistakes & Debugging (LikeC4 DSL)

Load this file when encountering validation errors, unexpected rendering, or when an eval answer is failing.

## Syntax Errors

| Error | Cause | Fix |
|-------|-------|-----|
| "Identifier PAYMENT.API not found" | Dots in identifier name | Use `payment-api` not `payment.api`; dots are FQN separators only |
| "Unknown kind SERVICE" | Kind not in specification | Define `element service { ... }` in the specification block |
| "Duplicate FQN cloud.backend" | Element ID repeated under the same parent | Rename one element; each sibling must have a unique identifier |
| "Expected property TYPE after include *" | Malformed filter predicate | Use `include * where kind is component`, not `include * component` |
| "Invalid relationship kind async-cache" | Kind not found in specification | Define `relationship async-cache { ... }` in specification first |

## Model & Hierarchy

| Error | Cause | Fix |
|-------|-------|-----|
| Element shows but relationships don't render | Relationship references FQN incorrectly | Use exact FQN matching the model hierarchy |
| "Can't define relationship from parent to child" | Direct parent-child relationships are forbidden | Move the relationship outside the parent element or use implicit notation |
| Child element not visible from other files | Referencing by short name instead of FQN | Import or use full FQN: `cloud.backend.api` |
| Extend block adds duplicate tags | Tags stack on merge | Use consistent tag names; duplicates are not deduplicated automatically |

## View Predicates

| Error | Cause | Fix |
|-------|-------|-----|
| `include *` shows grandchildren | Confusing `*` with `**` | `*` = direct children only; use `**` for recursive descent |
| Relationships disappear in scoped view | Neighbors not explicitly included | Add `include -> scope` or `include <-> scope` to pull in inbound/outbound sources |
| "WHERE predicate not matching any elements" | Tag or kind name is case-sensitive | Use exact case: `#Critical` ≠ `#critical` |
| Element included but styled differently | Global vs. local style conflict | Local view styles override global; audit style rules order in the view block |

## Deployment

| Error | Cause | Fix |
|-------|-------|-----|
| `instanceOf` doesn't resolve | Instance refers to wrong FQN | Use the exact logical model FQN, not the deployment node identifier |
| "Undefined DEPLOYMENT_KIND" | Kind referenced but not in specification | Define `deploymentNode vm { ... }` in specification |
| Deployment relationship inherits unexpectedly | Logical model edges are inherited automatically | Suppress inherited relationships explicitly in the deployment view if unwanted |

## Dynamic Views

| Error | Cause | Fix |
|-------|-------|-----|
| Parallel block renders incorrectly | Nested `parallel { parallel { ... } }` | Flatten: put all concurrent steps in a single `parallel { }` block |
| Response arrows (`<-`) show wrong direction | Chaining mixes `->` and `<-` inconsistently | Use symmetric chains: `a -> b -> c` then `c <- b <- a` for returns |
| `navigateTo` link doesn't work | Target view name does not exist | Ensure the target view name exists in the same project |
| `variant sequence` is ignored | Wrong keyword or spelling | Use exact: `variant sequence` (not `type`, `mode`, or `sequence` alone) |

## Validation & Import

| Most Common | Solution |
|---|---|
| `validate` reports config not found | Ensure `likec4.config.json` exists in the project root directory |
| Imported file shows "Module not resolved" | Use correct relative path: `import { x } from './path/to/file.c4'` |
| Symbol from import invisible in model | Symbol must be public (defined at top level); nested elements need FQN |
| Large error count in project but your file is clean | Use `likec4 validate --json --no-layout --file <edited-file> <project-dir>` and check `filteredErrors`/`filteredFiles`; text mode may still print upstream diagnostics |

## Performance & Large Models

| Symptom | Cause | Action |
|---|---|---|
| Validation takes >30s | Specification changes trigger full project re-parse | Keep specification in a separate file; avoid editing it frequently |
| Export generates a partial PNG | Layout engine timeout on complex view | Split large views with `navigateTo` or reduce the element count |
| IDE responsiveness slow | Too many open files or large specification in working file | Split into `spec.c4` + `model.c4` + `views.c4` |

## Debugging Workflow

When encountering errors, follow these steps in order:

1. **Run validation with `--file` and check `filteredErrors`:**
   ```bash
   likec4 validate --json --no-layout --file <your-file> <project-dir>
   ```
   If `filteredErrors` = 0 but `totalErrors` > 0, your file is clean; the error is in an upstream file.

2. **Check FQN integrity:** Find the identifier from the error message and verify it matches the model hierarchy exactly.

3. **Isolate predicate issues:** Copy the failing `include`/`exclude` rule into a new minimal test view to confirm predicate semantics in isolation.

4. **Validate specification first:** Comment out `model`, `deployment`, and `views`; validate the `specification` block alone. If it passes, uncomment the next block and repeat.

5. **Use `extend` strategically:** When enriching elements across files, use `extend FQN { }` rather than re-declaring — re-declarations cause duplicate FQN errors.

## Skill Best Practices

1. **Always start with project structure understanding.** Use the `understand-project-structure` skill before making changes to an unfamiliar project.
2. **For relationship ambiguity, always include KIND + TITLE.** When source/target/kind match multiple relationships, include title in the matcher to avoid silently targeting the wrong one.
3. **Response discipline on strict prompts.** Output one final answer first (no alternatives) when the prompt says "exact", "minimal", or "paste-ready".
4. **Validate after each file edit.** Always run `likec4 validate --json --no-layout --file <edited-file> <project-dir>` after changes; use `--file` to focus on your changes only.
5. **Cross-file references use FQN.** Never assume short names resolve across file boundaries; they don't.
6. **Keep specification stable.** Changes invalidate the entire model parse; prefer a separate `spec.c4` file and minimize changes to it.
7. **Test wildcard semantics locally.** When unsure whether `*` or `**` is correct, create a minimal test view to confirm behavior before committing.


path: references/views.md
content: # Views

Three types of views are supported:

1. Element views - projections of the model, based on predicates
2. Dynamic views - step-by-step sequence of interactions between elements
3. Deployment views - projections of the deployment model, based on predicates

View IDENTIFIER must be unique within the project, available across all files. Duplicate identifiers will result in a validation error.
There is special view - `index`, if not defined, it will be automatically created to include all top-level elements.

Syntax:

```likec4
views {

  LOCAL_STYLE_RULES     // optional style rules, applied to all views in this block

  // element view
  view IDENTIFIER {
    TAGS                // optional tags, must come first if present, before any properties
    PROPERTIES          // optional, but must come before any view rules
    ELEMENT_VIEW_RULES    
  }
  // element view can also be scoped to a specific element, explained below
  view IDENTIFIER of ELEMENT_ID {     
    TAGS
    PROPERTIES
    ELEMENT_VIEW_RULES    
  }
  // dynamic views
  dynamic view IDENTIFIER {
    TAGS
    PROPERTIES  
    DYNAMIC_VIEW_RULES
  }
  // deployment views
  deployment view IDENTIFIER {
    TAGS
    PROPERTIES
    DEPLOYMENT_VIEW_RULES
  }
}
```

## Element View Rules

Syntax:

```likec4
include PREDICATE, PREDICATE, ...
exclude PREDICATE, PREDICATE, ...
style ELEMENT_EXPRESSION, ... {
  // Apply style properties to elements matching the expressions
}
global style STYLE_GROUP_IDENTIFIER
autoLayout TopBottom|BottomTop|LeftRight|RightLeft [rankSep] [nodeSep]
```

See [Predicates](./predicates.md) for more information on predicates and expressions.

**Important:**

- Rules order matters, as every next rule applies on top of the previous, accumulating result.
- `exclude` only removes elements that were included by previous rules.
- `style` rules override previously applied styles.
  - Style cascade (each override the previous): Spec defaults → element properties → local styles → view-level styles → customized predicates

## Dynamic View Rules

Syntax:

```text
STEP ::=
   SOURCE -> TARGET [LABEL]       // forward message
   | SOURCE <- TARGET [LABEL]     // backward message
   [{
      RELATIONSHIP_PROPERTIES
      RELATIONSHIP_STYLE_PROPERTIES
   }]


DYNAMIC_VIEW_STYLE_RULE ::=
   style EXPRESSION, ... {
      // Apply style properties to elements matching the expressions
   }


DYNAMIC_VIEW_RULES ::=
   STEP
   STEP
   DYNAMIC_VIEW_STYLE_RULE
   ...
```

## Local Style Rules

Styles placed inside `views {}` but outside any `view {}` apply to all views in that block:

```likec4
views {
  // This style applies to ALL views in this block
  style * { color green }

  view view1 {
    include *                      // All elements are green
  }
  view index {
    include *
    style backend { color red }    // All elements are green, except backend which is red
  }
}
```

## Global Style Groups

Reusable style groups defined in `global { ... }`:

Syntax:

```likec4
global {
  styleGroup GROUP_IDENTIFIER {
    style EXPRESSION { ... }
    style EXPRESSION { ... }
  }
}

views {
  view index {    
    global style GROUP_IDENTIFIER
  }
}
```

```likec4
global {
  styleGroup brandColors {
    style * { color primary }
    style element.tag = #deprecated { color muted; opacity 30% }
    style element.tag = #critical { color red; border dashed }
  }
}

views {
  view index {
    include *
    global style brandColors    // Apply the style group
  }
}
```

Style groups can contain multiple `style` rules. They are applied in the order defined within the group. When used in a view, global styles sit between local styles and view-level styles in the cascade.

# Dynamic Views — Detailed Reference

## Steps

Each step represents an interaction between two elements:

```likec4
// Forward step
customer -> frontend "opens app"

// Backward step (response/return flow)
frontend <- backend "returns data"

// Step with full properties
customer -> frontend "places order" {
  title "Customer places an order"       // Override step label
  description "Detailed description"
  technology "HTTPS"
  notes '''
    Additional notes displayed in sidebar.
    Supports **Markdown** formatting.
  '''
  color red
  navigateTo order-detail                // Link to another dynamic view
}
```

Step properties: `title`, `description`, `technology`, `notes`, `navigateTo`, all relationship properties.

### Chained Steps

Steps can be chained to reduce repetition:

```likec4
customer
  -> frontend "opens"     // Read as "customer opens frontend"
  -> backend "requests"   // Read as "frontend requests backend"
  -> database "queries"   // Read as "backend queries database"
  <- backend "responds"   // Read as "database responds to backend"
```

Each arrow in the chain creates a separate step. The target of the previous step becomes the source of the next.

## Parallel Steps

Use `parallel` (or `par`) blocks for concurrent interactions:

```likec4
dynamic view flow {
  frontend -> backend "requests data"

  parallel {
    backend -> cache "checks cache"
    backend -> database "queries DB"
    backend -> external-api "fetches enrichment"
  }

  backend -> frontend "returns aggregated data"
}
```

Parallel blocks can be nested and mixed with sequential steps.

## Variants

| Variant             | Rendering                     | Use case                           |
| ------------------- | ----------------------------- | ---------------------------------- |
| `diagram` (default) | Animated box-and-line diagram | General flow visualization         |
| `sequence`          | UML sequence diagram          | API call sequences, protocol flows |

### Using `variant sequence`

The `variant sequence` keyword renders the dynamic view as a UML sequence diagram. This is especially useful for API call sequences and protocol flows.

**Key syntax points:**
- Use `variant sequence` at the start of the dynamic view block
- Use `->` for forward/call direction
- Use `<-` for backward/return direction (not `->` with different semantics)
- Sequence diagrams work best with leaf elements (not containers)

```likec4
dynamic view api-sequence {
  variant sequence

  client -> gateway "POST /orders"
  gateway -> auth "validate token"
  auth <- gateway "200 OK"
  gateway -> orders "create order"
  orders -> db "INSERT"
  orders <- db "order_id"
  gateway <- orders "201 Created"
  client <- gateway "201 Created"
}
```

**Common mistake:** Using `->` for returns instead of `<-`. The arrow direction indicates message flow:
- `a -> b` means "a sends to b" (request/call)
- `a <- b` means "b sends to a" (response/return)

```likec4
// ❌ WRONG - using -> for returns
dynamic view wrong {
  variant sequence
  client -> gateway "request"
  gateway -> client "response"  // This renders incorrectly!
}

// ✅ CORRECT - using <- for returns
dynamic view correct {
  variant sequence
  client -> gateway "request"
  client <- gateway "response"  // Proper return flow
}
```

## Include in Dynamic Views

Dynamic views support the same predicates as element views, used to add context elements that don't participate in steps:

```likec4
dynamic view flow {
  customer -> frontend "opens"
  frontend -> backend "requests"

  // Add parent containers as visual context
  include cloud with {
    color muted
    opacity 10%
  }
  include amazon
}
```

## Styling in Dynamic Views

Same styling rules as element views:

```likec4
dynamic view flow {
  customer -> frontend "opens"
  frontend -> backend "requests"

  style customer { color green }
  style * { size sm }
  style frontend { color muted }
}
```


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)