# Credential storage

Each linked agent has one signing key, which the CLI uses to sign each request.
The key itself is never sent to Catena, and where it's stored depends on the
host.

## Choose a credential mode

The table below shows where the key lives on each kind of host:

| Host                                                                                            | Where the key lives                                                       | How to set it up                                            |
| ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------- |
| macOS                                                                                           | The macOS Keychain                                                        | `catena link`                                               |
| Linux with a Secret Service keyring                                                             | The keyring                                                               | `catena link`                                               |
| Linux with no keyring, such as a headless VM or a container with a persistent home directory    | A file under `~/.config/catena/credentials/` that only your user can read | `catena link`                                               |
| A container that loses its home directory on restart                                            | A file under `$CATENA_HOME/credentials/` on a mounted volume              | Set `CATENA_HOME`, then `catena link`                       |
| A host with no persistent disk: CI, serverless, a cloud sandbox that starts fresh for each task | An environment variable                                                   | A [secret key](https://docs.catena.com/connect/secret-keys.md) in `CATENA_SECRET_KEY` |

When `catena link` finishes, it prints which store it used. Every other command
reads the key from that store, and `catena unlink` removes it.

> [!NOTE] **Hosts with no keychain**
>
> Do not use `catena link --service` on a host with no keychain. Plain `link`
> works there and falls back to the file store, while `--service` is for a
> person provisioning a deployed service.

## The file store

On a Linux host with no keyring (such as the computer a
[Meta Muse](https://docs.catena.com/integrations/meta-muse.md) agent runs on), the CLI writes the key to a
file under `~/.config/catena/credentials/`
(`$XDG_CONFIG_HOME/catena/credentials/` when that is set, or
`$CATENA_HOME/credentials/`) that only your user can read.

The file permissions keep other users on the machine from reading the key.
However, any program that runs as your user can read it, so we recommend
treating access to the machine as access to the credential. The agent's
[policy](https://docs.catena.com/policies.md) limits what anyone holding the key can do, and you can
revoke the link from the console at any time.

## Docker

A container that loses its home directory on restart will lose the profile and
key along with it. To keep them, you'll need to point `CATENA_HOME` at a volume
before linking and keep it set for every later command:

```sh
export CATENA_HOME=/data/catena
catena link --name "Container agent"
```

The value must be an absolute path. Once it's set, profiles, credential files,
and pending link requests will all move there, readable only by your user.

## Sandboxed agent tools

Some agent tools run commands inside a sandbox that refuses access the CLI
needs. When that happens, the CLI's error will say what was refused. Below are
the refusals you may see, and what to do about each one.

| Refused                         | What to do                                                                                                                                                                                                   |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Network access                  | The error names the host. Allow network access to that host.                                                                                                                                                 |
| Keychain writes                 | Codex's default sandbox refuses them. Run the command again with the sandbox's approval or escalation, and if the sandbox can't allow it, use a secret key. The CLI does not move a refused key into a file. |
| Writes under `~/.config/catena` | Allow that path, or set `CATENA_HOME` to a writable directory that persists between runs. Note that a rule that allows the older `~/.catena` path does not cover the new one.                                |

## Where profiles live

Profiles and their settings live in `~/.config/catena` (or
`$XDG_CONFIG_HOME/catena`), or in `$CATENA_HOME` when it's set. CLI 0.18 and
later move an older `~/.catena` there on first run and leave a link at the old
path.

## Revoke access

To revoke a linked machine, you can run `catena unlink` on it or unlink it from
the agent's page in the console. To revoke a secret key, use the agent's
**Secret keys** tab.

Both take effect immediately. We check each signed request against the link, so
an unlinked or revoked key will fail on its next request.

## Related

- [Link with the CLI](https://docs.catena.com/connect/cli.md): Link a new or existing agent that runs in a terminal, on your own machine or a headless host, with catena link.
- [Link with secret keys](https://docs.catena.com/connect/secret-keys.md): A secret key lets an agent act in Catena from hosts where catena link cannot store a credential, such as CI jobs, cloud sandboxes, and deployed services.
- [Security](https://docs.catena.com/security.md): How Catena handles custody of your funds, agent signing keys, policy enforcement, revocation, and vulnerability reports.
