CLI Reference

The CLI is the most direct way to use kUML — render, generate, validate, simulate, export, parse. Every subcommand prints its own help with --help.

Synopsis

kuml <subcommand> [options] <script>...

Common options on every subcommand:

  • --config <path> — load a kuml.config.kts file

  • --verbose / -v — enable debug output

  • --version — print version and exit

  • --help / -h — print subcommand help

kuml render

Render a script to SVG or PNG.

kuml render [options] <script>...

Options:

  • --output <path> — output file (or directory if multiple scripts)

  • --format svg|png|latex|tex — default svg. latex / tex emit TikZ output (UML, SysML 2, C4, and BPMN are all supported).

  • --theme <name> — theme name (e.g. plain, kuml, elegant, playful)

  • --engine <id> — layout engine ID (e.g. elk.layered, kuml.grid)

  • --layout grid|elk|auto — shorthand layout selector added in V2.0.26; auto lets kUML choose based on diagram type. Equivalent to --engine kuml.grid, --engine elk.layered, or engine auto-detection respectively.

  • --width <pixels> — PNG width (height is derived from aspect ratio)

  • --latex-standalone — wrap the SVG output in a \begin{figure}…​\end{figure} block suitable for direct inclusion in LaTeX documents (added in V2.0.31).

  • --watermark — opt-in visible "Powered by kUML" label in the bottom-right corner; the canvas grows downward so it structurally cannot overlap diagram content (added in v0.38.0). Independent of the always-on <!-- Generated by kUML vX.Y — kuml.dev -→ metadata comment, which is emitted on every render regardless of this flag.

If the script contains a umlModel { …​ } with multiple diagrams, each diagram renders to its own file using the diagram name as the file stem.

kuml render auto-detects the modelling language from the script’s return value — UML, SysML 2, C4, or BPMN (bpmnModel { …​ }). For BPMN models it also runs the BPMN constraint checker and prints any violations as warnings before writing the output.

kuml generate

Generate code from a script using a registered code generator.

kuml generate --input <script> [options]

Options:

  • -i, --input <script> — path to the *.kuml.kts script (classic mode)

  • -o, --output <dir> — output directory (created if missing)

  • --plugin <name> — generator name (kotlin, java, sql, exposed, or custom)

  • --package <fqn> — target package (Java/Kotlin)

  • --options key=value,key=value — generator-specific options

Examples:

kuml generate --input model.kuml.kts --plugin java --package com.example --options java-style=records --output gen/
kuml generate --input model.kuml.kts --plugin sql --options sql-dialect=mysql,sql-drop=true --output gen/

--sql-migration: additive-only schema-diff migrations

A second mode diffs two ERM model snapshots and writes a single additive-only Flyway migration file — mutually exclusive with -i/--input:

kuml generate --sql-migration \
    --from schema-v1.kuml.kts \
    --to schema-v2.kuml.kts \
    --version 2 \
    --description add_orders \
    --output migrations/

Writes migrations/V2__add_orders.sql. Both scripts must be ERM models; any destructive or ambiguous change (dropped/renamed entity or column, type or primary-key change) makes generation refuse with the full list of blockers. See ERM DSL for details.

kuml validate

Validate expressions and structure. Exits non-zero on any violation.

kuml validate [options] <script>...

Options:

  • --strict — also evaluate profile-level stereotype constraints (default: only element-level constraints)

  • --no-check-structure — skip structural checks (duplicate IDs, circular inheritance); OCL only

  • --json — emit violations as a JSON array to stdout instead of human-readable text

Output is structured: every violation prints constraint name, host classifier, OCL body, and a short failure message. Exit code 3 on violations, 0 on clean. Suitable as a CI step.

See Validation Reference for full flag details, exit codes, and a GitHub Actions integration example.

kuml diagnostics

Emit script compile/eval diagnostics with their source locations, for editor and IDE integration (this is what the JetBrains plugin’s inline error highlighting uses).

kuml diagnostics <script>

Unlike kuml validate — which focuses on OCL/structural model violations and prints script errors as a plain, location-less message — diagnostics preserves the line and column of every diagnostic so an editor can place squiggles precisely.

Output is one diagnostic per line on stdout, tab-separated (so consumers need no JSON parser):

<severity>	<startLine>	<startCol>	<endLine>	<endCol>	<message>
  • severity is WARNING, ERROR, or FATAL (only these are reported).

  • Location fields are empty when the diagnostic carries no location (e.g. a whole-file failure). The message is the last field, with any tab/newline replaced by a space, so split('\t') with a limit of 6 is always safe.

  • The command always exits 0 — validity is conveyed by the emitted lines, not the exit code, so callers can parse the result regardless of script validity.

