# div secrets

> Sets the values every run has in its environment, from stdin or this shell, and never shows one back.

```bash
printf %s "$HF_TOKEN" | div secrets set HF_TOKEN
div secrets set WANDB_API_KEY --from-env
div secrets
div secrets rm HF_TOKEN
```

A secret is a named value the org keeps for its runs. Every run the org places has every secret as an environment variable, so `train.py` reads `os.environ["HF_TOKEN"]` and nothing on the command line names it.

## Usage

```text
div secrets
div secrets set <name> [--from-env]
div secrets rm <name>
```

## set

`set` takes the value on stdin:

```bash
printf %s "$HF_TOKEN" | div secrets set HF_TOKEN
div secrets set GCP_KEY < key.json
```

or, with `--from-env`, from this shell's variable of the same name:

```bash
div secrets set WANDB_API_KEY --from-env
```

Never as an argument. An argument stays in shell history, and in `ps` for as long as the command runs, so `div secrets set HF_TOKEN hf_…` is refused. So is a terminal on stdin, because what you typed would be on screen.

One trailing newline is dropped, since that is what `echo` and a file's last line add. Everything else is kept exactly as it arrived.

Setting a name that already exists replaces its value:

```text
created HF_TOKEN. Every run placed from now on has it
replaced HF_TOKEN. Every run placed from now on has it
```

A name is letters, digits and underscores, and cannot start with a digit, because it becomes an environment variable. Names starting with `DIVERGENT_` are ours. A value can be up to 64 KiB.

## Listing

`div secrets` prints each name and the day it was last set. There is no way to read a value back, here or in the dashboard. We keep it sealed, and open it only to hand it to a run.

```text
HF_TOKEN       2026-09-22
WANDB_API_KEY  2026-09-20
```

The name is the first column on its own, so `div secrets | cut -d' ' -f1` is a list of names. `--json` prints the list the API returned.

## rm

`rm` deletes a secret. Runs already placed keep what they were given. Runs placed afterwards do not get it.

## In a run

A run gets the org's secrets when it is placed, and its log says which ones:

```text
placed with 2 secrets: HF_TOKEN, WANDB_API_KEY
```

The run's own [`--env`](https://docs.divergentlabs.xyz/compute/cli/run.md#flags) wins over a secret of the same name. `--env` values are kept with the run and shown back in the dashboard, so a credential belongs here instead.

If a run prints a secret's value, the log shows `••••` in its place. That covers values of six bytes or more. Masking anything shorter would mask every `1` in the output.

## Keys

A key needs the `secrets:write` scope to set or delete a secret, and `secrets:read` to list them. Keys made by [`div login`](https://docs.divergentlabs.xyz/compute/cli/login.md) carry both. A key made before secrets existed does not. `div` says so, and `div login` makes one that does.
