CLI reference
The lawsynth CLI is the primary surface for the whole toolkit — the Python and TypeScript SDKs mirror it, but every capability starts here. Every command is deterministic and offline: the same inputs, config, version, and binary produce the same output on any machine, with no network access. Run lawsynth <command> --help to print the per-command usage, flags, and honest caveats straight from the binary.
This page lists every subcommand, grouped by the task it serves. Flags are shown with what they do and the default the source sets where there is one; run --help for the exhaustive per-command flag list. Commands read and write the same portable .lsworld bundle unless noted otherwise.
Discover
Recover a law system — or a related operator — from observations.
discover
Sparse symbolic regression from a CSV/TSV/Parquet dataset to a .lsworld world.
--time COLUMN,--state NAME[,NAME...],--output WORLD.lsworld— the time column, state variables to model, and where to write the bundle (required).
--method sindy|weak-form— strong (derivative) form is the default;weak-formis the noise-robust integral form (renders coefficient laws, writes no bundle).
--preset NAME— seed the config from a domain preset (seelawsynth presets); explicit flags override it.
--degree N— polynomial library degree.--threshold VALUE— sparsity cutoff (default0.05).--solver stlsq|sr3|frols|ssr|trapping— the sparse solver.
--trigonometric,--rational,--regimes,--pareto,--refine,--causal— enable trig/rational features, regime detection, the Pareto frontier, joint parameter refinement, and dependency hypotheses.
--bootstrap REPLICATES [--confidence C],--track [--label TEXT]— bootstrap coefficient bounds and record the run forlawsynth runs.
$ lawsynth discover lorenz.csv --time t --state x,y,z --output lorenz.lsworld --solver stlsq --pareto
control
Controlled (SINDYc) discovery of a forced system dx/dt = f(x, u). Control columns enter the candidate library but are never differentiated or predicted. Prints one equation per state; writes no .lsworld bundle.
--time COLUMN,--state NAME[,NAME...],--control NAME[,NAME...]— time, state, and exogenous control columns (required).
--degree N,--threshold V— library degree and sparsity cutoff.--validate— roll the model forward under the dataset's own controls and report in-sample R²/RMSE.
$ lawsynth control cart.csv --time t --state x,v --control u --validate
network
Recover the directed coupling graph of a multivariate system: each state column is a node, and a surviving cross term x_j in node i's equation is reported as an edge j -> i. The graph is correlational, not causal.
--state NAME[,NAME...](required),--time COLUMN.
--degree D(1 = linear couplings),--threshold T(per-term cutoff),--edge-threshold E(minimum aggregated edge strength).
$ lawsynth network nodes.csv --state x1,x2,x3 --edge-threshold 0.1
select
Choose discovery hyperparameters by deterministic time-series cross-validation. The timeline is cut into K+1 contiguous segments; every candidate in the --degrees × --thresholds grid is scored on held-out data.
--state NAME[,NAME...],--degrees D[,D...](required).--thresholds T[,T...](default0.05).
--folds K(default3),--scheme forward|rolling(defaultforward),--metric r2|rmse(defaultr2),--time COLUMN(defaulttime).
--solver stlsq|sr3|frols|ssr|trapping,--trig,--rational— shape the discovery config each fold uses.
$ lawsynth select obs.csv --state x,y --degrees 2,3 --folds 5 --scheme rolling
koopman
Dynamic Mode Decomposition: fit the best-fit linear operator A with x' ≈ A x and report its spectrum. Takes a dataset, not a bundle — and writes no .lsworld (a linear operator is a different type from a symbolic world).
--state NAME[,NAME...](required),--time COLUMN.--rank R— truncate the SVD (default: full rank).
$ lawsynth koopman obs.csv --time t --state x,y --rank 4
sde
Discover a stochastic differential equation dX = a(X) dt + b(X) dW from a single noisy sample path via binned Kramers–Moyal moments. A statistical estimator — accuracy grows with path length; writes no .lsworld bundle.
--state NAME[,NAME...](required),--time COLUMN.
--bins N(state-space partition),--min-bin K(minimum occupancy for a trusted bin),--degree D,--threshold T.
$ lawsynth sde path.csv --time t --state x --bins 40
pde
PDE-FIND: discover a 1-D evolution law u_t = F(u, u_x, u_xx, …) from a space–time field. The field CSV is a plain rectangular numeric grid with no header — rows are time snapshots, columns are spatial points — distinct from the named-column trajectory CSV every other command reads.
--dx DX,--dt DT— the uniform spatial and temporal grid steps (required).
--degree D(maximum field power),--order M(maximum spatial-derivative order),--threshold T(relative sparsity cutoff).
$ lawsynth pde field.csv --dx 0.1 --dt 0.01 --order 3
Analyze
Interrogate a discovered world's structure and long-run behavior. Each command pins every declared parameter at its stored value so the field is autonomous.
stability
Locate the fixed points f(x)=0 inside a search box and classify each by its Jacobian eigenvalues. The box is required and load-bearing: roots outside it are dropped, and the report states how many seeds converged so an empty result reads as "nothing found in this box".
--box LOW:HIGH[,LOW:HIGH...]— one interval per state, in state order (required).
--grid N,--tolerance V,--dedup V,--marginal-band V,--max-iterations N,--divergence V,--json.
$ lawsynth stability lorenz.lsworld --box 0:5,0:5,0:30
bifurcation
Sweep a free parameter and track how fixed points appear, merge, or lose stability (folds and Hopf bifurcations). Needs a parameterized world: the named parameter must appear in at least one law — a world that inlines its coefficients as constants has nothing to sweep and is rejected with a clear message.
--parameter NAME,--range MIN:MAX,--box LOW:HIGH[,LOW:HIGH...](required).
--steps N(default21),--grid N,--json.
$ lawsynth bifurcation model.lsworld --parameter mu --range 0:2 --box -3:3,-3:3
sensitivity
Integrate the forward-sensitivity equations to report how each trajectory component responds to a discovered coefficient. Each --parameters name must be a declared world parameter; a parameter that never appears in the laws has exactly zero sensitivity.
--parameters NAME[,NAME...](required),--initial NAME=VALUE... (unset components default to0).
--start T,--dt DT(default0.01),--steps N(default100),--json.
$ lawsynth sensitivity model.lsworld --parameters a,b --steps 200
lyapunov
Estimate the Lyapunov spectrum from an initial condition with the Benettin/QR method; a positive leading exponent signals chaos. This is a time-averaged estimate whose accuracy grows with --steps and shrinks with --dt.
--initial NAME=VALUE[,NAME=VALUE...]— one per state (required).
--dt DT,--steps N,--reorth K,--transient F(fraction in[0,1)),--json.
$ lawsynth lyapunov lorenz.lsworld --initial x=1,y=1,z=1
invariants
Search a bounded monomial basis for conserved quantities H(x) whose Lie derivative vanishes along the flow. The library bounds the search: an empty result means none was expressible in the degree-D library, not that none exist.
--degree D(default2),--trig(add sin/cos terms),--box LO:HI(default-1:1.5),--resolution N(default5),--tolerance T(default1e-9),--json.
$ lawsynth invariants oscillator.lsworld --degree 2
basins
Map which initial conditions flow to which attractor over a search box. Only fixed-point attractors are recognized; a limit cycle or strange attractor reads as undetermined, reported plainly.
--box LOW:HIGH[,LOW:HIGH...](required).
--resolution N,--dt DT,--max-time T,--tolerance V,--json.
$ lawsynth basins bistable.lsworld --box -2:2,-2:2 --resolution 60
Control
Turn a world into something you can estimate, reduce, or steer. estimate and reduce linearize at the first fixed point located inside --box.
estimate
Design a state estimator that reconstructs the full state from partial measurements. --poles places the error poles by Ackermann's formula (single measured state only); --kalman designs the steady-state Kalman gain (accepts several measured states).
--box LOW:HIGH[,LOW:HIGH...],--measure NAME[,NAME...](required).
--poles P[,P...](one per state, eachREALorREAL:IMAG) or--kalman [--process-var V] [--measurement-var V](covariances default to1).
--grid N,--json.
$ lawsynth estimate model.lsworld --box -2:2,-2:2 --measure x --kalman
reduce
Balanced-truncation model-order reduction of the linearization. Requires a stable (Hurwitz) fixed point inside the box — balanced truncation rejects an unstable equilibrium. B and C default to the identity (every state actuated and measured) unless --measure selects the measured states.
--box LOW:HIGH[,LOW:HIGH...](required), and exactly one of--order K(keep K states) or--tolerance T(discard states whose Hankel energy fraction is at mostT).
--measure NAME[,NAME...],--grid N,--json.
$ lawsynth reduce model.lsworld --box -2:2,-2:2 --order 2
mpc
Successive-linearization LQR-MPC: relinearize each step, design a local LQR gain from Q = q·I and R = r·I, apply the first (clamped) move, and RK4-advance the true nonlinear plant. The local LQR needs a stabilizable linearization.
--control NAME[,NAME...],--setpoint NAME=VALUE[,...],--initial NAME=VALUE[,...](required).
--dt DT(default0.05),--steps N(default200),--q W,--r W,--u-min V,--u-max V(saturate every channel),--json.
$ lawsynth mpc plant.lsworld --control u --setpoint x=1 --initial x=0
Simulate & forecast
Run a world forward — as-is, discretely, past the observed window, or across named scenarios. Trajectories print at full precision so downstream tooling can diff them exactly.
simulate
Integrate a continuous world over [start, end]. --initial, --start, --end, and --step are all required.
--initial NAME=VALUE(repeatable),--start T,--end T,--step DT.
--parameter NAME=VALUE,--input NAME=VALUE,--parameter-at TIME:NAME=VALUE,--input-at TIME:NAME=VALUE— constant and scheduled overrides.
$ lawsynth simulate model.lsworld --initial x=1 --start 0 --end 10 --step 0.05
simulate-discrete
Step a discrete-time world forward. --steps N is required; --start T defaults to 0.
--initial NAME=VALUE(repeatable),--steps N,--start T, plus the same--parameter/--input/--parameter-at/--input-atoverrides assimulate.
$ lawsynth simulate-discrete map.lsworld --initial x=0.4 --steps 100
forecast
Simulate forward to a horizon with constant parameter overrides and scheduled what-if interventions, and emit CSV. With --confidence --data, estimate per-state spread by bootstrapping the model's residuals on the observed window (deterministic seed).
--horizon T(default20),--start T,--step DT(default0.1),--initial NAME=VALUE...,--parameter NAME=VALUE...,--intervene NAME=VALUE@TIME...,--output FORECAST.csv.
--confidence --data OBS.{csv,tsv,parquet} [--time COLUMN] [--level L] [--replicates N] [--seed N] [--html FILE]— bands default to level0.95and512replicates.
$ lawsynth forecast model.lsworld --horizon 40 --step 0.05 --intervene y=0.5@20 --output forecast.csv
scenarios
Define several named what-if scenarios (each a set of NAME=VALUE@TIME interventions) plus an implicit baseline, then compare their final states and divergence in one table. With --html, overlays every trajectory on one chart per state.
--horizon T(default20),--start T,--step DT(default0.1),--initial NAME=VALUE...
--scenario NAME[:k=v@t,...](repeatable),--html FILE.
$ lawsynth scenarios model.lsworld --scenario baseline --scenario shock:y=0.5@10
Share & report
Explain, edit, package, and diff worlds — no server, no external assets.
explain
Print a plain-language and structured account of a world: what each law says, the variables and parameters it uses, and its dimensionality and complexity.
$ lawsynth explain model.lsworld
report
Render a single dependency-free HTML file: rendered equations, variable/parameter tables, and inline SVG trajectory and phase-portrait charts. With --data, overlays simulated vs observed samples and a residual strip.
--output REPORT.html,--title TEXT,--start T,--end T,--step DT,--initial NAME=VALUE...,--data OBS.{csv,tsv,parquet},--time COLUMN(defaulttime).
$ lawsynth report model.lsworld --output report.html
export
Emit a standalone, dependency-free artifact so the world runs anywhere.
--format <python|c|onnx|matlab|latex|json>(required): a runnable Python module, a C source with RK4, an ONNX-style computation-graph JSON, an Octave/MATLAB.mfile, a LaTeXalign*law system, or a documented JSON description.
--output FILE— writes to the file when given, otherwise prints to stdout.
$ lawsynth export model.lsworld --format python --output model.py
simplify
Reduce each law to its smallest equivalent form via bounded equality saturation (e-graph). The rewrites are value-preserving, so the command simulates both worlds and reports the maximum trajectory deviation as an equivalence proof.
--output SIMPLIFIED.lsworld— write the simplified-but-equivalent world.
$ lawsynth simplify model.lsworld --output model.simplified.lsworld
compose
Combine two worlds into one coupled system — the union of their variables, parameters, and laws. Colliding identifiers are namespaced with a prefix so both coexist.
--output COMBINED.lsworld(required).--prefix-a A_,--prefix-b B_— namespace every identifier of that world; without them only colliding identifiers are prefixed (defaultsa_/b_).
$ lawsynth compose predator.lsworld prey.lsworld --output coupled.lsworld
edit
Apply targeted, immutable edits in order, each producing a new re-validated world.
--output EDITED.lsworld(required).--rename OLD:NEW,--set-param NAME=VALUE,--drop-law TARGET(must be unreferenced),--scale-law TARGET=FACTOR.
$ lawsynth edit model.lsworld --output tuned.lsworld --set-param sigma=10 --rename x:pos
compare
Diff two worlds: variables and parameters added/removed/changed, per-law structural and parameter differences, and a complexity comparison. Because bundles are byte-stable, diffs reflect real changes, not run-to-run noise.
--json,--html FILE— machine-readable output or a self-contained side-by-side HTML diff.
$ lawsynth compare a.lsworld b.lsworld --html diff.html
Workspace & runs
Prepare data, scaffold and catalog worlds, track runs, and check your environment.
inspect
Print a one-line summary of a bundle — its state count, variables, and parameters — for either a continuous or a discrete world.
$ lawsynth inspect model.lsworld
profile
Inspect a dataset before discovery: per-column type and statistics, row count, time monotonicity and sampling regularity, degenerate columns, and quality warnings.
--time COLUMN(defaulttime),--json.
$ lawsynth profile obs.csv
prep
Clean a dataset before discovery with the real preprocess transforms, applied in the order given.
--output CLEAN.csv(required),--time COLUMN(defaulttime).
--trim START:END,--drop-constant,--detrend,--smooth-window N(half-window radius,N>=1),--resample DT.
$ lawsynth prep raw.csv --output clean.csv --trim 0:50 --detrend --resample 0.1
monitor
Model-based anomaly detection: simulate the world across newly observed data, standardize the residuals, and flag timesteps that drift beyond K sigma.
--data NEW.{csv,tsv,parquet}(required),--time COLUMN(defaulttime),--threshold K(default3).
$ lawsynth monitor model.lsworld --data recent.csv --threshold 3
stream
Replayable windowed online discovery: advance a window across the time column, keep a current model, and re-discover only on a sustained residual drift (a regime change), emitting an immutable JSONL change-record stream. Not incremental learning — each model is re-discovered from scratch over its triggering window.
--time COLUMN(defaulttime),--state NAME[,NAME...](required).
--window N(default60),--step M(default =--window),--threshold K(default4),--sustain W(default2),--degree D(default2),--growing,--output HISTORY.jsonl.
$ lawsynth stream obs.csv --time t --state x,y --window 60 --output history.jsonl
validate
Split observations into train/holdout by time, simulate across the holdout, and report per-state forecast skill (RMSE, MAE, R², and a skill score vs a persistence baseline) with a trust verdict.
--data OBS.{csv,tsv,parquet}(required),--time COLUMN(defaulttime),--holdout FRACTION(default0.2).
$ lawsynth validate model.lsworld --data obs.csv --holdout 0.2
backtest
Rolling-origin (walk-forward) forecast evaluation: pick N evenly-spaced origins, forecast H steps from each, and score against the actuals — reporting how error decays with horizon and a trust verdict.
--data OBS.{csv,tsv,parquet}(required),--time COLUMN(defaulttime),--origins N(default5),--horizon H(default10),--html REPORT.html.
$ lawsynth backtest model.lsworld --data obs.csv --origins 5 --horizon 10
pipeline
Run a reproducible, declarative workflow from one config file: ingest a CSV, discover, optionally validate on a holdout, then write a bundle, an HTML report, and optional exports. Deterministic and offline.
pipeline PIPELINE.tomlruns a config;pipeline --exampleprints a documented sample.
$ lawsynth pipeline study.toml
library
Manage a catalog of worlds with provenance (a SHA-256 content hash, and with --from-data the source data's hash and columns). The index defaults to ~/.lawsynth/library.tsv; override with --dir.
- Subcommands:
add,list,show,search,compare,remove.
$ lawsynth library add lorenz.lsworld --name lorenz --tags chaos,3d
runs
Browse discovery runs recorded by discover ... --track. Each run's id is derived from its data hash plus config (never a wall clock), so the same experiment resolves to the same id. Records default to ~/.lawsynth/runs/.
- Subcommands:
list,show ID,compare ID-A ID-B.--dir DIRoverrides the directory.
$ lawsynth runs list
workspace
Bundle the library index, its .lsworld bundles, and the runs registry into one self-describing, SHA-256-checked, portable archive — or unpack one.
workspace export ARCHIVE.lsworkspace [--dir DIR],workspace import ARCHIVE.lsworkspace [--dir DIR] [--force](import is non-destructive unless--force).--dirdefaults to~/.lawsynth.
$ lawsynth workspace export team.lsworkspace
presets
List the discovery presets usable with discover --preset <name>. Each preset seeds a bundle of discovery settings tuned for a domain; explicit flags override it.
$ lawsynth presets
templates
List the canonical systems available to lawsynth new.
$ lawsynth templates
new
Instantiate a canonical system as a real .lsworld bundle. With --data it also writes a deterministic synthetic observation CSV, ready to discover.
TEMPLATE(required, e.g.lotka-volterra,pendulum,van-der-pol,sir).--output WORLD.lsworld(defaults to<template>.lsworld),--data OBS.csv,--samples N(defaults per template;>= 2).
$ lawsynth new lotka-volterra --output lv.lsworld --data lv.csv
domains
Curated, self-validating domain presets. Lists them, shows a preset's reference law and discovery config, or runs a round-trip: synthesize the preset's clean trajectory, discover, and report per-state recovery. The round-trip runs on clean synthetic data — it validates the preset's search space, not robustness to real noise.
domains,domains show NAME,domains run NAME [--json].
$ lawsynth domains run damped-oscillator
doctor
Run an environment and health check: CLI version, available subcommands, offline build constraints, a writable library directory, and a self-test that round-trips a tiny world through the bundle format and engine. Prints PASS/WARN/FAIL and an overall verdict.
$ lawsynth doctor
Plugins
plugin
Package, install, and verify LawSynth plugins. Signing uses a keyed HMAC-SHA256 over the package hash — it proves integrity and authenticity relative to a shared secret, not public-key authorship.
- Subcommands:
pack DIR --output PKG.lsplugin [--sign KEYFILE],install PKG.lsplugin [--grant CAP1,CAP2] [--allow-unverified] [--force] [--dir DIR] [--trust KEYSFILE],list,verify ID,remove ID,registry <add|list>.
- Install verifies checksums and signature, grants a subset of declared capabilities, and installs into
~/.lawsynth/pluginsby default. Unsigned packages install only with--allow-unverifiedand are marked untrusted.
$ lawsynth plugin install analysis.lsplugin --grant read-bundle
See also
- The end-to-end loop, in five commands: Getting started.
- What each pillar is for, with SDK equivalents: Capabilities.
- Why the output is reproducible: Why determinism.