# Installation

From nothing to a running simulator.

Run a [simulator](https://www.rystic.ai/docs/concepts/glossary.md#simulator) on your machine and point your app, your tests or your agent at `localhost`. Same state every run.

Running an agent with Slack MCP in [Harbor](https://www.rystic.ai/docs/concepts/glossary.md#harbor)? Start with [Slack MCP in Harbor](https://www.rystic.ai/docs/slack-harbor.md) for the licensed [environment](https://www.rystic.ai/docs/concepts/glossary.md#environment) image, tool connection and episode reset. The standalone installation below is for HTTP API clients.

New to the words these pages use? The [Glossary](https://www.rystic.ai/docs/concepts/glossary.md) defines each one, from simulator, environment and scenario to seed and register, in a sentence.

## What you need

1. Mac or Linux, 64-bit. (Windows: zip on request.)
2. A Rystic account. The install signs you in through the browser; sign up there with GitHub or Google and a new account starts on Free, 10 hours a month. [Plans and API keys](https://www.rystic.ai/docs/licensing.md) explains the plans.
3. A network connection while a simulator runs: it checks in with Rystic. Docker only if you want containers later.

Enterprise, with a license file or install link instead? See [Enterprise: license files](https://www.rystic.ai/docs/licensing.md#enterprise-license-files).

## Install

```bash
curl -fsSL https://www.rystic.ai/install.sh | sh
```

The install ends by running `rystic login`. It opens your browser on www.rystic.ai, or prints a link and a code on a headless or SSH machine. Sign up or sign in, check the code, click **Approve**; a new account gets an organization on Free. The CLI stores a Free API key that does not expire.

```
installed rystic 0.0.34 → /usr/local/bin/rystic     # or ~/.local/bin; RYSTIC_BIN overrides
to sign in, open: https://www.rystic.ai/device?...
confirm the code on the page reads ABCD-1234 — waiting for approval (Ctrl-C to stop)
approved · Free plan
```

`RYSTIC_NO_LOGIN=1` skips the login step; run `rystic login` later.

### Without a browser: CI and agents

[Create an API key](https://www.rystic.ai/docs/licensing.md#get-an-api-key) and sign the CLI in with it:

```bash
rystic login rys_…
```

`rystic login --token-stdin < key.txt` keeps the key out of your shell history. Success ends like this:

```
signed in: the API key is stored in /Users/you/.rystic/token
docker login registry.rystic.ai: ok — `docker pull registry.rystic.ai/<product>:<version>` and `rystic run --runner docker` now work
next: rystic run <product>  ·  rystic docs
```

The key is stored in `~/.rystic/token`, readable by you only, and never printed. If Docker isn't running, the last line says `skipped` and names the command to run later; the native runner doesn't need it.

## Check everything

```bash
rystic doctor stripe-twin
```

Every `✗` is followed by a `→` line with the command that fixes it. `!` is a warning, not a failure. Before your first pull, `✗ install  no installed version` is normal — the first `run` pulls for you.

`doctor` checks your API key first: `✓ api key` names the organization and plan it belongs to. `✗ api key plan` means your plan leaves that simulator out; a refused key exits 11 with the same message `rystic pull` prints.

## First run

```bash
rystic run stripe-twin
```

```
stripe-twin 0.0.18 (model 95c5dbcd) → http://localhost:8080  [native default]
```

That line is the simulator's identity: version, model hash, URL, runner. On an Enterprise license it also names the licensee and expiry. Port is 8080 unless you say otherwise; `--port 0` takes a free one and prints it. `Ctrl-C` stops it.

In the background:

```bash
rystic run stripe-twin -d --name dev --port 0
rystic ps
rystic stop dev
```

## Make a first request

Second terminal — create a charge, refund it, read both back:

```bash
CH=$(curl -s localhost:8080/v1/charges -u sk_test_twin: \
  -d amount=2000 -d currency=usd -d source=tok_visa | jq -r .id)
# -> ch_…

curl -s localhost:8080/v1/refunds -u sk_test_twin: -d charge=$CH

curl -s localhost:8080/v1/charges/$CH -u sk_test_twin:
# -> "refunded": true, "amount_refunded": 2000

curl -s 'localhost:8080/_rystic/egress?tail=5'
# -> charge.succeeded, refund.created, charge.refunded, … — the webhooks it would have sent
```

Any `Authorization` header works, and none of your requests leave your machine. Point your SDK's base URL at `http://localhost:8080` and your existing code runs unchanged — each simulator page shows the one-line client change.

## Start from a named scenario

Every simulator ships [named scenarios](https://www.rystic.ai/docs/concepts/glossary.md#named-scenario) compiled into the binary — no data files, no network.

A simulator boots empty unless you name a [scenario](https://www.rystic.ai/docs/concepts/glossary.md#scenario), and `reset` clears state and reseeds the simulator's built-in records, the state it boots in without one. Stripe's scenario is `design_studio`: Website Design Contractors' account, 30 customers and 269 charges since November 2024. The same studio is on Lob, PayPal, Resend and Slack. Naming a scenario boots the same state on every plan:

```bash
rystic run stripe-twin --scenario design_studio
```

GitHub and Kalshi ship more scenarios; `GET /_rystic/scenarios` lists them with a one-line summary each, and the binary's `--list-scenarios` prints the same menu. A running simulator takes a scenario without a restart. This [resets](https://www.rystic.ai/docs/concepts/glossary.md#reset) state, applies the scenario, answers `204`:

```bash
curl -X POST localhost:8080/_rystic/scenario \
  -H 'content-type: application/json' -d '{"name":"design_studio"}'
```

The same call works on every simulator; only the scenario names differ. The Kalshi simulator holds no markets until you give it some, so a trading bot needs a scenario before it can place an order — see [Kalshi simulator](https://www.rystic.ai/docs/simulators/kalshi.md#quickstart). [Control plane and plans](https://www.rystic.ai/docs/control-plane.md#what-each-plan-boots) has what a simulator boots and what `reset` keeps.

## Next

1. [Agent quick start](https://www.rystic.ai/docs/agent-quick-start.md) — hand the simulator to a coding agent.
2. [Docker builder](https://www.rystic.ai/docs/docker-builder.md) — pick your simulators and copy a ready `rystic.yaml`, CLI lines and Compose file.
3. [The rystic CLI](https://www.rystic.ai/docs/cli.md) — every command, flag, exit code.
4. [Control plane and plans](https://www.rystic.ai/docs/control-plane.md) — every `/_rystic` route and the plan that serves it.
5. [Docker](https://www.rystic.ai/docs/docker.md) — the same simulator as a container; your API key is the credential.
6. [Integration tests in CI](https://www.rystic.ai/docs/integration-testing.md) — the simulator as a GitHub Actions service container.

## If it didn't work

| you saw | it means | do this |
|---|---|---|
| `that is not an API key` (exit 2) | the key was cut short or mistyped | copy it again from [Account → API keys](https://www.rystic.ai/account/api-keys), or create a new one |
| exit 11, `release endpoint refused (…): invalid_token`, `revoked`, `org_deleted`, `key_expired` or `product_not_in_plan` | the key is unknown, revoked or expired, or its plan leaves that simulator out | the next line says where the key came from and what to do; [When the CLI refuses the key](https://www.rystic.ai/docs/licensing.md#when-the-cli-refuses-the-key) |
| `command not found: rystic` | the install folder isn't on your `PATH` | open a new terminal; the installer printed the folder |
| the simulator exits, naming the monthly limit, a spend cap, or a revoked key | a plan or key problem | see [What stops a simulator](https://www.rystic.ai/docs/licensing.md#what-stops-a-simulator) |
| exit 3 with `no license file found … — or sign in with a sim token` | `pull`, or the first `run`, found no license and no usable key | `rystic login rys_…` |
| exit 3, or any `license` / `signature` error | an Enterprise license problem | see [License errors](https://www.rystic.ai/docs/licensing.md#license-errors) |
| exit 8, runtime unavailable | Docker isn't running (only with `--runner docker`) | start Docker, or drop the flag — native needs none |

Stuck anyway? Send us `rystic doctor` output — it names the broken piece without revealing your key.

---

Source: https://www.rystic.ai/docs/installation · Markdown: https://www.rystic.ai/docs/installation.md
