CLI (LILA-045/046/047/053, #450)
lila is the command-line front end of @lila-modeler/engine: the same validation and simulation
pipeline used by the web app, the desktop app and the MCP server, driven from a terminal. This
page is the reference an agent or a script needs: every command with one real example, its exit
codes, what --json/--csv/--xlsx write, and how to read the result.
Every example below runs from the repository root, against the committed
examples/pedido benchmark. Requires Node.js 22 or later.
Install
The CLI ships in the engine package, @lila-modeler/engine
on npm, under the beta tag while the project is pre-1.0. Install it, or run it without installing:
npm install -g @lila-modeler/engine@beta # puts `lila` on your PATH
npx -p @lila-modeler/engine@beta lila validate model.bpmn
npx @lila-modeler/engine@beta validate model.bpmn
The examples below use npx lila … from a checkout of the repository, which also has the
examples/pedido benchmark they run against:
git clone https://github.com/AlambritoDito/lila-modeler.git
cd lila-modeler
npm ci
npm run build
npx lila then resolves the workspace's own binary (packages/engine/bin/lila.js), with no
registry lookup.
npx lila only finds this CLI inside the checkout (after npm ci). Anywhere else it would fetch
the unrelated lila package from npm, so from another directory use one of the
@lila-modeler/engine commands above, call the bin directly (node <checkout>/packages/engine/bin/lila.js …) or use npx --no lila …, which refuses to install.
validate
Parses a .bpmn file (or one process of a .lila, see below), prints its IR (nodes, flows, lanes) and the full validation
(docs/SEMANTICS.md §17 error/warning codes). Warnings alone still exit 0; any error exits 1.
npx lila validate examples/pedido/model.bpmn
Exit code: 0.
A model outside the supported profile — here, a boundary event, which the engine does not
simulate (docs/SEMANTICS.md §2) — exits 1 and names every problem:
npx lila validate packages/engine/test/fixtures/boundary-event.bpmn
Exit code: 1.
--json prints the same report ({ ir, ignoredProcessIds, errors, warnings }) as one JSON
document instead of the text above; the exit code rule is the same.
run
Validates model and scenario, simulates with replications, and prints the Bizagi-style tables
(process elements, sequence flows, resources) plus Lila's extras: bottleneck ranking, process
summary, per-outcome breakdown. Exits 1 if the model or the scenario has a validation error, or
if the scenario's model does not match the file given on the command line; 0 otherwise.
npx lila run \
examples/pedido/model.bpmn examples/pedido/as-is.scenario.json \
--seed 42 --replications 3 \
--json results/run.json --csv results/csv --xlsx results/as-is.xlsx
Exit code: 0.
--json <file>writes the deterministicRunResult(docs/RESULTS_FORMAT.md) as one JSON document. Its shape isrunResultSchema, exported from@lila-modeler/engine/result-schema— validate against it before trusting a parsed file.--csv <directory>writeselements.csv,flows.csv,resources.csv,process.csv(RFC- and
log.csv(the event log, streamed while the run executes, ISO timestamps fromrun.start). It is the only flag that writes the event log;--jsonand--xlsxdo not carry it.
- and
--xlsx <file>writes one workbook with the Summary, Elements, Flows, Resources and Parameters sheets. No event log sheet — use--csvfor that.- All three create missing directories, write to a temporary path and rename atomically, and refuse to overwrite a path that is a directory.
--save(with a.lilaand a scenario of it) stores the run in the project, as the app does; see «Storing a run» underexport.
compare
Simulates two or more scenarios against the same model and prints them side by side: value plus
relative delta against the first (base) scenario, with a * marking a statistically significant
difference at the 95% confidence level.
npx lila compare \
examples/pedido/model.bpmn \
examples/pedido/as-is.scenario.json examples/pedido/to-be-3-cajeros.scenario.json \
--seed 42 --replications 3 \
--json results/compare.json
Exit code: 0.
The default table is a curated KPI subset; --all prints every metric compare() produces for
every element, resource, flow and outcome. --json <file> writes the CompareResult; --xlsx <file> writes one workbook with one tab per scenario plus a Comparison tab. compare has no
--csv — it compares finished runs, it does not replay one.
export (#538)
Produces the deliverables without the app — no window, no browser — from the same engine code the app uses:
lila export diagram <model.bpmn|project.lila>draws the diagram with the engine's own SVG renderer (the BPMN DI geometry, Lila Light colours on white). Without--outit prints the SVG on stdout.lila export doc <project.lila> --out file.docx|file.htmlwrites the process document, as the app's «Export document»: diagram, descriptions in flow order, the scenario and the results of a stored run. The HTML embeds the SVG diagram. The Word file has no diagram, and neither format has the run's charts: Word needs a PNG and the engine has no rasteriser. A note on stderr says what was left out.lila export results <project.lila> --out book.xlsx|directorywrites the results of a stored run: one.xlsx(Summary, Elements, Flows, Resources, Parameters), or with--format csvelements.csv,flows.csv,resources.csvandprocess.csvin the directory, the same fileslila runwrites (a stored run keeps no event log, so there is nolog.csv).
--format defaults to the extension of --out (.docx, .html, .xlsx). --process picks
the process of a repository, as elsewhere. Runs are the ones the app saved in the .lila:
--run latest (the default) is the run of the current model and scenario, --scenario <name>
narrows it to one scenario (needed when several scenarios have a current run), and --run <id>
picks one by id — an error lists the ids; --run <id> and --scenario together are an error. The document only takes a current run and, without one,
goes without results; results without a run is an error saying so. An older run's results are
exported against the model it ran on.
Nothing is overwritten: an existing output file is an error and nothing is written, unless
--force. The file being exported (the .lila or .bpmn) is never a destination, --force or
not, by any path that reaches it. Every file is written to a temporary file next to it and then
published at once, so an error never leaves half a file.
npx lila export diagram examples/pedido.lila --out results/pedido.svg
Exit code: 0.
npx lila export doc examples/pedido.lila --out results/pedido.html
Exit code: 0.
Storing a run: lila run <project.lila> <scenario> --save simulates a scenario of the archive
and stores the run in the .lila exactly as the app does (same shape, the model and scenario
revisions it ran on, built by the same engine function), so the app opens it as the current run
and lila export uses it. The write is atomic and under the file's lock; concurrent saves all
land, and a save after the model or that scenario changed is refused. A .bpmn or a scenario file
on disk cannot be saved. The app keeps every run, and so does --save:
npx lila run project.lila as-is --seed 42 --replications 5 --save
npx lila export results project.lila --out results/as-is.xlsx
examples/pedido.lila stores no run, so its results cannot be exported until one is saved (the
message says how):
npx lila export results examples/pedido.lila --out results/pedido.xlsx
Exit code: 1.
process annotate and process raci (#99)
Document a process from the terminal, the way the app's properties panel does, and read back its RACI matrix:
lila process annotate <project.lila> <elementId>writes into the element with that BPMN id:--documentation <text>replaces its description (""removes it);--responsibility TYPE:role(repeatable,TYPEone ofR,A,C,I) replaces its whole RACI list, and--clear-responsibilitiesempties it;--ref kind=id(repeatable;systemRef,documentRef,riskRef,controlRef,kpiRef,input,output) replaces the lists of the kinds given (kind=empties one);--attribute id=value(repeatable, by attribute id or name) sets an extended attribute, checked against the project's attribute definitions (id=removes the value; the attributes not given stay). It prints the element as it ends up;--jsonprints{ file, process, elementId, dryRun, changed, written, before, after }.lila process raci <project.lila>prints the RACI matrix: a row per element with responsibilities, in the order of the process document (lila export doc), a column per role.--jsonprints{ file, process, roles, rows };--csvprintsid,name,lane,<roles>as CSV.
--dry-run shows the result and writes nothing. A write saves the .lila atomically, under its
lock, with every other process unchanged (see A .lila as input); the
model's revision goes up by one, as when the app saves. An unknown element, a type that is not
RACI or an attribute value that does not fit its definition is an error, and nothing is written.
npx lila process annotate examples/pedido.lila Task_TomarPedido --responsibility R:cajero --responsibility A:gerente --ref systemRef=POS --dry-run
Exit code: 0.
npx lila process raci examples/pedido.lila --json
Exit code: 0.
scenario import and scenario template (#514)
The app's «Download template» and «Import Excel/CSV…» (docs/SCENARIO_SHEETS.md) on a scenario
of a .lila:
lila scenario template <project.lila> <scenario> --out sheet.xlsxwrites the scenario sheet (Elements, Arrivals, Resources, Assignments, Calendars), filled in with the scenario's values, for a person to fill in. An existing file is refused unless--force.lila scenario import <project.lila> <scenario> <sheet.xlsx|sheet.csv>plans the sheet against the resolved scenario and prints each change (Cashier (cajero) · capacity: 2 → 3), the rows not applied and the notes, then writes the changes into the scenario's own file — its delta when itextendsanother, exactly as the app does. A plan that would leave the scenario with errors is refused and nothing is written.--dry-runprints the plan and writes nothing;--jsonprints{ file, process, scenario, sheet, dryRun, written, tables, changes, issues }.
npx lila scenario template examples/pedido.lila as-is --out results/as-is.xlsx
Exit code: 0.
npx lila scenario template project.lila as-is --out as-is.xlsx
# … a person fills in as-is.xlsx …
npx lila scenario import project.lila as-is as-is.xlsx --dry-run
npx lila scenario import project.lila as-is as-is.xlsx
project show and scenario show (#628)
What a .lila holds, read without writing anything — no write, no revision change:
lila project show <project.lila>prints the project's name and format version (2 for a repository of several processes, 1 otherwise) and, per process, its slug, name,bpmn:processid, model revision and number of flow nodes, its scenarios (entry, name, revision,extends) and its saved runs (id, scenario, replications, simulated start, and whether the run is current or stale: stale when the model or the scenario changed after it). A.lilakeeps no date of when a run was taken;startis therun.startof the scenario it ran.--jsonprints{ file, name, formatVersion, processes: [{ slug, name, processId, modelRevision, elements, scenarios: [{ entry, name, revision, extends }], runs: [{ id, scenario, start, replications, current }] }] }.lila scenario show <project.lila> <scenario>prints the scenario as stored (with itsextends), or with--resolvedmerged throughextendswith the engine's defaults — the objectpatch_scenariopatches,modelrelative to the scenario. Then the validator's notes against the process model (errorsE-…first, then warningsW-…), the checksrunmakes before it simulates, so it doubles as a scenario lint; it still exits0when there are errors.--jsonprints{ file, process, entry, revision, resolved, scenario, runnable, notes }.
npx lila project show examples/pedido.lila --json
Exit code: 0.
npx lila scenario show examples/pedido.lila to-be-3-cajeros --resolved
Exit code: 0.
mcp
Starts the MCP server (@lila-modeler/mcp) over stdio, for an MCP client to launch — not something you
run directly in a terminal and read from. Details, tool contracts and client registration are in
docs/MCP.md; the underlying command is:
node packages/engine/bin/lila.js mcp
lila mcp needs @lila-modeler/mcp installed next to the engine; the CLI alone stops with
lila mcp: the package @lila-modeler/mcp is missing. Outside a checkout, the usual way to start
the server is the package's own command, npx -y @lila-modeler/mcp.
process
Creates a process from an outline, reads one back (#97) and edits one (#98). An outline is the process as data —
lanes plus an ordered list of steps with branches — and is the same JSON the MCP tool
create_process takes; its format and rules are in docs/MCP.md.
lila process create --outline <file.json> -p <file.lila> [--name name] [--process slug] [--dry-run] [--json]
lila process show -p <file.lila> [--process slug] [--json]
lila process edit -p <file.lila> --ops <ops.json> [--process slug] [--dry-run] [--no-layout] [--json]
process create builds the BPMN, lays it out (pool, lanes, flows), validates it and adds it to the
.lila as a new processes/<slug>/ with a base scenario as-is.scenario.json; a .lila that does
not exist is created. --name overrides the outline's name, --process picks the slug (derived
from the name otherwise). It never replaces a process: a slug already in the file exits 1 and
writes nothing, and so does an outline with problems (all of them are listed, each with its path).
--dry-run builds and checks everything and writes nothing. It prints a one-line summary and the
validator warnings and Lila's notes; --json prints the result object of create_process
instead, and on a failure { "error", "issues" } (each issue with its path and message) before
exiting 1. With a new .lila, --process must be the slug the name gives.
npx lila process create --outline examples/outline/credit-application.json -p credit.lila --dry-run
Exit code: 0.
Dry run: would create process "Credit application" (credit-application) in the new file /…/credit.lila: 5 steps, 2 lanes. Nothing was written.
The slug pedido is taken in examples/pedido.lila, so this is refused:
npx lila process create --outline examples/outline/credit-application.json -p examples/pedido.lila --process pedido --dry-run
Exit code: 1.
process show prints the outline of one process, one step per line with its type, name, lane,
duration, resources and where it goes; --json prints { slug, outline, warnings }, the outline in
normal form (the form create_process returns). Durations, resources and branch probabilities
come from the process's as-is.scenario.json. What an outline cannot carry is reported on stderr.
npx lila process show -p examples/pedido.lila
Exit code: 0.
Process "Restaurant" (pedido)
Task_TomarPedido task "Take order" triangular(min=60, mode=120, max=300) Cashier
Gateway_ANDFork and "Prepare and pack" → Task_Preparar | Task_Empacar
…
Gateway_Aprobacion xor "Approved?" → Approved: Timer_Reposo (0.78) | Rejected: end (0.22)
Timer_Reposo timer "Rest" constant(value=600) → end
process edit applies a list of operations to one process, all or none: the JSON array the MCP
tool edit_process takes as operations (add, connect, remove, rename, setType,
moveToLane, addLane; format and rules in docs/MCP.md). Every
operation is checked, the result is validated, and the .lila is written only if all of it is fine;
otherwise it exits 1, writes nothing and lists every problem with the index of its operation. The
process is laid out again unless --no-layout, which keeps every position and only places the new
shapes. It prints a summary, one line per operation, notes (each scenario entry removed because it no
longer applies, with its previous values, so the process still simulates; branch probabilities that
no longer add up) and the validator warnings; --json
prints the result object of edit_process. --dry-run writes nothing.
examples/outline/pedido-edit.json adds a "Charge" step with a duration and the cashier, renames
and retypes two steps, adds two lanes and moves the cooking to the kitchen lane:
npx lila process edit -p examples/pedido.lila --ops examples/outline/pedido-edit.json --dry-run
Exit code: 0.
Dry run: would edit process "pedido" (pedido) in /…/examples/pedido.lila: 6 operations, 0 elements removed. Nothing was written.
0: added task "Task_Cobrar" after "Task_TomarPedido"
1: renamed "Task_Preparar": "Prepare food" → "Cook"
2: "Task_Revisar": task → userTask
3: added lane "Counter" (Lane_1)
4: added lane "Kitchen" (Lane_2)
5: moved "Task_Preparar" to lane "Kitchen"
warning W-MSGFLOW Process_Restaurante: Process_Restaurante: 2 message flows (bpmn:messageFlow) were ignored.
Removing the parallel split is ambiguous (one flow in, two out), so the whole edit is refused, the rename included:
npx lila process edit -p examples/pedido.lila --ops examples/outline/pedido-edit-ambiguous.json --dry-run
Exit code: 1.
lila process: the edit was refused; nothing was changed:
operations[1].id: cannot remove "Gateway_ANDFork": with 1 incoming and 2 outgoing flows it is not clear how to reconnect them. Remove or reconnect its flows first.
General options
Apply to every subcommand, in any position on the command line:
--lang en|es— language of the output (messages, not column names or BPMN IDs, which are a stable contract). Default:LILA_LANG, thenLANG, English if neither is set.-h,--help— usage forlilaorlila <command> --help.-v,--version, or theversionsubcommand — prints the installed@lila-modeler/engineversion and exits0.
npx lila --version
Exit code: 0.
Exit codes
| Code | Meaning |
|---|---|
0 |
The command ran; validate may still have printed warnings. |
1 |
Usage error, unknown command, a model/scenario validation error, an outline with problems or a process that already exists (process create), an edit that is refused (process edit), a scenario whose model does not match the file given, a .lila that cannot be opened or whose process or scenario cannot be found, an export with no run or over an existing file, or an uncaught error from the command (message on stderr). |
For agents
A model change is safe to hand back only after this loop, all against --json output so a script
can decide without parsing prose:
- Validate first.
lila validate model.bpmn --json; check the exit code, thenerrors(code,id,message). Stop here if it is not0— nothing downstream is trustworthy. - Run with a fixed seed and enough replications for a narrow confidence interval:
lila run model.bpmn scenario.json --seed 1 --replications 30 --json results/run.json. - Read
results/run.jsonwith any JSON tool. Its shape matchesdocs/RESULTS_FORMAT.mdand validates againstrunResultSchema(@lila-modeler/engine/result-schema); column names are the Bizagi-parity contract indocs/BIZAGI_PARITY.md, not renamed per language. - To evaluate a change, write a second scenario that
extendsthe first with only the changed keys (docs/SCENARIO_FORMAT.md), thenlila compare model.bpmn base.json changed.json --seed 1 --replications 30 --json results/compare.json. Read each row'sdeltaRelandsignificant; a metric can move withoutsignificantbeing true at low replication counts.
The text tables on stdout carry the same numbers; they exist for a human at a terminal, not for parsing.
A .lila as input (#466)
A .lila file is a zip of a Lila project folder (docs/PROJECT_FORMAT.md). validate, run
and compare take it wherever they take a .bpmn; nothing has to be unzipped first. The
committed examples/pedido.lila is the examples/pedido folder in one
file:
npx lila validate examples/pedido.lila
Exit code: 0.
With a .lila model, a scenario argument is resolved in this order:
- An existing file at that path (relative to the current directory) is that file, as with a
.bpmn. It is simulated against the process in the archive; its ownmodelfield is not compared with the archive, andvalidateScenariostill rejects an element id that the process does not have. - Otherwise it names a scenario of the process, by its entry name
(
to-be-3-cajeros.scenario.json), the same name without.scenario.json(to-be-3-cajeros), or the scenario's"name"("TO-BE 3 cashiers", which must then be unique in the process). Itsmodelandextendsresolve inside the archive, exactly as in the project folder. A name that matches nothing lists the scenarios that exist.
npx lila run examples/pedido.lila as-is --seed 42 --replications 3 --json results/run.json
Exit code: 0.
npx lila compare examples/pedido.lila as-is to-be-3-cajeros --seed 42 --replications 3
Exit code: 0.
Both print, and write, exactly what the same commands print on examples/pedido/model.bpmn and
its scenario files. Output paths (--json, --csv, --xlsx) are unchanged: relative to the
current directory, never inside the archive — the CLI does not write to a .lila.
Several processes. A version 2 project (a repository, docs/PROJECT_FORMAT.md) holds more
than one process, each with its own model and scenarios. --process <slug> picks one; with a
single process it is implicit, and with several and no --process the command stops with an
error that lists the slugs. A slug that is not in the project is an error too, and so is
--process with a .bpmn:
npx lila validate examples/pedido.lila --process facturacion
Exit code: 1.
lila run project.lila as-is --process pedido --seed 1 --replications 30 --json results/run.json
The MCP tools accept a .lila the same way, and patch_scenario can write a scenario back into
one (docs/MCP.md).