Example — a script with two unresolved references:

$ kuml diagnostics broken.kuml.kts
ERROR	3	5	3	13	Unresolved reference 'nonsense'.
ERROR	3	18	3	19	Unresolved reference 'y'.

A valid script produces no output.

kuml simulate

Run a state-machine simulation. See the simulate reference for the full event/trace format.

kuml simulate [options] <script>

Options:

  • --events <path> — JSON file with event array

  • --interactive — REPL mode (no --events)

  • --output <path> — write the trace to a file (otherwise stdout)

  • --expected <path> — diff trace against an expected file; exit code 6 on mismatch

  • --epoch-clock — replace wall-clock timestamps with monotonic epoch ms from 0

  • --machine <name> — pick a machine by name when the script contains multiple

kuml transform

Model-to-model (M2M) code generation. Applies a named transformer to a kUML source script and writes the result to a file.

kuml transform [options] <script>

Options:

  • --transformer <name> — transformer ID (e.g. uml-to-sysml2-requirements, uml-to-openapi)

  • --list-transformers — list all registered transformers and exit (no script required)

  • --output <path> — output file path; if omitted, writes to stdout

Examples:

kuml transform --list-transformers
kuml transform domain.kuml.kts --transformer uml-to-sysml2-requirements \
    --output sysml2-req.kuml.kts

SysML 2 transformer targets are supported as of V2.x. See SysML 2 DSL Reference.

kuml version

Print kUML version information.

kuml version [--json]

Options:

  • --json — emit version info as a JSON object ({ "version": "…​", "buildDate": "…​", "commit": "…​" })

Without flags, prints the same human-readable version string as kuml --version. Useful in CI to record the exact kUML version used for a build artefact.

kuml export

Export a kUML model to an external format.

kuml export [options] <script>

Options:

  • --format <name> — currently structurizr (more formats in V2)

  • --output <path> — output file

kuml parse

Read an external format back into a kUML script.

kuml parse [options] <input>

Options:

  • --format <name>structurizr

  • --output <path> — output *.kuml.kts file

kuml profile

Inspect registered profiles. Useful for debugging stereotype-driven codegen.

kuml profile list
kuml profile show JavaEE
kuml profile validate JavaEE       # self-check: every stereotype constraint is parseable

kuml reverse

Reverse-engineer Java or Kotlin source code into a *.kuml.kts script. Discovers reverse engines via ServiceLoader from kuml-codegen-reverse-java (V3.0.7) and kuml-codegen-reverse-kotlin (V3.0.8).

kuml reverse --list-engines                                # list registered engines
kuml reverse src/main/java   --lang java   --output domain.kuml.kts
kuml reverse src/main/kotlin --lang kotlin --output domain.kuml.kts
kuml reverse src/main/java   --lang auto                   # majority-vote on file extensions
kuml reverse src/main/kotlin --verbose-diagnostics         # print every INFO/WARN on stderr

Options:

  • --lang java|kotlin|auto — source language. Default: auto (file-extension majority, ≥ 60 % share required).

  • --output <file> — write the generated *.kuml.kts here; defaults to stdout.

  • --include "<glob>" (repeatable) — file include patterns. Defaults: **/*.java / **/*.kt per --lang.

  • --exclude "<glob>" (repeatable) — file exclude patterns.

  • --model-name <name> — name of the generated model (default ReverseEngineered).

  • --list-engines — print available reverse engines (id + description) and exit.

  • --verbose-diagnostics — print every WARN/INFO diagnostic on stderr (default: one-line summary).

The Kotlin engine is JVM-only (it bundles kotlin-compiler-embeddable), so the reverse subcommand is available in the Fat-JAR / installDist / distTar / runtimeZip distributions but excluded from the GraalVM Native Image build.

Diagnostic codes are grouped per engine:

  • REV-CORE-NNN — engine-agnostic

  • REV-J-NNN — Java engine

  • REV-K-NNN — Kotlin engine

See the kuml-codegen-reverse-api README for the full table.

kuml ai

Inspect and manage AI provider configuration, agent tool sets, benchmarks, pricing, compliance audit logs, and the API key vault:

kuml ai provider list                # configured LLM providers
kuml ai tools list                    # agent tool sets (including the MCP bridge)
kuml ai bench                         # benchmark provider latency/quality
kuml ai pricing                       # provider pricing tables
kuml ai audit                         # compliance audit log
kuml ai vault                         # API key vault (AES-256-GCM)

