Skip to Content
Licensing

Getting started

Licensing

Editions

Free editionLicensed
SimulatorsSlack, GitHubevery simulator your license names
Setupdownload one binary, run itthe rystic CLI plus a license
Worldone fixed world per simulatorthe full scenario pack, seeds, tapes, --live
Control planeversion, routes, reset, network only; the rest is compiled outseed, scenario, clock, inspect, egress, UI
Dockernoregistry.rystic.ai, the license is the credential
Reports usageyes — what it sendsno; the CLI records release downloads only (details)

Getting a license

Request access. A license reaches you one of two ways:

  1. An install linkhttps://www.rystic.ai/api/install?l=…. The long l= value is the license; one pasted line installs the CLI and activates it.
  2. A license file, named like rystic-license-acme-2026.json.

Both carry the same signed license: licensee, the products it covers, and an expiry date. Installation has the commands for each.

Activation

rystic login ./rystic-license-acme-2026.json
license:   /Users/you/.rystic/rystic-license.json
licensee:  Acme
products:  [stripe-twin, kalshi-twin]
expires:   2027-08-19 (valid)
  1. login verifies the license and, if Docker is running, logs it in to registry.rystic.ai. --no-docker skips that half.
  2. rystic license activate <file> is the same command minus the Docker half. You will meet both spellings.
  3. rystic license prints the active license and its claims.

Where it lives

The license is verified on your machine against a key built into the CLI and parked in $RYSTIC_HOME (default ~/.rystic). Every later command finds it there without a flag. Nothing phones home to check it.

To point a single command or a container at a different license, set RYSTIC_LICENSE to a file path — or to the license itself, JSON or base64. That is how a container gets it; no image ever carries one. Docker has the mounts.

Expiry and renewal

rystic license and rystic doctor show the expiry date. Past it, commands answer license_expired; ask Rystic for a renewal and rystic login the new file. rystic login --force activates a license even when it is expired.

License errors

you sawit meansdo this
curl: … error: 403 from the install linkthe link’s l= value was cut shortpaste the full link again, or use the license file
no license file found … (exit 3)no license activated on this machinerystic license activate ./rystic-license-acme-2026.json
signature does not verifythe file was altered or re-encoded in transitre-download it exactly as sent; ask for a fresh one
license_expiredpast its dateask Rystic for a renewal
asset_not_found … carries no build for this licensethat version was never cut for youask Rystic, or rystic pull -version <x.y.z> one you have

Exit code 3 is always a license problem. rystic doctor names the broken piece without revealing your license.

Free edition

A downloadable twin you can run with nothing else: no license, no signup, no command-line tool, no config. The download is the whole setup.

Get it

One fixed link per simulator. Every release replaces the build behind it; there is no version to pick.

SimulatorLinkWorld
Slack/dl/free/slack-twindesign_studio
GitHub/dl/free/github-pulls-twingithub-pulls_open_queue
tar xzf slack-twin-free-darwin-arm64.tar.gz
./slack-twin
#  expect: rystic: slack-twin <ver> listening on [::]:8080 (model sha256:…) — free edition, world design_studio
curl -s localhost:8080/_rystic/version
#  expect: {..."edition":"free",..."product":"slack-twin",...,"world":"design_studio"}

Point your client’s base URL at http://localhost:8080https://slack.com/api/ becomes http://localhost:8080/api/, https://api.github.com becomes http://localhost:8080. Any Authorization header works. Port taken? --addr :9000.

What it is

  1. The modeled API, reads and writes alike. Post a message, open a pull request, submit a review — the world moves as the licensed twin’s does.
  2. One canonical world per simulator, loaded at start: the table above names it. POST /_rystic/reset or a restart puts it back.
  3. GET /_rystic/version and GET /_rystic/routes, so a client can tell what it is talking to.
  4. /_rystic/network fault injection.

What it is not

The control plane is compiled out, not switched off. Every one of these answers 404 with a body naming the paid unlock:

RemovedWhat the licensed twin does with it
POST /_rystic/seed, /_rystic/scenario, /_rystic/clock, /_rystic/seed-rngset the world, pin the clock, choose any of the pack’s scenarios
GET /_rystic/inspect, /_rystic/egress, /_rystic/events, /_rystic/registers, /_rystic/uidump state, read rendered webhooks, watch the twin live
/_replay/*, --scenario (ignored), --seed, RYSTIC_SCENARIO, RYSTIC_SEED, --livetapes, boot-time worlds, live feeds

State is visible only through the modeled API’s own GETs. sweep, docker via the registry, and the rystic CLI’s run/pull are licensed too.

What it reports

The free edition phones home; the licensed twin never does. At start, once an hour, and on a clean stop it POSTs to www.rystic.ai/api/free-metrics:

  1. product, version, edition, world
  2. operating system and architecture
  3. a random install id, written to .rystic-free-id beside the binary on first run
  4. the event (start, heartbeat, stop) and seconds since start
  5. request counts per API route

Nothing from request bodies, no hostnames, and the server stores no IP. There is no opt-out; an unreachable endpoint changes nothing about how the twin runs. The EULA in the archive (LICENSE.txt §13) says the same.

Upgrading

A license is the same binary plus the control plane, the scenario pack, seeds, tapes, --live, sweep, and docker via registry.rystic.ai. Get a license, then rystic pull slack-twin or rystic pull github-pulls-twin.

Last updated on