> For the complete documentation index, see [llms.txt](https://docs.drizz.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.drizz.dev/twins/reference/keys-and-limits.md).

# Keys and limits

How you sign in, where your key is kept, keys for CI, what each role may mint, and how many worlds you can hold and for how long.

How you sign in, where your key is kept, what each role may mint, and how many worlds you can hold.

## Sign in

```bash
twin login
```

Your browser opens with a short code. Sign in with your work email and approve the code. That's all: no file to fill in, no token to paste.

`twin login` mints an **API key** for this machine and keeps it. Every `twin` command then uses it.

{% hint style="info" %}
Your organization's access comes from Drizz. If the sign-in says your email has no access yet, ask your Drizz contact.
{% endhint %}

| Option            | What it does                                                    |
| ----------------- | --------------------------------------------------------------- |
| `--name NAME`     | what to call the key (default: `twin-harness <this machine>`)   |
| `--no-browser`    | print the sign-in link only, for a machine with no browser      |
| `--server SERVER` | sign in to another twins server, such as one your company hosts |

## Where your key is kept

`twin login` keeps the key in your operating system's credential store:

| System        | Where                                                    |
| ------------- | -------------------------------------------------------- |
| macOS         | the Keychain                                             |
| Linux         | the Secret Service                                       |
| Anywhere else | `~/.config/twin/credentials.json`, readable by you alone |

To choose yourself, set `TWIN_CREDENTIAL_STORE` to `keychain`, `secret-service`, `file` or `auto` (the default: the OS store when there is one, else the file). `TWIN_CREDENTIALS=<path>` keeps it in a file of your choice instead (and means the file, not the OS store).

## See who you are

```bash
twin whoami
```

`twin whoami` shows the key kept here, who it belongs to, where it is kept, and whether the twin takes it.

| Exit status | Meaning                              |
| ----------- | ------------------------------------ |
| `0`         | the twin takes the key               |
| `4`         | not signed in, or the key is refused |
| `69`        | the twin did not answer              |

## Sign out

```bash
twin logout                # revoke this machine's key on the server, and forget it
twin logout --everywhere   # ...and end every sign-in session you hold
twin logout --local        # forget it here only; it stays valid until revoked
```

If you have no live sign-in session, `twin logout` opens your browser to sign in first, so it can revoke the key. A key the server did not revoke stays kept. Keys you forgot earlier with `--local` are revoked too, the next time you run `twin logout`.

## Keys in CI

A CI job has no browser. Give it a key minted elsewhere, in one of two ways:

{% tabs %}
{% tab title="Environment variable" %}
Set `TWINS_API_KEY` from your CI system's secret store. Every `twin` command uses it instead of a kept key:

```bash
export TWINS_API_KEY=<key>
twin world create seed.md --folder world
```

{% endtab %}

{% tab title="twin login --with-key" %}
Keep the key for the job's later steps. `--with-key -` reads it from stdin, so it never appears on a command line:

```bash
echo "$KEY" | twin login --with-key -
twin login --with-key - < key.txt
```

{% endtab %}
{% endtabs %}

Mint a key for CI in the [web console](/twins/using-twins/web-console.md#settings), under **Settings → API keys**.

{% hint style="warning" %}
Store keys in your CI system's secret store. Never commit a key, and never pass one as a command-line argument.
{% endhint %}

## API keys and world tokens

Two credentials do two different jobs. They are not interchangeable.

|                      | API key                              | World token                                                      |
| -------------------- | ------------------------------------ | ---------------------------------------------------------------- |
| Who holds it         | you, your scripts, CI                | your agent                                                       |
| What it does         | makes, reads and deletes worlds      | acts as one person inside one world                              |
| Where it comes from  | `twin login`, or Settings → API keys | `twin start`, `twin world create`, or the console's Connect page |
| Given to your agent? | never                                | yes                                                              |

When you run your agent with `twin world run`, it gets the world token (`TWIN_TOKEN`), never your API key.

## Roles

Each person in your organization has a role: **owner**, **admin** or **member**. A role bounds the keys a person may mint.

* An API key carries a fixed set of **scopes**, frozen when it is minted. The minter's role at that moment bounds them.
* An owner or an admin may mint a key with any of the six scopes.
* A member may mint a key with five of them. Only `WORLDS_ADMIN` is withheld.
* A key never widens. A later role change does not give an existing key more.

In the web console, winding a twin's clock, arming a fault and loading a kept scenario need an owner or an admin.

## Limits

| Limit                                     | Default      | Notes                                                              |
| ----------------------------------------- | ------------ | ------------------------------------------------------------------ |
| Worlds your organization holds at once    | 25           | an admin can raise it. `twin world list` shows how many are in use |
| World lease (`twin world create`)         | 6 hours      | `--lease <seconds>` sets another                                   |
| World lease (`twin start`, signed in)     | 1 hour       | `--lease <seconds>` sets another                                   |
| Trial world (`twin start`, not signed in) | the server's | it deletes itself when its time is up                              |

A world deletes itself when its lease ends, unless you delete it first. To free room sooner, delete worlds you are done with:

```bash
twin world list
twin world cleanup --label demo --yes
```

## Private and shared worlds

Worlds are private by default. Set `TWIN_WORLD_SHARED=1` to make worlds your organization shares instead. A teammate's key can read a shared world; only an admin's can delete it.

## Your own twins server

If your company hosts its own twins server, sign in to it instead:

```bash
twin login --server https://twins.acme.internal
```

Or set `TWIN_SERVER=https://twins.acme.internal`. On a server with sign-in turned off, keep a key its administrator made for you:

```bash
echo "$KEY" | twin login --server https://twins.acme.internal --with-key -
twin whoami
```

See [Self-hosting](/twins/self-hosting.md) and [Your own sign-in](/twins/self-hosting/your-own-sign-in.md).

## Next

* [CLI reference](/twins/reference/cli.md): every `twin login`, `whoami` and `logout` option.
* [Troubleshooting](/twins/reference/troubleshooting.md): "not signed in", and the world limit.
* [Web console](/twins/using-twins/web-console.md): mint a key under **Settings → API keys**.

***

*Last updated: 27 October 2026*
