# OpenSwap CLI documentation — all pages

> Canonical per-page URLs: https://leokit.dev/cli/docs/<slug>.md

---
title: Quickstart
description: How to swap crypto from your terminal in about two minutes with OpenSwap — no account, no wallet connection, no browser extension.
order: 1
version: 0.1.0
---

# Quickstart

OpenSwap is a free, open-source command-line tool that swaps crypto across
30+ blockchains — Bitcoin, Ethereum, Solana, and most major chains. You don't
create an account, you don't connect a wallet, and the tool never touches
your private keys. This page takes you from nothing to your first swap in
about two minutes.

## Run it

If you have Node.js 20 or newer, you already have everything you need:

```bash
npx openswap@latest
```

That opens a simple menu. If you'd rather install it properly:

```bash
npm install -g openswap
openswap doctor
```

`doctor` checks that your terminal, credentials, and connection are all
working. Either way, the tool works immediately — a free community key is
built in, so there is nothing to sign up for.

## Get your first quote

A quote compares prices across every available route and costs nothing. It's
read-only — no wallet, no risk:

```bash
openswap quote -a 100 -f arb:USDC -t btc:BTC
```

That means: "quote 100 USDC on Arbitrum into native Bitcoin." Prices stream
in live from every provider (Chainflip, THORChain, Maya, NEAR, Relay, and
more) and are sorted by what you'd actually receive after fees.

You can name assets almost any way that feels natural: `USDC` (the tool asks
which network), `usdc on base`, `base:USDC`, or the fully precise
`CHAIN.SYMBOL-ADDRESS` form.

Here's what a quote looks like when you pipe it to a script — real output
from a real run:

```
protocol	expected_receive	usd	fees_usd	eta_seconds
rango	0.00150716	99.47	0.4698	30
relay	0.00150625	99.41	0.5298	8
near	0.00150247	99.16	0.7797	45
chainflip	0.00150216	99.14	0.7997	90
```

## Make your first swap

```bash
openswap swap -a 100 -f arb:USDC -t btc:BTC
```

The tool walks you through it step by step:

1. **Pick a route** from the live list.
2. **Enter the destination address** — where you want the swapped funds sent.
3. **Enter the address you'll pay from.** This also becomes your refund
   address, so if anything fails, funds come back to you.
4. **Review everything and type `SWAP`** to confirm.
5. **Pay the deposit address** from any wallet you already use — scan the QR
   code the terminal shows, or copy the address. Your wallet does the paying;
   OpenSwap never holds your money.

Before the payment screen even appears, the swap is saved to a receipt on
your machine. That means you can close the terminal at any point and nothing
is lost:

```bash
openswap resume          # picks up your latest swap and keeps watching it
openswap history         # every swap you've ever made from this machine
```

## Want to practice first?

