LawSynthGitHub

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-form is the noise-robust integral form (renders coefficient laws, writes no bundle).
  • --preset NAME — seed the config from a domain preset (see lawsynth presets); explicit flags override it.
  • --degree N — polynomial library degree. --threshold VALUE — sparsity cutoff (default 0.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 for lawsynth 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...] (default 0.05).
  • --folds K (default 3), --scheme forward|rolling (default forward), --metric r2|rmse (default r2), --time COLUMN (default time).
  • --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 (default 21), --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 to 0).
  • --start T, --dt DT (default 0.01), --steps N (default 100), --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 (default 2), --trig (add sin/cos terms), --box LO:HI (default -1:1.5), --resolution N (default 5), --tolerance T (default 1e-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, each REAL or REAL:IMAG) or --kalman [--process-var V] [--measurement-var V] (covariances default to 1).
  • --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 most T).
  • --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 (default 0.05), --steps N (default 200), --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-at overrides as simulate.
$ 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 (default 20), --start T, --step DT (default 0.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 level 0.95 and 512 replicates.
$ 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 (default 20), --start T, --step DT (default 0.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 (default time).
$ 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 .m file, a LaTeX align* 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 (defaults a_ / 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 (default time), --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 (default time).
  • --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 (default time), --threshold K (default 3).
$ 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 (default time), --state NAME[,NAME...] (required).
  • --window N (default 60), --step M (default = --window), --threshold K (default 4), --sustain W (default 2), --degree D (default 2), --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 (default time), --holdout FRACTION (default 0.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 (default time), --origins N (default 5), --horizon H (default 10), --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.toml runs a config; pipeline --example prints 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 DIR overrides 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). --dir defaults 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/plugins by default. Unsigned packages install only with --allow-unverified and are marked untrusted.
$ lawsynth plugin install analysis.lsplugin --grant read-bundle

See also

  • What each pillar is for, with SDK equivalents: Capabilities.