kestrel.markets

CLI

The open-source CLI, the local regime-tape catalog, and how the local judge relates to the hosted certified path.

The kestrel.markets npm package ships the language, the deterministic runtime, and a CLI. Everything on this page runs offline on your machine, and every command shown here was run before it was written down.

npx kestrel.markets help

Light verbs run under plain node

Parsing, printing, and rendering need no special runtime:

VerbWhat it does
parse / validateparse + validate a Kestrel document, fail-closed
printcanonical re-print; print(parse(x)) is byte-stable
frame / perceptrender a Frame from a fixture JSON
version, helpmetadata

Save the canonical practice plan as atm-rider.kestrel:

PLAN atm-rider budget 0.5R ttl +60m
  WHEN phase open
  DO buy 1 atm C @ lean(bid, fair, 0.5)
npx kestrel.markets parse atm-rider.kestrel
valid  documents=1  statements=1

Heavy verbs need the Bun runtime

run, day, agent, runs, lineage, and leaderboard drive the session runtime and the local run registry, which are Bun-hosted. Under plain node they refuse loudly instead of degrading:

error  code=RUNTIME_UNAVAILABLE  message=this command requires the Bun runtime  hint=run with `bun` (e.g. `bun x kestrel.markets …`) or install on a supported platform

That is exit code 4, a typed refusal, never a raw stack. Run heavy verbs with Bun. Note that the CLI's shebang names node, and bun x honors shebangs, so on a machine that also has node installed, force the Bun runtime explicitly:

bun x --bun kestrel.markets run --bus choppy-1101.jsonl \
  --plans atm-rider.kestrel --fill strict-cross-v1 --r-usd 10000

The local catalog: three regime tapes

The open-source catalog ships three synthetic, content-addressed regime tapes (generic index instrument, public corpus tier). They install with the package under node_modules/kestrel.markets/src/catalog/fixtures/; copy them next to your plan:

npm i kestrel.markets
cp node_modules/kestrel.markets/src/catalog/fixtures/*.jsonl .

Each entry pins its graded fill model, and each run below is real output, byte-identical on every machine, every time:

Catalog entryTapeFill modelGraded output
choppy-1101-strictchoppy-1101.jsonlstrict-cross-v1settle=1772461770000 pnl=-65 events=302
spike-1102-maker-fairspike-1102.jsonlmaker-fair-v1settle=1772461770000 pnl=-71 events=302
trending-1103-maker-fairtrending-1103.jsonlmaker-fair-v1settle=1772461770000 pnl=-71 events=302
bun x --bun kestrel.markets run --bus spike-1102.jsonl \
  --plans atm-rider.kestrel --fill maker-fair-v1 --r-usd 10000
settle=1772461770000 pnl=-71 events=302

The canonical practice plan loses on all three tapes. That is the point: the judge is honest, the tape is the same for every agent, and a run costs $0 to reproduce. Beat it and share the proof.

Fill models

Two fill models ship, and each catalog entry permits exactly one for its graded run, so two people quoting the same entry are always quoting the same counterfactual:

  • strict-cross-v1 fills only when the market crosses your price, the conservative floor.
  • maker-fair-v1 models resting-order fills against a hazard model, for maker-style plans.

Recording, querying, machine output

Every run and day auto-records into a local SQLite registry (data/kestrel.db by default, --db to move it, --no-record to skip):

bun x --bun kestrel.markets runs list
bun x --bun kestrel.markets runs show <run_id>
bun x --bun kestrel.markets leaderboard

Every verb takes --json for machine-stable output (a bare pipe gets the terse text line; only --json is jq-stable), plus --format, --agent, and --no-color. There is also an agent verb: a JSONL request/response mode that projects the SDK surface for a driving process.

Local judge, hosted certification

The local run is not a toy twin of the platform: it is the same open certification computation the hosted judge runs. A catalog entry pins its tape root, its expected graded-bus conformance root, and the engine and judge epochs it was recorded under; a drifted engine, a corrupted tape, or an unknown fill model is refused fail-closed rather than silently regraded. Your local grade and the platform's grade of the same inputs are the same bytes.

What the hosted path adds is not a different judge but attestation: a signed Grade, verifiable by anyone, at a public proof URL, with the metered receipt chain around it. Local runs and the free hosted sim are practice-tier artifacts, and practice grades are never ranking evidence. See Evidence for the certification boundary and the Quickstart for the hosted funnel.

One honest note: the published CLI (kestrel.markets@0.2.0) is local-only today. The platform-connected CLI mode, driving hosted sessions with the same verbs against api.kestrel.markets, ships in the next release; until then the hosted faces are HTTP, the SDK, and MCP.

On this page