Language reference
Use this page to look up syntax after you understand the core model. For guided decisions and realistic examples, use the design guides.
Document shape
Section titled “Document shape”A document contains one flow, state, or sequence diagram. The language-version header is optional; an omitted header selects language version 1.
kdiagram 1
diagram "System title" { // flow statements}sequence "Scenario title" { // sequence statements}state "Order lifecycle" { entry: initial "Start" pending: state "Pending payment" done: final "Completed"
entry -> pending pending -> done "authorize [approved]"}State diagrams support initial, state, final, junction, fork, and join. Kekonic Diagrams
checks that there is exactly one initial pseudostate, initial has no incoming transitions, and final
states have no outgoing transitions.
Line comments begin with //. Block comments use /* … */. Semicolons and commas may separate
properties but are not required.
Models and views (kdiagram 2, draft)
Section titled “Models and views (kdiagram 2, draft)”When several pictures share one topology (C4 context + containers, review deck + detail), elevate to
a model with embedded view lenses instead of copying files. Requires kdiagram 2.
Simple diagrams should stay as a single diagram { … } — no modeling ceremony. A standalone
diagram { … } is one-shot sugar: nodes, groups, edges, layout, and presentation live together.
kdiagram 2
model "Storefront" { customer: person "Customer" platform: system "Commerce platform" { description: "Lets customers check out and coordinates payment." } boundary commerce "Commerce platform" { web: container "Web application" api: container "API application" } stripe: external "Stripe"
view context { include customer, platform, stripe customer -> platform "Uses" platform -> stripe "Charges" layout { direction: TD } }
view containers { include customer, commerce.*, stripe customer -> web "Browses" web -> api "Places orders" api -> stripe "Charges" layout { direction: LR; groupLayout: compound } }}| Construct | Role |
|---|---|
model "Title" { … } |
Shared nodes, structural groups, and styles. No edges, layout, or presentation at this layer. |
view name { … } |
Named lens: include / exclude, edges, layout, presentation, animation, edge-route policy. |
include / exclude |
Selectors: bare id, prefix.* (group subtree or id prefix), or *. |
diagram { … } |
One-shot form — co-located nodes, groups, edges, and presentation. Default for a single picture. |
Edges are illegal in a multi-view model body (FM222). Put a -> b inside each view. Level of
detail uses explicit summary nodes in the model (for example platform: system "…" in context,
commerce.* in containers) rather than view-time collapse.
When --view or a host view is omitted, the compiler prefers a view named default, then main,
else the first view in source order.
Target a lens with kdiagrams render file.kdiagram --view context, Studio’s view picker, or
<k-diagram view="context" show-view-switcher>. One self-contained .kdiagram file per model —
there is no cross-file import in this draft.
Worked example: Storefront — shared model with views. Design notes: Architecture diagrams.
Flow diagrams
Section titled “Flow diagrams”id: kind "Visible label" { subtitle: "Secondary line" technology: "Runtime or platform" description: "Longer supporting text" note: "Compact annotation" icon: shopping-cart iconColor: #7c3aed iconPaint: theme shape: hexagon scale: 1.15 minWidth: 140 maxWidth: 260 styles: [warning]}Only the ID and kind are required. An omitted label is derived from the ID. IDs are referenced by connections and must be declared before use.
subtitle: true displays the built-in kind subtitle. A quoted subtitle replaces it with authored
text. shape changes geometry without changing semantic kind. icon: none removes a kind’s default
icon.
Built-in semantic kinds
Section titled “Built-in semantic kinds”- Architecture:
user,person,actor,participant,system,external,container,component,service,application,module,package,deployment - Infrastructure:
server,database,cache,store,bucket,queue,topic,stream,gateway,loadbalancer,cloud,firewall,zone - Messaging:
broker,event,command,message,worker,producer,consumer,dlq,job - Flow:
start,end,process,task,subprocess,choice,decision,io,document,preparation,manual,connector,success,warning,failure - Modeling:
table,entity,class,interface,aggregate,projection,policy - State and Git:
state,initial,final,junction,fork,join,commit,branch,tag - Annotation:
note,label,image,icon
C4 element kinds render with distinct type names: person (Person), system (Software
System), external (External System), container (Container), component (Component). Keep one C4
level per diagram. Turn on presentation { showKindSubtitles: true } (or subtitle: true per node)
so the type line is visible. description is the C4 body; technology is the tech tag. A database
at container level is still a container with shape: cylinder. Kekonic Diagrams does not provide a
C4 code (class) view. See Architecture diagrams.
Unknown kinds produce a warning and use generic defaults, which allows extension without a parser failure.
Geometry kinds
Section titled “Geometry kinds”Use geometry directly when meaning does not map to a semantic kind:
rectangle, rounded, pill, circle, ellipse, diamond, hexagon, triangle,
parallelogram, trapezoid, folded-document, cylinder, and boundary.
Common short aliases such as rect, diam, and hex normalize to their full shape IDs.
Connections
Section titled “Connections”source -> target "Optional label" { priority: high labelPosition: end icon: mail iconColor: #16a34a branch: yes styles: [success]}| Operator | Relationship | Reverse form |
|---|---|---|
-> |
direct or synchronous flow | <- |
=> |
asynchronous event | <= |
~> |
eventual or signal flow | <~ |
..> |
dependency | <.. |
-x |
failure or rejection | x- |
-- |
association without an arrow | — |
<-> |
bidirectional flow | — |
--> is a dashed dependency in flow diagrams and commonly a reply in sequence diagrams. Edge
chains are allowed: a -> b -> c. Properties on a chain apply to each generated edge.
Priority values are low, normal, and high. Label positions are start, middle, and end.
Branch values are yes, no, and neutral; labels such as “yes” and “no” are also recognized.
On ERD relationships, cardinality sets crow’s-foot multiplicity (1:N, 0..1:1, 1:0..N, and
similar IE forms, or Mermaid-ish ||--o{). identifying: true paints a solid identifying line;
false paints a dashed non-identifying line. Foreign-key columns usually infer both — override
only when inference is wrong. See Tables.
Groups and regions
Section titled “Groups and regions”group app "Application" { chrome: true padding: normal icon: boxes arrange: stack align: stretch gap: normal
api: gateway "API" service: service "Orders"}boundary, zone, and swimlane are group variants. Groups may contain nodes and nested groups.
Top-level swimlane groups infer groupLayout: swimlane and direction: LR (override with
groupLayout: flat if you only want membership boxes). Lane chrome uses a left header strip.
See Control layout.
Arrangement values inside a region are flow, pack, and stack. A parent containing child
regions may use stack, row, grid, or surround, with columns, rows, column, row,
span, colSpan, and rowSpan for tracks. surround places exactly one nested hub group in the
center and sibling nodes on a ring; use side: west|east|north|south on those nodes for
cardinal arcs. Optional shape: hexagon|circle|ellipse|rounded|rectangle sets group chrome
silhouette (default rectangle). chrome: false keeps a structural group in layout without painting
its border or label. See Control layout for complete patterns.
Tables
Section titled “Tables”table (and entity with columns) draws an ERD card. The structured columns { } block is the
canonical form; a columns: ["id PK uuid", …] array of compact specs is also accepted.
customers: table "customers" { note: "Account holder" columns { id: uuid PK email: varchar(320) UK NN credit_limit: numeric(10,2) default_locale: text NN // en|es }}
orders: table "orders" { columns { id: uuid PK customer_id: uuid FK NN -> customers.id billing_address_id: uuid FK NN -> addresses.id shipping_address_id: uuid FK -> addresses.id }}
order_items: table "order_items" { columns { order_id: uuid PK FK NN -> orders.id line_no: int PK NN }}
line_taxes: table "line_taxes" { columns { order_id: uuid PK FK NN -> order_items.order_id line_no: int PK FK NN -> order_items.line_no tax_code: text PK NN rate: numeric(10,2) NN }}
payments: table "payments" { columns { id: uuid PK order_id: uuid FK UK NN -> orders.id }}
// Override inference when it is wrong:customers.id -> orders.customer_id { identifying: false, cardinality: "1:N" }Column line
Section titled “Column line”name: type markers -> ref // comment
- Type is a documentation label. Parameterized forms such as
varchar(320)andnumeric(10,2)are one type; commas inside()do not start a new column. - Markers:
PK(alsoPRIMARY),FK(FOREIGN),UK(UNIQUE),NN(NOT NULL,NOTNULL,NOT_NULL). Order is free relative to the type. - FK target:
-> table.column, or composite-> table.(col_a, col_b).ref/referencesare aliases of->. - Comment:
//after the column becomes muted secondary text on the row. - Table
note:paints under the title.
An FK target creates a column-anchored crow’s-foot relationship automatically. You do not need a second edge unless you are overriding inference.
Inferred relationships
Section titled “Inferred relationships”| Source | Parent end | Child end | Line |
|---|---|---|---|
| Nullable FK | optional (0..1) |
many (0..N) |
dashed |
NN FK |
mandatory (1) |
many (0..N) |
dashed |
UK + FK |
1 or 0..1 |
1 or 0..1 |
dashed |
| FK columns that are the child’s PK | 1 or 0..1 |
1 (identifying 1:1) |
solid |
| FK column that is part of a composite PK | 1 or 0..1 |
many | solid (identifying) |
Several FK columns that point at different columns of the same parent merge into one relationship. Several FKs that share the same parent column stay as separate edges (billing vs shipping) and fan out on the parent key row.
Overrides
Section titled “Overrides”parent.column -> child.column { identifying: true, cardinality: "1:N" }
cardinality accepts 1:N, 0..1:1, 1:0..N, 1:0..1, and similar IE forms, or Mermaid-ish
||--o{. Authored identifying / cardinality win over inference. A label that is only
cardinality is omitted from the drawing (the crow’s foot already says it).
Wrap tables in a group for a schema or bounded context. Prefer layout { groupLayout: compound }.
See Data models for rendered examples.
Kekonic Diagrams does not compile indexes, check constraints, defaults, IDEF1X categorization,
or migrate SQL. Many-to-many needs an explicit junction table. Use a column // comment or table
note: for those facts.
Policy blocks
Section titled “Policy blocks”layout { direction: LR arrange: row density: normal spacingScale: 1.1 groupLayout: compound nodePlacement: balanced considerModelOrder: true edgeNodeSpacing: 24 edgeEdgeSpacing: 14 edgeLabelSpacing: 12}
edges { route: metro crossings: smart cornerRadius: 8 arrowheads: true}
render { theme: dark shadows: false roundedCorners: false}
presentation { title: auto titleSubtitle: "Optional visible subtitle" groupAccent: true showKindSubtitles: false showEndpoints: false clampLabels: true}Top-level shorthand direction LR and density normal are also accepted. API options override
source policy; source policy overrides built-in defaults. A worked custom palette with
shadows and roundedCorners is on Themes.
Directions are LR, RL, TD, and BT. Density values are compact, normal, and spacious.
Diagram-level arrange values are row, stack, and grid; they place ungrouped nodes and
top-level regions in declaration order. Nested groups can define their own arrange policy.
Node placement values are straight, balanced, and basic. Route values are straight,
bezier, orthogonal, rounded, and metro: metro/rounded/orthogonal paint the
laid-out corridor; straight uses a port-to-port chord when the line of sight is clear;
bezier is an obstacle-aware cubic along that corridor. Crossing values are none, gaps,
jumps, and smart.
Styles
Section titled “Styles”style degraded { --node-fill: #2a1f08 --node-stroke: #d69e2e}
cache: cache "Redis" is degradedapi -> cache is degradedStyles contain renderer variables. Apply them with is styleName or styles: [one, two]. Built-in
semantic styles are success, warning, danger, error, muted, and info.
Sequence diagrams
Section titled “Sequence diagrams”Sequence participants use node declarations. Messages appear in source order.
sequence "Request" { autonumber client: actor "Client" api: service "API"
client -> api "request" activate api api --> client "response" deactivate api}Sequence-only statements include activate, deactivate, create, destroy, note over,
divider, autonumber, and structured fragments: alternate/else, optional, loop, parallel/and,
critical, and break. See Sequence diagrams for working examples.
Animation
Section titled “Animation”animation "Happy path" { dim * activate client wait 250ms flow client -> api -> database for 1.2s pulse database for 600ms loop}An empty block enables inferred playback. Authored cues include dim, activate, deactivate,
pulse, flow, wait, parallel, and loop. See Tell a story.