kuml ai is not the MCP server entry point — there is no mcp-stdio subcommand. The MCP server is the standalone kuml-mcp binary (module kuml-mcp, mainClass = dev.kuml.mcp.MainKt), started directly as /path/to/kuml-mcp/bin/kuml-mcp. It exposes 6 authoring tools (kuml.render/validate/list_elements/describe/generate/examples) and 5 Behaviour-Runtime tools (kuml.run.start/event/snapshot/patch/stop) — agents can query and drive a kUML model the same way they query a database. See Authoring MCP and Behaviour-Runtime MCP for the full tool reference.

kuml workspace

Inspect, validate and render OKF knowledge workspaces — directory trees of Markdown documents with type: frontmatter and ` ```kuml ` diagram blocks:

kuml workspace init [--name <name>] [--mode knowledge|engineering] [--output <dir>]
kuml workspace info <dir>
kuml workspace validate <dir> [--strict-vocabulary]
kuml workspace render <dir> [-f svg|png] [--strict] [--no-mirror]
kuml workspace convert <src> --to okf|kts [--force] [--output <dir>] [--strict]

init scaffolds a new workspace into --output (default ./<slug> from --name); info, validate and render take the workspace root as a positional <dir>; convert (added in v0.38.0) takes a single .kuml.kts script or OKF Markdown note (or a directory of them) and wraps/unwraps it into the other format — a text-level operation, not a model re-serialization, since both formats share identical DSL text.

This is the canonical subcommand group for workspace-level operations — there are no top-level kuml validate/kuml render aliases for it. See Knowledge Workspaces for the .kuml-workspace.toml marker format, the full type: vocabulary, and the OKF-* finding codes, including the OKF-C-00x codes specific to convert.

Logging

All log output goes to stderr — stdout is reserved for rendered output (SVG/PNG) and structured JSON, so it is always safe to pipe (kuml render --format svg > out.svg) or redirect (kuml validate --output json 2>/dev/null) without a stray log line corrupting the result.

Set KUML_LOG_LEVEL to control verbosity (default WARN). Valid values are TRACE, DEBUG, INFO, WARN, ERROR, OFF and ALL (case-insensitive):

KUML_LOG_LEVEL=DEBUG kuml ai provider list

KUML_LOG_LEVEL can also be set as a JVM system property (-DKUML_LOG_LEVEL=DEBUG) instead of an OS environment variable — useful when launching the CLI from a wrapper script or a java -jar invocation that has no convenient way to export an env var. Both channels are normalized identically; a system property takes precedence over the environment variable if both are set, matching Logback’s own substitution lookup order.

An unset KUML_LOG_LEVEL falls back to WARN. A value outside the list above (a plausible-but-wrong guess like SILENT, NONE or quiet) is normalized back to WARN as well, rather than being passed through — Logback’s own parser would otherwise silently fall back to maximum verbosity (DEBUG) for any name it doesn’t recognize, which is the opposite of what a lower-verbosity guess like SILENT was going for. This normalization applies the same way regardless of which channel (environment variable or system property) the value was set through.

Third-party HTTP/AI client loggers (io.ktor, ai.koog, de.betchvaia, aws.smithy.kotlin, software.amazon.awssdk, org.eclipse.elk, org.apache.hc, io.netty) are intentionally pinned to WARN regardless of KUML_LOG_LEVEL — those stacks log full request/response bodies, including Authorization headers, at DEBUG/TRACE. Raising KUML_LOG_LEVEL only ever increases kUML’s own log verbosity.

Exit codes

Code Meaning

0

Success.

1

Script error (compilation, missing imports).

2

User error (bad argument, file not found).

3

Validation error (OCL constraint violated).

4

Generation error (code generator threw).

5

Layout error (engine failed to produce a result).

6

Trace diff (simulate --expected mismatch).

14

kuml reverse --lang <id> referenced an unknown engine.

15

kuml reverse engine returned ERROR-level diagnostics.

16

kuml reverse found no source files in the given directory.

These codes are stable — CI scripts can branch on them.

Performance notes

The CLI compiles each script once and caches the result in the Kotlin scripting host. The first invocation is slow (cold JVM, JIT warmup, ELK initialisation) — typically 2-4 seconds. Subsequent invocations within the same JVM (use kuml shell if needed) are sub-second.

For build pipelines that render dozens of diagrams, the Gradle plugin’s kumlRender task is much faster: it reuses the Gradle daemon’s warm JVM and Gradle’s incremental input checks skip unchanged files entirely.