`openswap tour` walks you through a complete swap in two minutes with real
prices and a clearly simulated payment — nothing real can move. There's also
a full sandbox: see [Test mode](https://leokit.dev/cli/docs/test-mode).

## Where to next

- [Command reference](https://leokit.dev/cli/docs/commands) — every command and flag on one page
- [Keys, fees & founding keys](https://leokit.dev/cli/docs/keys-and-fees) — what swaps cost and how to pay less
- [Security & custody](https://leokit.dev/cli/docs/security) — why this is safe

---

---
title: Command reference
description: Every OpenSwap command, flag, output mode, exit code, and environment variable, explained in plain English on one page.
order: 2
version: 0.1.0
---

# Command reference

Every OpenSwap command on one page. If you're new, start with the
[Quickstart](https://leokit.dev/cli/docs/quickstart) — this page is for
looking things up.

A note on examples: placeholders are written in angle brackets, like
`<AMOUNT>` or `<ADDRESS>`. Replace them with real values — never paste a
placeholder into a command that moves money.

## How output works

OpenSwap adapts its output to where it's running. In a normal terminal you
get the interactive experience. Piped into another program, it switches to
clean, stable text automatically. For scripts and bots there are explicit
modes:

| Flag | What you get |
| --- | --- |
| *(nothing, in a terminal)* | Interactive mode with prompts |
| *(nothing, piped)* | Plain text, tab-separated, no prompts ever |
| `--plain` | The same stable plain text, explicitly |
| `--json` | Exactly one JSON result object on stdout |
| `--jsonl` | One JSON object per line (for streaming commands) |
| `--no-input` | Never prompt; missing input becomes an error |
| `--no-color` | No colors (the `NO_COLOR` env var works too) |

The JSON result always has the same shape:
`{schema_version, command, ok, data | error, warnings, meta}`. Errors include
a machine-readable `code`, a human `message`, whether the problem is
`retryable`, an honest `funds_may_have_moved` flag, and `actions` — safe
next commands to run.

## Exit codes

These are frozen — you can script against them and they will not change:

`0` success · `1` internal error · `2` bad usage · `3` auth/config problem ·
`4` no route found or policy said no · `5` temporary upstream problem (retry) ·
`6` signer problem · `7` broadcast problem · `130` you pressed Ctrl-C.

## Everyday commands

### `openswap`
Run with nothing else, it opens the menu: pick a pair, watch routes stream
in, trade.

### `openswap quote -a <amount> -f <from> -t <to>`
Compare prices across every route. Read-only and free — no wallet involved.
Routes are sorted by what you'd actually receive, and fees are shown
honestly: if a provider doesn't price a fee, it says *not priced* instead of
pretending it's zero. Useful extras: `--slippage-bps <n>` to set your
slippage tolerance, `--refresh` to refetch the asset list.

### `openswap swap -a <amount> -f <from> -t <to>`
The full swap, start to finish: compare routes, lock one, get a deposit
address and QR, pay from any wallet, and track to delivery. In scripts, you
must be explicit: `--to-address`, `--refund-address`, and `--yes` are all
required, because creating a deposit address is a real action. `--dry-run`
rehearses everything without creating anything. `--protocol <name>`
preselects a route.

### `openswap status [id] [--watch]` and `openswap resume [id]`
Check on a swap, or watch it live until it finishes. With no id, they use
your latest swap. A swap ends as `success`, `failed`, `refunded`, or —
if a deposit was never paid — `deposit_expired`.

### `openswap history`
Every swap you've made from this machine, newest first. Pick one to see full
details and live tracking.

### `openswap assets list` and `openswap assets search <query>`
Browse or search the 7,000+ supported assets. `--chain <C>` filters to one
chain; results are cached for a day.

### `openswap balances <address> --chains A,B,C`
Check what an address holds across several chains at once.

## Keys and configuration

### `openswap auth login | status | logout`
Store your own API key in the operating system's keychain, see which key is
active, or remove it. The key is typed in privately — never passed as a
flag, never written to a file. For CI, set `OPENSWAP_API_KEY` instead. See
[Keys, fees & founding keys](https://leokit.dev/cli/docs/keys-and-fees).

### `openswap config list | get | set`
Non-secret settings only. Anything that looks like a secret is refused —
secrets belong in the keychain or environment.

### `openswap doctor`
A health check: runtime, terminal capabilities, credential validity, API
reachability, and storage. Run it first when something seems off.

## Practice and automation

### `openswap tour`
A guided two-minute walkthrough with real prices and a simulated payment.
Nothing is saved and nothing real can move.

### `openswap test …`
The sandbox. `on`/`off` toggles it, `pay` simulates paying a deposit,
`fund` sets a pretend balance, `scenario` picks a default outcome, `reset`
starts a fresh simulated world. Full guide:
[Test mode](https://leokit.dev/cli/docs/test-mode).

### `openswap watch -a <amount> -f <from> -t <to> --jsonl`
A live price feed: quotes stream continuously as JSON lines. Built for bots.
`--once` exits after the first full round.

### `openswap bot init | check | run`
Policy-gated automation: `init` builds your policy file interactively,
`check` tests a trade against it with zero side effects, `run` executes
(simulating first by default). Full guide:
[Bots & automation](https://leokit.dev/cli/docs/bots).

### `openswap wallet setup | status`
The optional signing wallet, used only for routes that can't work with a
deposit address. Setup recommends creating a fresh dedicated wallet rather
than importing your main one.

### `openswap agent setup | status | docs`
For AI agents: `setup` installs the Claude Code skill, `docs` prints the
complete machine contract. See
[For AI agents](https://leokit.dev/cli/docs/agents).

### `openswap receipts list | show | export <id>`
The raw receipt store — durable local records of every swap. `export`
prints a receipt as JSON, handy for support. See
[Receipts & data on disk](https://leokit.dev/cli/docs/receipts).

### `openswap feedback`
Send a bug or idea straight to the team. It shows you exactly what
diagnostic info would be included and asks before sending anything.

## Environment variables

| Variable | What it does |
| --- | --- |
| `OPENSWAP_API_KEY` (or `LEOKIT_API_KEY`) | Your API key, for CI and bots. Lookup order: environment → keychain → built-in community key |
| `OPENSWAP_TEST_MODE` | `1` forces the sandbox on, `0` forces it off |
| `OPENSWAP_TEST_TIMESCALE` | Speeds up simulated swaps (CI and agents) |
| `OPENSWAP_TEST_SEED` | Makes simulated outcomes reproducible |
| `OPENSWAP_EVM_PRIVATE_KEY` | Bot signer hot key (prefer the keystore) |
| `OPENSWAP_EVM_KEYSTORE` + `OPENSWAP_EVM_KEYSTORE_PASSWORD` | Encrypted keystore signer for bots |
| `OPENSWAP_EVM_RPC_URL` | Your own RPC endpoint for the signing lane |
| `NO_COLOR` | Disables colors everywhere |

## Which platforms work?

macOS and Linux are fully supported. On Windows, run it under WSL — the
native Windows credential store isn't wired up yet, so use the
`OPENSWAP_API_KEY` environment variable there.

## Our compatibility promise

Scripts you write today keep working: JSON fields are only ever added, never
changed in place; exit codes are frozen; renamed commands get a deprecation
window with warnings first.

---

---
title: Test mode & tour
description: How to practice crypto swaps with zero risk: OpenSwap test mode simulates the whole exchange, with magic amounts to script any outcome.
order: 3
version: 0.1.0
---

# Test mode & tour

You can try everything OpenSwap does without risking a cent. There are two
ways in: a guided tour, and a full sandbox.

## The two-minute tour

```bash
openswap tour
```

The tour walks you through a complete swap with **real live prices** and a
clearly simulated payment. No deposit address is created, nothing is saved,
and no funds can move. If it's your first run, the menu puts the tour right
at the top.

## The sandbox: test mode

```bash
openswap test on     # everything now runs simulated — you'll see a TEST badge
openswap swap        # do a full swap; the deposit "pays itself" after a few seconds
openswap test off    # back to the real world
```

Test mode runs the entire CLI against a simulated exchange: streaming
quotes, deposit addresses, receipts, tracking — all of it, with pretend
wallets and balances. It exists so you can learn the tool risk-free, and so
bots and CI pipelines can rehearse thousands of swaps before touching real
money.

## How realistic is it?

Very — that's the point. The production code paths run unmodified; only the
outside world is simulated. Quotes stream the same way, amounts use the same
precision, and addresses go through the same validation. Prices are a
snapshot with a little noise, not live.

Three things keep it safely separate from your real swaps:

- Simulated receipts are prefixed `ost_` and marked `simulated`, and all
  test data lives in its own folder — your real receipts can't be touched.
- Every screen shows a **TEST** badge, and the payment screen deliberately
  shows no QR code (a scannable code for a fake address is the one thing
  someone might actually pay).
- Test mode never contacts the real API at all.

## Choosing how a practice swap ends

Deposits auto-pay after about 8 seconds, or trigger payment yourself:

```bash
openswap test pay
```

Want a specific outcome? End the amount with a magic value:

| Amount ends in | What happens |
| --- | --- |
| `.13` | The swap fails after payment |
| `.19` | The swap refunds back to the sender |
| `.07` | The deposit window is only 15 seconds |
| `.23` | Confirmations come in slowly |

Or set a default story for every practice swap:
`openswap test scenario refund` (choices: `happy`, `refund`, `fail`,
`expire`, `slow`).

## The rest of the toolbox

```bash
openswap test status               # current scenario, seed, balances, cheatsheet
openswap test fund BASE:USDC 500   # give yourself a pretend balance
openswap test reset                # brand-new simulated world
```

For CI: `OPENSWAP_TEST_TIMESCALE=50` runs the simulation 50× faster (a full
swap story finishes in under a second), and `OPENSWAP_TEST_SEED` makes
outcomes reproducible run after run.

## For AI agents

Everything works identically in machine mode (`--json --yes`), every JSON
response is marked `simulated`, and magic amounts make outcomes
deterministic — which means an agent can prove a change works end to end
before claiming it's done:

```bash
OPENSWAP_TEST_MODE=1 OPENSWAP_TEST_TIMESCALE=100 openswap swap \
  --from eth:usdc --to base:usdc --amount 25 \
  --to-address 0x1111111111111111111111111111111111111111 \
  --refund-address 0x2222222222222222222222222222222222222222 --yes --json
```

---

---
title: Bots & automation
description: How to automate crypto swaps safely with OpenSwap: policy files that set hard limits, a live price feed, and simulation before any real trade.
order: 4
version: 0.1.0
---

# Bots & automation

OpenSwap is built for unattended trading — but with one hard rule at its
core: **a script or an AI may suggest a trade, but only your written policy
can approve one.** A policy is a small JSON file of limits you set once:
which assets, which destination, how much per trade, how much per day. If a
proposed trade breaks any rule, it's rejected cleanly (exit code `4`) and
your loop just moves on.

## Setting up your policy

```bash
openswap bot init
```

That walks you through the choices interactively and can test the result
against live routes on the spot. A finished policy looks like this:

```jsonc
{
  "version": 1,
  "name": "my-strategy",
  "mode": "enforce",                    // "monitor" logs violations without blocking
  "assets":       { "allow_from": ["ARB.USDC-0x…"], "allow_to": ["BTC.BTC"] },
  "protocols":    { "allow": ["chainflip", "near"] },
  "destinations": { "allow": ["bc1q…"] },
  "limits": {
    "max_trade_usd": 250,
    "max_daily_volume_usd": 1000,
    "max_total_fee_usd": 5,
    "max_quote_age_seconds": 20,
    "cooldown_seconds": 60
  },
  "kill_switch_file": "./STOP"          // create this file and everything halts
}
```

One important behavior: **unknown values fail closed.** If a route's USD
value or fees can't be priced, and one of your limits depends on it, the
trade is rejected. The policy never guesses in your favor's opposite.

## The loop

A working bot is five commands:

```bash
openswap watch -a 100 -f arb:USDC -t btc:BTC --jsonl    # 1. live price feed
openswap bot check --policy p.json … --json             # 2. would this trade pass? (no side effects)
openswap bot run   --policy p.json … --json             # 3. execute — simulates by default
openswap bot run   --policy p.json … --json --live      # 4. execute for real
openswap status <receipt> --json                        # 5. watch it finish
```

`bot run` binds quotes to your signer's address, filters to your allowed
protocols, checks the policy, simulates every transaction — and only
broadcasts when you say `--live`. Retries are safe: an idempotency key
(automatic, or set your own with `--idempotency-key`) means a retried run
replays the stored result instead of trading twice.

**In this release (0.1.x), `--live` ships disabled** while the signing lane
is hardened. Everything else — `check`, simulated `run`, the price feed, and
deposit-address bots below — is fully available.

## The signer

Live bot trades on EVM chains sign with a key you configure explicitly:

| Environment variable | Meaning |
| --- | --- |
| `OPENSWAP_EVM_PRIVATE_KEY` | A hot key (you'll be warned on `--live`) |
| `OPENSWAP_EVM_KEYSTORE` + `OPENSWAP_EVM_KEYSTORE_PASSWORD` | An encrypted keystore — the right choice for real funds |
| `OPENSWAP_EVM_RPC_URL` | Your own RPC endpoint (serious bots should set this) |

Before anything signs, guards check the target address, the chain id, and
that the amount being moved never exceeds what was approved.

## Bots without a signer

If your automation pays from external wallet infrastructure instead, use the
normal swap flow with a policy attached:

```bash
openswap swap --policy p.json --json --yes …
```

Same policy protection, but you get a deposit address to pay rather than an
on-chain signature — this works for every chain, not just EVM.

---

---
title: For AI agents
description: The complete machine contract: JSON envelope, exit codes, financial rules, and recipes — identical to `openswap agent docs`.
order: 5
version: 0.1.0
---

# For AI agents

OpenSwap treats agents as first-class users. The fastest bootstrap from
inside any agent:

```
npx openswap@latest agent docs
```

That prints the complete machine contract below — this page and that command
are kept identical, so you can rely on either. Claude Code users can install
the packaged skill with `openswap agent setup`.

Before moving real funds, rehearse in [test mode](https://leokit.dev/cli/docs/test-mode):
`openswap test on` gives you a full simulated exchange through the unchanged
production code paths.

---

# OpenSwap CLI — contributor & coding-agent guide

Terminal-first crosschain swaps (npm: `openswap`). TypeScript, Node ≥ 20,
self-contained: it talks HTTP to the public LeoKit API — no SDK dependency,
no wallet custody, no signing in the default flow.

> **Driving the CLI as an agent rather than developing it?** This file is not
> for you. [AGENT-CONTRACT.md](AGENT-CONTRACT.md) is the machine contract —
> JSON envelopes, frozen exit codes, financial rules. Run `openswap agent docs`
> to print it; you never need to read this repository.

## Read before changing anything

- [docs/README.md](docs/README.md) — public doc index
- [docs/architecture.md](docs/architecture.md) — layers and file map
- [AGENT-CONTRACT.md](AGENT-CONTRACT.md) — the machine/agent output contract
  (frozen exit codes)
- [brand/BRAND.md](brand/BRAND.md) — brand kit. Assets are GENERATED: edit
  `brand/otto.pixels.json`, run `npm run brand`, commit outputs (tests enforce
  freshness). Otto appears only on the bare `openswap` menu — never add the
  mascot to subcommands or machine output.

## Commands

```bash
bun install          # or npm install
bun run typecheck    # tsc --noEmit — must stay clean
bun run test         # vitest unit suite — must stay green
bun run build        # tsup → dist/index.js
node dist/index.js   # run the built CLI (targets Node)
```

## Non-negotiable rules

- **Money math**: decimal strings + BigInt only — never float arithmetic on
  amounts. Quote responses go through `parseJsonPreservingBigInts` (base-unit
  amounts exceed 2^53 in production, and arrive in exponent form above 1e21).
- **Never fabricate financial data**: no invented minimums, no totals from
  partially priced fees, no guessed statuses. `null` renders as "not provided",
  and a `usd: 0` fee against a non-zero amount means *unpriced*, never free.
- **Secrets**: never in argv, URLs, config files, receipts, logs, or errors.
  Credentials resolve only in `src/core/credentials.ts` (env → OS keychain →
  the intentionally public community key).
- **State-changing calls** (`/deposit-address`, `/deposit`, broadcast) are
  never auto-retried and never happen under `--dry-run`; receipts are written
  BEFORE payment instructions render.
- **Payment URIs are built locally** from a validated address — never rendered
  from a server-supplied string.
- Renderers contain no business logic; upstream strings are untrusted —
  `sanitize()` everything user-visible.
- Machine contract is frozen: envelope shape and exit codes only change with
  a documented deprecation (see [AGENT-CONTRACT.md](AGENT-CONTRACT.md)).
- Copy rules: "crosschain" (one word); "Expected receive" (never "You will
  receive" for an estimate); never "best" without naming the criterion.

## API behavior worth knowing

Quotes expire in ~30 seconds. Deposit-bound quotes need `origin` +
`destination` at quote time, and `/deposit-address` needs both `to_address`
and `from_address` (the payer/refund wallet). `/deposit` returns
`unsigned_transactions`. `/status` has two response shapes — always go through
`normalizeStatus`. Route discovery uses the SSE stream so every provider gets
its window; don't replace it with one-shot quote calls.

## Verifying a change

Test mode runs the whole CLI against a simulated backend through the unchanged
production code paths, so a full swap can be verified without funds:

```bash
OPENSWAP_TEST_MODE=1 OPENSWAP_TEST_TIMESCALE=100 node dist/index.js swap \
  -a 25 -f eth:usdc -t base:usdc \
  --to-address 0x1111111111111111111111111111111111111111 \
  --refund-address 0x2222222222222222222222222222222222222222 --yes --json
```

`node scripts/e2e-sim.mjs` runs the same lanes non-interactively and is what CI
gates on. See [docs/test-mode.md](docs/test-mode.md).

## Security

Report vulnerabilities privately — see [SECURITY.md](SECURITY.md). Never open a
public issue for an exploitable finding, and never route one through
`openswap feedback`.

---

---
title: Security & custody
description: Is OpenSwap safe? The CLI never holds funds or keys — you pay a deposit address from your own wallet. Here is the full security model.
order: 6
version: 0.1.0
---

# Security & custody

The short version: **OpenSwap never holds your money and never sees your
keys.** It finds you a route and gives you a deposit address; your own
wallet does the paying. There's no seed phrase to enter, no browser
extension, and no account — which means there's nothing here to steal.

## How a swap actually works

When you confirm a swap, the route provider creates a **deposit address** —
a normal blockchain address that belongs to the swap. You pay it from any
wallet you already trust, the provider does the crosschain exchange, and
funds arrive at your destination address. The CLI's job is to compare
routes, validate everything, and keep the receipt. It's a guide, not a
custodian.

The one exception is explicitly opt-in: the [bot signer](https://leokit.dev/cli/docs/bots)
for automated trading, which is never part of the human flow.

## What protects you during a swap

- Destination and refund addresses are validated for the right chain, and
  known placeholder addresses are rejected outright.
- The final quote is re-created bound to *your* destination before you
  review it, and confirming means typing `SWAP` — not just hitting Enter.
- Amounts are recomputed with exact integer math, and the QR code is only
  shown if it agrees perfectly with the validated address and amount.
- Routes that need extra metadata a plain address can't carry are refused on
  the QR path rather than risking a mis-send.
- Your receipt is saved *before* payment instructions appear, so a crash or
  closed laptop can't lose a swap.
- If an outcome is ever unknown, the error says `funds_may_have_moved`
  honestly and nothing is blindly retried.

## How API keys are handled

Your key is looked up in this order: the `OPENSWAP_API_KEY` environment
variable → the operating system's keychain (via `openswap auth login`) → the
built-in community key. Keys are typed in privately, never accepted as
command-line flags, never written to files or receipts, and never sent
anywhere except the official API.

The community key being public is intentional: it can fetch quotes and
prepare swaps, and that's all — it cannot move funds and cannot read
anything private.

## The optional signing wallet

If you set one up, `openswap wallet setup` recommends **creating a fresh
dedicated wallet** rather than importing your main one. It's generated
locally, encrypted on disk, and asks for its passphrase at every signing.
Keep only active trading balances on it.

## Privacy

There is **no telemetry**. Receipts and logs stay on your machine with
restrictive permissions and contain no credentials. The one thing that ever
leaves your machine voluntarily is `openswap feedback` — and it shows you the
exact, redacted diagnostics and asks for consent before sending.

## Found a security problem?

Please report it privately — see the
[security policy](https://github.com/steemleo/OpenSwap/blob/main/SECURITY.md)
for the disclosure process. Don't open a public issue for an exploitable
finding, and don't send it through `openswap feedback` (that posts to a team
chat channel, which isn't confidential).

---

---
title: Keys, fees & founding keys
description: What OpenSwap costs (0.10% standard, 0.01% on stables), how to earn affiliate fees with your own free key, and the 100 founding keys.
order: 7
version: 0.1.0
---

# Keys, fees & founding keys

## What does OpenSwap cost?

The tool itself is free and open source. When a swap actually executes, two
kinds of cost apply:

- **Route fees** — network and protocol fees set by whoever executes the
  swap (Chainflip, THORChain, Maya, NEAR, Relay, and the rest). Every quote
  shows these before you commit, and if a provider doesn't price one, the
  CLI says *not priced* rather than pretending it's zero.
- **The platform fee** — 0.10% of the swap on the built-in community key.
  Stablecoin-to-stablecoin swaps are cheaper for everyone: 0.01%.

There are no subscriptions, no gas markups, and nothing hidden. Every route
shows its full cost up front.

## The built-in community key

`npx openswap@latest` works out of the box because a shared, intentionally public
community key ships inside the tool. It can fetch quotes and prepare swaps —
and nothing else. It can't move funds and can't see anything private.
Affiliate fees on community-key volume go to LeoDex, which is what pays for
the free tier.

## Get your own key (and keep the affiliate fees)

Here's the honest economics: every swap routes an affiliate fee to whoever's
API key was used. On the community key, that's LeoDex. **With your own key,
it's you.** If you're building a bot, an app, or just routing your own
serious volume, that fee belongs in your pocket.

Keys are free at [dash.leokit.dev](https://dash.leokit.dev) — sign in with
Google or GitHub, no sales call. Then store it securely:

```bash
openswap auth login
```

The key goes into your operating system's keychain, not a file. For CI and
bots, use the `OPENSWAP_API_KEY` environment variable instead.

## Founding keys: 0.01% for life

The first 100 people to claim a founding key swap at a **0.01% platform fee
forever** — one tenth of the standard rate, on everything, permanently.

Claim yours at [leokit.dev/cli](https://leokit.dev/cli#founding). It takes
an email address; the key appears on screen immediately. One key per email —
and if you ever lose it, submit the same email again and your key is shown
again. When the hundred are gone, they're gone.

## Fork it — seriously

OpenSwap is MIT licensed, and forks are welcomed on purpose: put your own
API key in a fork and **the affiliate fees on all its volume are yours.**
That's the deal — the platform fee funds the rails either way, and the
affiliate layer rewards whoever brings the users. The repo includes a brand
pipeline (one JSON file regenerates every logo and banner), so a rebranded
fork is an afternoon's work, not a design project. Two asks: keep the MIT
notice, and never commit a raw webhook or key to your fork.

---

---
title: Receipts & data on disk
description: Where OpenSwap stores swap receipts and settings on your machine, every receipt field explained, and how to remove all of it.
order: 8
version: 0.1.0
---

# Receipts & data on disk

Everything OpenSwap knows lives on **your** machine. Nothing is uploaded and
there is no telemetry. This page explains exactly what's written, where, and
how to read or delete it.

## Where things live

| Path | What's in it |
| --- | --- |
| `~/.local/share/openswap/receipts/` | One JSON file per swap |
| `~/.config/openswap/` | Settings; the optional encrypted signer wallet |
| `~/.cache/openswap/` | The asset list cache (refreshed daily) |
| Your OS keychain, entry `openswap-cli` | Your API key, if you ran `auth login` |
| `~/.local/share/openswap/test-mode/` | The practice sandbox, fully separate |

Files are written atomically (a crash can't corrupt them) with permissions
only you can read. Receipts never contain secrets — no keys, no passphrases.

## What's in a receipt

A receipt is the durable record of one swap, written **before** the payment
screen appears — so nothing is lost if your laptop dies mid-swap. Print any
receipt as JSON with `openswap receipts export <id>`.

| Field | Plain-English meaning |
| --- | --- |
| `receipt_id` | The swap's id: `os_…` for real swaps, `ost_…` for practice ones |
| `environment` | `mainnet` (real) or `simulated` (test mode) |
| `quote_id`, `protocol` | Which quote you locked, and which provider ran it |
| `from_asset`, `to_asset` | What you swapped, precisely identified |
| `amount_display`, `amount_base_units` | The amount, both human-readable and exact |
| `expected_out_display`, `expected_out_usd` | What the route promised you'd receive |
| `destination_address` | Where the swapped funds go |
| `refund_address` | Where funds return if the swap fails |
| `deposit.deposit_address` | The address you paid |
| `deposit.expires_at` | The payment deadline (always at least 20 minutes) |
| `deposit.payment_uri`, `deposit.memo`, `deposit.network` | Helpers your wallet used |
| `tx_hashes.source` / `.destination` / `.refund` | On-chain transactions, filled in as tracking sees them |
| `last_state`, `last_checked_at`, `last_error` | The latest tracking snapshot |
| `schema_version` | The receipt format version — fields are only ever added |

To check on any receipt later:

```bash
openswap status <receipt_id>          # one look
openswap status <receipt_id> --watch  # follow it until it finishes
```

A swap always ends in one of four states: `success`, `failed`, `refunded`,
or `deposit_expired` (you never paid the deposit — nothing moved).

## Removing everything

```bash
npm uninstall -g openswap
rm -rf ~/.local/share/openswap ~/.config/openswap ~/.cache/openswap
```

Then delete the `openswap-cli` entry from your keychain if you stored a key.
That's the entire footprint — gone.

---

---
title: Changelog
description: OpenSwap CLI release notes.
order: 99
version: 0.1.0
---

# Changelog

All notable changes to this project are documented here.
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this
project adheres to [Semantic Versioning](https://semver.org/). While on 0.x,
minor versions may include breaking changes.

## [Unreleased]

## [0.1.0] - 2026-07-21

### Added
- Initial public release: crosschain quote/swap/status/receipts with
  streaming route discovery (SSE), deposit-address funnel with local QR +
  clipboard handoff, durable resumable receipts.
- `openswap tour` — 2-minute guided walkthrough (real prices, simulated
  payment, nothing real moves).
- Policy-gated bot mode (`bot init/check/run`) with allowlists, USD ceilings,
  fee caps, cooldowns, and a kill-switch file; simulate-first execution.
- Optional EVM signer (encrypted V3 keystore or env key) unlocking
  wallet-signed routes.
- Agent surface: `--json` envelopes with frozen exit codes, AGENT-CONTRACT.md
  contract, installable Claude Code skill (`openswap agent setup`).
- Otto the Otter brand system with a fork-friendly asset pipeline
  (`npm run brand`).
