Lemma CLI
See Installation for install options.
Commands
lemma run: evaluate a spec
lemma run [[repo] spec] [name=value ...] [--prefix PATH] [--rules=RULES] [options]
Syntax:
- Positionals: optional repository qualifier (e.g.
@iso/countries), then spec name (seelemma run --help) spec --rules=rule: evaluate one rulespec --rules=rule1,rule2: evaluate specific rules (comma-separated)- No arguments with
-i: interactive mode
Options:
--prefix <path>: workspace directory or.lemmafile (default: current directory)--rules <rules>: comma-separatedShow.ruleskeys (omit to evaluate this spec's outputs)--json: output results as JSON (default: human-readable table). Each rule result may includemissing_data(unbound input keys in evaluation / decision-tree order). Types, filled values, and suggestions come fromlemma show, not from evaluate JSON.-x, --explain: include explanation trees (human: reasoning tables per rule; JSON: per-ruleexplanationobjects matchingapi.v1.json). Unbound inputs appear in those tables when a rule still awaits input (MissingDataveto). JSON still carries raw per-rulemissing_datafrom the engine.-i, --interactive: guided spec/rule/data selection--effective <datetime>: evaluate at effective datetime (e.g.2025,2025-03,2025-03-04)
Examples:
lemma run pricing
lemma run pricing --rules=total,tax
lemma run --prefix ./policies nl/tax/net_salary --rules=net_salary -x
lemma run pricing quantity=10 is_vip=true
lemma run pricing --json
lemma run pricing -x
lemma run pricing --effective 2025-01-01
lemma run -i
lemma run '@iso/countries' alpha2
lemma show: declared data catalog and rules
Shows declared data slots with types and constraints (minimum, maximum, units, decimals, text options), filled values, suggestions, import path, and this spec's rule graph (ShowRule: type, path, branches, depends_on_rules as input_key). Lemma source text is available via Engine::source (API) only.
show lists every declared promptable data slot (types, constraints, fill, suggestions, path). needed_by_rules names Show.rules keys that still need the slot after normalize; empty means offered for reuse (data x: alias.slot), not an eval intake key for this spec. Run-data-aware pruning for a concrete run is per-rule results.*.missing_data.
lemma show [[repo] spec] [--prefix PATH] [--effective <datetime>] [--json]
Options:
[repo]: optional repository qualifier (e.g.@iso/countries)[spec]: spec name (omit when workspace has a single spec)--prefix <path>: workspace directory or.lemmafile (default: current directory)--effective <datetime>: effective datetime for temporal specs--json: output as JSON (default: human-readable table)
Examples:
lemma show pricing
lemma show --prefix ./policies net_salary
lemma show --prefix tax.lemma calculator
lemma show '@iso/countries' alpha2
lemma show pricing --json
lemma list: list loaded specs by repository
Lists every loaded spec, grouped by repository. Local specs (no repository qualifier) are printed unindented; named repositories (including embedded lemma) appear as headers with indented spec names.
lemma list [--prefix PATH] [--json]
Options:
--prefix <path>: workspace directory or.lemmafile (default: current directory)--json: outputEngine::list()JSON: array of{ "repository", "specs" }where each spec is aListedSpec(name, optionaleffective_from/effective_to). Human text lists unique spec names only.
Examples:
lemma list
lemma list --prefix ./project
lemma list --json
lemma install: install repositories from LemmaBase
Resolves @... references and downloads repositories from LemmaBase into lemma_deps/.
lemma install [--prefix PATH] --all
lemma install [--prefix PATH] <repository> -f
Options:
--prefix <path>: workspace directory or.lemmafile (default: current directory)-a, --all: install all@...references in the workspace-f, --force: overwrite existing repositories when content has changed on LemmaBase
lemma format: format .lemma files
lemma format [paths...] [--check] [--stdout]
Options:
--check: check formatting without modifying (exit 1 if any file would change)--stdout: write formatted output to stdout
lemma server: start HTTP server
lemma server [--prefix PATH] [--host <host>] [-p <port>] [--watch] [--explain] [--eval-timeout SECONDS] [--cors]
Options:
--prefix <path>: workspace directory or.lemmafile (default: current directory)--host <host>: bind address (default:127.0.0.1)-p, --port <port>: port (default:8012)--watch: live-reload on.lemmafile changes--explain: enable explanation generation (clients sendx-explainheader; JSON shapeapi.v1.json)--eval-timeout <second>: wall-clock timeout for a single evaluation request (default:10)--cors: allow cross-origin browser requests from any origin (off by default)
SIGINT/SIGTERM stop accepting new connections, drain in-flight requests up to --eval-timeout, then exit 0.
Routes:
| Method | Route | Description |
|---|---|---|
| GET | / |
List all specs |
| GET | /{spec} |
Show spec interface (data, rules, versions) |
| POST | /{spec} |
Evaluate (data as JSON or form body) |
| GET/POST | /{spec}/{rules} |
Evaluate specific rules (comma-separated) |
| GET | /openapi.json |
OpenAPI 3.1 specification |
| GET | /docs |
Interactive API documentation (Scalar) |
| GET | /health |
Health check |
Example:
lemma server --prefix ./policies --watch
curl "http://localhost:8012/pricing?quantity=10&is_member=true"
curl -X POST http://localhost:8012/pricing \
-H "Content-Type: application/json" \
-d '{"quantity": 10, "is_member": true}'
lemma lsp: start language server
Starts the Language Server Protocol server over stdio for editor integration (diagnostics, formatting, semantic tokens). The VS Code/Cursor extension invokes this automatically; a globally installed lemma CLI is the only requirement.
Workspace file discovery uses the same policy as lemma list / lemma run: project .gitignore rules, plus always loading <workdir>/lemma_deps/**/*.lemma. The CLI injects that discovery and a filesystem watch into the LSP. The watch covers discovered workspace .lemma files and lemma_deps/ only (not a recursive whole-tree watch), so disk changes such as lemma install update diagnostics without hanging on large build directories. Editor open/change/save/close remain the primary sync path for buffers.
lemma lsp
lemma mcp: start MCP server
Start the MCP server so AI assistants can work with workspace specs. Default transport is stdio. Pass --http for Streamable HTTP (POST /mcp). Full setup guide: MCP.
lemma mcp [--prefix PATH] [--write] [--request-timeout SECONDS]
lemma mcp --http [--prefix PATH] [--write] [--request-timeout SECONDS] [--host HOST] [--port PORT] [--cors]
Options:
--prefix <path>: workspace directory or.lemmafile (default: current directory)--write: enable write tools (read-only by default)--request-timeout <seconds>: wall-clock timeout for a single request (default:10)--http: Streamable HTTP instead of stdio--host <host>: bind address when using--http(default:127.0.0.1)--port <port>: listen port when using--http(default:8013;lemma serveruses8012)--cors: permissive CORS when using--http(off by default)
HTTP MCP has no built-in authentication or TLS. It binds to localhost by default; for non-localhost bind, put it behind a reverse proxy that terminates TLS and enforces access control.
Workspace
A workspace is a directory containing .lemma files. Commands that load specs use --prefix to select the workspace (default: current directory). Every .lemma file is loaded recursively from that directory, plus any repositories in lemma_deps/.
policies/
pricing.lemma
shipping.lemma
tax.lemma
Resource Limits
Resource limits control parse-time and planning-time budgets. These are security boundaries that prevent unbounded resource consumption from untrusted input.
| Limit | Default | Purpose |
|---|---|---|
max_sources |
4096 | Maximum source files in one engine |
max_loaded_bytes |
50 MB | Total source text across all files |
max_source_size_bytes |
5 MB | Single source file size |
max_expression_depth |
7 | AST nesting depth |
max_expression_count |
65,536 | Expression nodes per source (parser) |
max_normalized_expression_nodes |
30,000 | Unique normal-form cells reachable from one rule root after normalize (rule references count as one cell) |
max_normal_form_depth |
4096 | Nesting depth of a rule's normalized NormalForm DAG (rule references count as one level) |
max_data_value_bytes |
1 KB | Single data value size |
max_spec_dependency_depth |
32 | uses chain depth |
max_dag_specs |
4096 | Total specs in dependency DAG |
max_expression_depth and max_spec_dependency_depth bound recursion during parsing and planning. Raising these beyond the defaults requires stack analysis for your deployment.
API Defaults
Effective datetime: when no --effective flag or Accept-Datetime header is provided, the engine uses the current instant to select the temporal version of the root spec.
Accept-Datetime (HTTP): clients send Accept-Datetime with the same formats as --effective: YYYY, YYYY-MM, YYYY-MM-DD, or an ISO 8601 datetime. Empty or omitted → now. Invalid values are a bad request. Responses include Vary: Accept-Datetime. When the resolved spec row has an effective_from, the server also sets Memento-Datetime to that instant.
Explanations: disabled by default in CLI (lemma run), HTTP, and SDKs. Use --explain (CLI and server) + x-explain (HTTP client), or explain: true (SDK) to opt in. MCP run/evaluate always return formatted ASCII explanation trees (no explain arg, no opt-out) plus a Missing data block when inputs are unbound. Evaluate/run JSON (CLI --json, HTTP, SDKs) has no top-level data array: unbound inputs are per-rule missing_data; types and suggestions come from lemma show / MCP show. When explanations are enabled on JSON surfaces, each results.<rule>.explanation is a rule node ("type":"rule", "name", "result", "body", optional "causes" / "children") per api.v1.json. Bound data uses "type":"data", unused cause paths "type":"data_unused".
See Also
- Learn guide
- Installation
- Language reference
- API schema (Show, Response, list, errors,
RuleResult.explanation/ExplanationNode) - LemmaBase
- Engine test coverage
- CLI test coverage
- CLI benchmarks
- Engine benchmarks