> ## Documentation Index
> Fetch the complete documentation index at: https://docs.run.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Secrets

> Store credentials once, attach them to the sandboxes that need them.

Store a credential once and attach it to the sandboxes that need it, instead of
sending it with every command. Secrets arrive as environment variables in every
`exec`, and as files under the sandbox's home directory.

A sandbox holds **only what it asks for**, and nothing by default. An agent that
just needs to run `npm install` is not also carrying your Stripe key.

## Groups

A secret belongs to a group, and a group is what a sandbox attaches — `aws`,
`database`, `github`. Create one from a `.env` file you already have:

```bash theme={null}
runcloud secret-group create aws --from-dotenv aws.env
runcloud secret-group create gcp --from-json service-account.json
```

Or type the values into a hidden prompt, when they are not already in a file:

```bash theme={null}
runcloud secret-group create stripe --key STRIPE_SECRET_KEY
```

**A value is never accepted as a command argument.** An argument lands in your
shell history, in `ps` output, and in CI logs, so there is no `KEY=value` form —
`--from-dotenv`, `--from-json`, `--stdin`, and the hidden prompt cover every case
without that.

```bash theme={null}
runcloud secret-group list
runcloud secret-group show aws     # names and kinds; never values
runcloud secrets set AWS_SESSION_TOKEN --group aws --stdin < token.txt
runcloud secrets rm AWS_SESSION_TOKEN --group aws
```

You can also manage groups on the [dashboard](https://run.cloud/dashboard/secrets),
which is usually easier for a `.env` file: paste it, and it confirms the names it
is about to store.

## Attaching them

`--secret-group` and `--secret` are repeatable, and **the order matters**: on a
name collision, the later one wins. `--env` is applied last of all.

```bash theme={null}
# Two groups; if both define DATABASE_URL, prod wins.
runcloud sandbox create --secret-group defaults --secret-group prod

# A whole group plus one secret out of another.
runcloud sandbox create --secret-group aws --secret github/GITHUB_TOKEN

# A literal for this sandbox only.
runcloud sandbox create --secret-group aws --env CI=true

# Explicitly nothing (the default, stated).
runcloud sandbox create --no-secrets
```

In the guest, they are plain environment variables:

```bash theme={null}
runcloud sandbox exec sbx_abc123 'aws s3 ls'
```

An `--env` passed to a single `exec` still wins over the sandbox's standing
secrets, so a one-off override behaves the way you would expect.

## File secrets

Some credentials are files — a service-account JSON, a PEM key, a `.netrc`:

```bash theme={null}
runcloud secrets set-file sa.json \
  --group gcp \
  --path .config/gcloud/sa.json \
  --from-file ./service-account.json
```

The path is relative to the sandbox's home directory, and the file is readable
only by your sandbox's user. Attach the group and it is there before your first
command runs.

Like environment variables, file secrets are held in memory rather than on the
sandbox's disk — so a snapshot does not contain them and a fork inherits none.

## Changing what a running sandbox holds

```bash theme={null}
runcloud sandbox secrets sbx_abc123 --secret-group aws --env CI=true
```

This is a **full replacement, not a merge**: whatever is not in the call is gone
from the sandbox. That is how you revoke — `runcloud sandbox secrets sbx_abc123`
with no flags takes everything back. Restate any `--env` values you still need;
the platform never stored them, so it cannot put them back.

## What you should know

**A value cannot be read back.** Not through the CLI, the API, the SDKs, or the
dashboard. You can list names, kinds, and paths; you can replace a value; you
cannot retrieve one. If you have lost a credential, get a new one from wherever it
came from.

**A fork inherits no secrets.** Secrets live in memory inside the sandbox, so a
snapshot of its disk cannot contain them. Give a fork what it needs:

```bash theme={null}
runcloud sandbox restore snap_abc123 --secret-group aws
```

**A paused or archived sandbox's memory contains its secrets.** Pausing writes the
sandbox's RAM to disk, and archiving uploads it — so both hold whatever the
sandbox held. Destroy a sandbox you no longer need rather than leaving it paused
with live credentials.

**Anything running in the sandbox can read the sandbox's secrets.** That is what
makes them useful, and it is worth being deliberate about: attach the groups a
workload needs, not every group you have.

## Limits

|                                   |                                                               |
| --------------------------------- | ------------------------------------------------------------- |
| Environment variables per sandbox | 100                                                           |
| Total size per sandbox            | 64 KiB                                                        |
| Variable name                     | letters, digits, and underscores; must not start with a digit |
| Reserved prefix                   | `SBX_` is reserved for the platform                           |
| File paths                        | relative to the home directory; no `..`                       |

## From the SDKs

The SDKs talk to a control plane directly and pass literal values, which is the
common case for programmatic use:

```ts theme={null}
const box = await client.create({
  env: { DATABASE_URL: process.env.DATABASE_URL },
  secretFiles: [{ path: ".config/gcp.json", contents: saJson }],
});

await box.setSecrets({ env: { DATABASE_URL: rotated } });  // replaces
```

Organization-wide groups are resolved by the run.cloud API, so use the CLI or the
dashboard for those.
