Command-line interface

Installing harel puts a single harel command on your PATH that wraps the static tooling, an in-memory run, the formatter, and the language server.

harel new      FILE [NAME] [--force]        # scaffold a starter .stm (validates + runs as-is)
harel validate FILE [NAME]                 # parse + validate; exit 1 on errors
harel render   FILE [NAME] [--mermaid]      # PlantUML (default) or Mermaid
harel list     FILE                         # machines / fragments / events in a file
harel run      FILE [NAME] [-e KIND[:JSON]] # drive a machine with events (in-memory)
harel fmt      FILES... [--check|--diff]    # format .stm files
harel lsp                                   # start the DSL language server (stdio)
harel monitor  [--definitions-dir DIR]      # the monitoring TUI (needs the `tui` extra) — see Monitor
harel --version

NAME selects the machine when a file declares more than one.

Starting from scratch

harel new writes a small, commented machine that validates and runs with no setup — zero to a working state machine in one command:

$ harel new approval.stm
created approval.stm  (machine approval)
next:
  harel validate approval.stm
  harel run      approval.stm -e Submit -e Approve

$ harel run approval.stm -e Submit -e Approve
(start)              -> Draft
Submit               -> Review
Approve              -> Approved
status: DONE  outcome: success

The machine name defaults to the file name (sanitised to a valid identifier); pass NAME to override, and --force to overwrite an existing file.

Examples

Validate a machine and render it:

$ harel validate examples/place_order/order.stm order
order: ok

$ harel render examples/place_order/order.stm order --mermaid
stateDiagram-v2
[*] --> Cart
...

Drive a machine with a sequence of events (each -e is one event; attach data as KIND:'{...}' for guarded transitions):

$ harel run examples/place_order/order.stm order \
    -e PlaceOrder -e PaymentAuthorized -e Picked -e Packed -e Dispatched -e Delivered
(start)              -> Cart
PlaceOrder           -> AwaitingPayment
PaymentAuthorized    -> Fulfilling.Picking
...
status: DONE  outcome: success

run resolves a machine’s action modules from the working directory (for package-qualified paths like pkg.mod.fn, run it from your project root) and from the .stm file’s own directory. Seed the initial context with --seed '{"items": [...]}', and add --validate to check the machine before running.

fmt and lsp are passthroughs: harel fmt --check **/*.stm and harel lsp behave exactly like the standalone harel-fmt / harel-lsp entry points.

Verified

The commands behave as shown — exercised in CI:

from harel.cli import main

assert main(["list", "test/data/order.stm"]) == 0
assert main(["validate", "test/data/order.stm", "order"]) == 0
assert main(["render", "test/data/order.stm", "order", "--mermaid"]) == 0