Secrets
Store encrypted credentials at the workspace level and hand one to an agent through a Credential ref, without ever putting a plaintext value in a launch config.
A secret is an encrypted value scoped to your workspace — typically an API key, access token, or other credential your agents need at runtime. You create it once with a name and a value; from then on, CodeHerder and everyone in your workspace only ever see the name and a version number, never the value itself.
Two ways to give an agent a credential
A workspace secret, covered on this page, is one of two ways to do this. CodeHerder holds the encrypted value and it’s available to the agent on any device it runs on. The other is a device-side reference — an @secret:<key> value in the launch config that the device itself resolves at spawn time, so the value never reaches CodeHerder at all. Reach for a device-side reference when you don’t want CodeHerder to hold the credential; see Secrets on a device for how it works.
Who can manage secrets
Owners and admins create, rotate, and delete secrets — from the web app, under Settings → Secrets, or from the CLI with ch secrets. Other workspace members don’t have access to either surface, and agents can never view or manage secrets: every ch secrets command requires a human token, so an agent’s own credentials can’t be used to create, read, or change a secret. The entire point of a secret is that an agent can use a credential without ever holding or seeing it.
(You can wire an existing secret into an agent’s launch config from the CLI regardless of who created it — see “Giving a secret to an agent” below.)
Creating a secret
From the web app: open Settings → Secrets, click + New secret, name it, paste the value, and save.
From the CLI: ch secrets create --name <name> --value <value>. Name it with lowercase letters, digits, hyphens, and underscores, up to 64 characters (for example, github-pat or slack_webhook) — names must be unique within the workspace.
--value takes the actual credential, and reads it three ways. Prefer the file or stdin forms — an inline value lands in your shell history:
ch secrets create --name github-pat --value --from-file token.txt # from a file
printf %s "$TOKEN" | ch secrets create --name github-pat --value - # stdin
ch secrets create --name github-pat --value "the-value-itself" # inline (avoid — shell history)
Either way, the value is write-only: once saved, CodeHerder never displays it again, in the web app, through the CLI, or through the API. Keep a copy wherever you originally generated it if you might need to check it later.
Listing and inspecting secrets
ch secrets list shows every secret in the workspace — name, version, and when it was last updated. ch secrets show <name|id> shows the same metadata for one secret. Neither ever prints the value; there’s no way to read a secret back once it’s saved.
Both commands, and every other ch secrets command, resolve <name|id> by the secret’s name or its full ID — see Referring to things on the command line for how name matching works — and need CH_WORKSPACE_ID set so CodeHerder knows which workspace to look in (see Agents and the CLI for setting up the CLI).
Rotating a secret
From the web app: click Rotate on the secret’s row and paste the new value.
From the CLI: ch secrets rotate <name|id> --value <newValue>, with the same three --value forms as creating one. Either way, CodeHerder bumps the secret’s version number every time you rotate it, so its row always shows how many times it’s changed.
Every agent config that references the secret picks up the new value automatically the next time it spawns — there’s nothing else to update.
Deleting a secret
From the web app: click Delete on the secret’s row. From the CLI: ch secrets delete <name|id> (alias ch secrets rm <name|id>).
Either way this is irreversible, and any agent config that still references the deleted secret fails to spawn. Before you delete a secret, update or remove the Credential ref on every agent that uses it — otherwise a task that reaches that stage errors out instead of starting.
Giving a secret to an agent
A secret does nothing by itself — you connect one to an agent through a Credential ref on the agent’s launch config (see Agents and the CLI for launch configs in general). Open the config’s editor and use the Credential refs field:
- Enter the environment variable name the agent’s process should see, for example
GITHUB_TOKEN. It must be uppercase letters, digits, and underscores, starting with a letter or underscore — and it can’t start withCH_, which CodeHerder reserves for its own variables. - Select the workspace secret to bind to that name.
- Save.
You can do the same from the CLI with ch agent config set <agentId> --credential-ref <ENV_VAR>=<secretId> (repeat the flag for more than one).
Either way, CodeHerder resolves the reference and injects the value into the process environment only at the moment a session spawns — the value is never stored in plaintext in the launch config, and it never appears in logs, task text, or session output. The agent’s process just sees a normal environment variable.
Credential refs don’t add an extra approval step of their own: once you’ve assigned and approved the agent to run on a device (see Agents and the CLI), every Credential ref on its launch config resolves automatically each time that stage spawns.
Availability
Secrets depend on encryption support being configured on your deployment. If Settings → Secrets isn’t there, it isn’t enabled on your deployment — ask your workspace admin.
Related guides
- Secrets on a device — the device-side alternative: reference a credential that lives only on a device, with no round trip through CodeHerder.
- Agents and the CLI — configure a launch config, including where Credential refs live, and assign/approve an agent on a device.
- Managing your devices — device state and troubleshooting for wherever an agent runs.
- Integrations — a different, workspace-level way to store a credential: connecting the workspace itself to an external service like GitHub or PagerDuty, rather than handing a secret to an agent.
