rystic

Getting started

Installation

A Rystic simulator is a single static binary — a local, deterministic twin of a real service. You run it, point your agent or test harness at localhost instead of the live API, and get the one thing production and sandboxes can't: the same state, every run.

There's nothing to configure globally. Each simulator ships as its own binary with an identical control plane, so once you've run one you've run them all.

Prerequisites

  1. A 64-bit macOS, Linux, or Windows machine (the binaries are static, no runtime needed).
  2. The client library for the service you're testing — the same one you already use against the real API. Rystic mirrors the real request/response surface, so your existing code points at it unchanged.
  3. curl (or any HTTP client) for driving the control plane.

1. Get a simulator

Every simulator is distributed as a standalone executable named after its service — stripe-twin, kalshi-twin, and so on.

Builds are in limited release. Request access and you'll get a link to the archives, one per platform: darwin_arm64, darwin_amd64, linux_amd64, linux_arm64, and windows_amd64 / windows_arm64 zips. Then verify and unpack:

shasum -a 256 -c checksums.txt --ignore-missing
tar xzf kalshi-twin_0.0.4_darwin_arm64.tar.gz

The archive contains the binary, a HOWTO.md, starter seed scenarios, check scripts, and LICENSE.txt — the agreement governing use.

2. Run it

./stripe-twin                       # serves on :8080
RYSTIC_ADDR=:9000 ./stripe-twin     # or pick a port

The simulator now speaks the real service's API on that port.

Release builds are license-gated: put the rystic-license.json we sent you in the working directory, or point RYSTIC_LICENSE at it. Verification is fully offline — no phone-home — and runs once at startup, so a running simulator is never interrupted. Renewal is a new license file, not a new binary.

3. Point your agent at it

Change one thing — the base URL — and run your code exactly as you already do:

export STRIPE_API_BASE=http://localhost:8080

Simulators accept any credentials, so no real keys are required. The specific env var or config field depends on the service; see each simulator's guide.

4. The control plane

Every simulator adds a small admin API under /_rystic/ alongside the real surface. This is how you set up a world, freeze time, and inspect results.

EndpointWhat it does
POST /_rystic/resetwipe all state back to empty
POST /_rystic/seedload a state snapshot (JSON body)
POST /_rystic/clockset or advance the simulator's clock
POST /_rystic/seed-rngfix the RNG for fully deterministic ids
GET /_rystic/inspectdump the entire current state
GET /_rystic/registerslist every seedable state family and its fields

GET /_rystic/registers is the fastest way to learn what a given simulator can be seeded with.

5. The regression loop

The pattern is the same for every simulator: reset, seed a known world, run your agent, assert on the result.

curl -X POST localhost:8080/_rystic/reset
curl -X POST localhost:8080/_rystic/seed -d @scenario.json
# ... run your agent ...
curl -s localhost:8080/_rystic/inspect          # assert on final state

Because state is in-memory and deterministic, reset takes milliseconds and the same seed produces the same behavior every time. Wire it into CI — each simulator is a single dependency-free binary.

Next steps

  1. Stripe simulator — charges, refunds, checkout, customers.
  2. Kalshi simulator — a real matching engine for trading bots.