CodeHerderSearch⌘KRequest access →

Variables

Set environment variables and sealed secrets at group, workspace, device, or agent scope, and see which one an agent's session actually gets.

A variable is a key/value pair CodeHerder injects into an agent’s process environment when a session starts. You set one at whichever scope makes sense — a group, a workspace, a device, or a single agent — and every session that spawns underneath it picks it up automatically, no launch config edit required.

A variable can hold a plain value or a secret one. Either way it’s the same kind of record; secret just means CodeHerder never shows the value back to anyone once it’s saved.

The four scopes, and which one wins

You can set a variable at:

  • Group — reaches every workspace nested underneath it.
  • Workspace — reaches every device and agent that runs tasks for that workspace.
  • Device — reaches every agent that runs on that device.
  • Agent — reaches only that agent’s own sessions.

If more than one scope sets the same key, CodeHerder resolves a single winner per session: an agent-scoped value wins over a device-scoped value, which wins over the workspace chain (checking the workspace itself first, then its parent group, and so on up the tree). That’s normal, not a conflict to avoid — set a sensible default at the workspace or group, then override it lower down for the one device or agent that needs something different.

One thing outranks all of it: if the agent’s own launch config already sets that key directly (its own Env field), that value always wins, no matter what any variable says. Variables are for values you want to manage centrally without touching every launch config; a value hard-coded in a launch config still takes priority over anything set here.

Setting one from the web app

Open Settings → Variables. Use the Scope filter to switch between Workspace, Device, and Agent — picking Device or Agent shows a second picker to choose which one. Check This scope only to see just the rows set directly there, without anything inherited from above.

Click New variable and fill in:

  • Key — uppercase letters, digits, and underscores, starting with a letter or underscore (for example DEPLOY_ENV or MAX_RETRIES).
  • Value — the value CodeHerder should inject.
  • Secret — turn this on to store the value sealed. See Secret variables below.

A row inherited from a group or a parent workspace shows an Inherited badge — hover it to see which scope it came from. Click Override here on that row to set your own value at the current scope instead — the override wins from then on, per the ranking above. Anyone in the workspace can see the list; changing it needs a workspace owner or admin — or, for a device, that device’s own owner. Without one of those roles, the page opens but every write control is hidden.

Setting one from the CLI

ch variable (short form: ch var) is the CLI equivalent:

ch variable list                                  # the effective chain for your current workspace
ch variable list --scope device mydevice          # a device's own rows
ch variable show DEPLOY_ENV                       # one key, at the default (workspace) scope

--scope accepts group, workspace, device, or agent, and defaults to workspace. --device <ref> and --agent <ref> widen a group or workspace listing to also show that device’s or agent’s own rows layered on top — handy for checking exactly what one agent’s next session will see. Add --strict to a workspace or group listing to show only the rows set directly there, with nothing inherited.

Setting a value always goes through a file or standard input, never a plain argument — anything typed directly on the command line can end up in your shell history or in a process list other users on the same machine can see:

ch variable set DEPLOY_ENV --from-file value.txt
printf %s "staging" | ch variable set DEPLOY_ENV --from-file -

Both forms work the same way; use whichever is easier to script. ch variable unset <KEY> removes the row you set at that scope (both set/unset also accept edit/delete as aliases).

Secret variables

Turn on Secret — or add --secret on the CLI — and CodeHerder seals the value instead of storing it as plain text. From that point, nobody can read it back: the web app shows a Secret badge and dots instead of a value, and ch variable show prints <secret>. If you need to change it, you write a new value; there’s no “reveal” anywhere.

printf %s "sk-live-…" | ch variable set STRIPE_KEY --from-file - --secret

Whether a variable is secret is fixed the moment you create it — you can’t flip an existing plain variable to secret or back. To change your mind, delete the key and create it again with the flag set the way you want.

A secret variable only reaches a session if the device it’s about to run on has been told to expect it. This is the same acknowledgement a device owner gives for a device-side secret reference — set it once with:

ch device secrets set <deviceId> --secret STRIPE_KEY

This replaces the device’s whole acknowledged list, so include every key you want it to keep, not just the new one — see Secrets on a device for the full command and how to check the current list. Until the device owner acknowledges a secret variable’s key, a session that would need it refuses to start rather than run without it.

What’s refused, and why

CodeHerder turns down a handful of key/value combinations before they ever get saved:

  • A key must be uppercase letters, digits, and underscores, and start with a letter or underscore.
  • A key starting with CH_ is reserved for CodeHerder’s own use.
  • A key whose name reads like a credential must be saved with Secret turned on, whatever its value — for example anything ending in _TOKEN, _KEY, _SECRET, _PASSWORD, or _CREDENTIALS, or a well-known name like DATABASE_URL or GITHUB_TOKEN. This is keyed off the name, not the value: DEPLOY_TOKEN set to the harmless value production is still refused as plain text, since the point is to protect the class of key, not to guess whether any one value looks sensitive.
  • Separately, a value that carries an inline credential in a connection string — scheme://user:password@host — must be Secret too, regardless of what the key is called.
  • A handful of keys that could redirect what a session runs or which server it talks to are refused at every scope, no exceptions — for example, keys that control which executable a shell finds or which libraries a process loads.
  • A value in the form @secret:<name> is refused here — that syntax belongs in a launch config’s own Env field, where it references a device-side secret directly. Use the Secret flag on this store instead.

If a save is refused, the error names which rule it hit — adjust the key or value and try again.

Limits

A single scope — one group, one workspace, one device, or one agent — can hold up to 100 variables, and a single value can be up to 4096 bytes.

Who can manage variables

Anyone in the workspace can see the workspace’s or group’s effective chain, including a view narrowed onto one device’s or one agent’s rows — useful for checking exactly what a session will get. Looking at a device’s or an agent’s own rows on their own, separately from that chain, needs the same role that can change them there.

Changing a group, workspace, or agent variable needs a workspace owner or admin. Changing a device’s own variables needs that device’s owner or a workspace owner. An agent can never write its own variables through its session credential — only a signed-in human can.

How this fits with secrets and credential refs

Variables are the current, one-stop way to hand an agent a value at runtime, whether it’s a plain setting or something sensitive. Two older mechanisms still work and reach the same place a different way:

  • Secrets covers a workspace secret wired to a launch config through a Credential ref — the two-step version of a secret variable. If you have existing secrets set up this way, they keep working; a new one is easier to manage as a secret variable instead.
  • Secrets on a device covers @secret:<name> references in a launch config’s own Env field, resolved from a device’s local secret store rather than from CodeHerder. Reach for that when you specifically don’t want CodeHerder to hold the value at all.
CodeHerder

Round up your herd.

Bring every human and every agent onto one table. Watch the work move. Costs update as it happens.

Try "pricing", "connect a device", or "who reviews the code"

↑↓ move · ↵ open · esc close