Skip to content

Environment variables and secrets

Mend stores project environment input in two lanes. Both become environment variables in future workspace processes, but they have different storage and read behavior.

Lane Storage Read behavior Use for
Configuration Plaintext Names and values can be read back Ports, modes, feature switches, public URLs
Secrets Encrypted with a machine-local key Names are visible; values are write-only Passwords, tokens, private keys, credential-bearing URLs

On a Kubernetes install a third source exists, cluster bindings: names of cluster Secrets and ConfigMaps whose contents Mend never stores at all.

Changes apply from the next workspace launch. Running agents, shells, and Services keep the values their workspace started with.

Anyone who can see the project can read its names. Only the people who manage it, its creator and the organization’s owners, can add, change, or remove entries, from the web app or the CLI. Organization defaults do not include environment variables; each project holds its own.

From an adopted project:

Terminal window
mend env load

The default file is .env. Pass another path when needed:

Terminal window
mend env load .env.development

Use --project when the current directory does not identify the target project:

Terminal window
mend env load .env.development --project api

Mend parses the file, upserts accepted names, and reports malformed or rejected lines. Existing entries with the same name are replaced.

During import, names containing common secret markers such as TOKEN, SECRET, PASSWORD, PASSWD, CREDENTIAL, or APIKEY go to Secrets. Names ending in _KEY, and the exact name KEY, also go to Secrets.

Send the whole file to Secrets:

Terminal window
mend env load .env --secret

Send named values to Secrets while leaving the rest to automatic routing:

Terminal window
mend env load .env --secret DATABASE_URL,SENTRY_DSN

This is useful for URLs that embed a password but do not look secret from their name.

Terminal window
mend env show

The command prints configuration names, secret names, and any cluster bindings, with a revision per lane. It labels configuration as plaintext and never prints secret values. Cluster bindings show as secret/<name> or configmap/<name> because the object names are all Mend knows.

Open the project’s Setup page. The Configuration and Secrets sections support create, rename, replace, and remove operations. Secret rows only show whether a value is set. Members who do not manage the project see a note in place of these sections.

Renaming a secret without entering another value preserves the stored value. Replacing it writes a new encrypted value.

On a Kubernetes install a project can bind cluster objects: each binding names a Kubernetes Secret or ConfigMap in the platform’s workspaces namespace whose keys become workspace environment. Mend stores the binding itself, a kind plus an object name, and never the keys or values inside the object. The Sealant worker resolves the object at each fresh workspace launch, so rotating a Secret with kubectl applies from the next launch without touching Mend, and no value ever crosses Mend’s database.

The boundaries:

  • Only objects the operator labeled for workspace environment resolve.
  • Object names follow Kubernetes DNS-1123 subdomain grammar, and a project holds at most 16 bindings.
  • A project can also name a workspace service account, the Pod identity its workspaces run as. The operator allowlists which accounts may be requested.
  • On a local-runner install, bindings do not resolve. A declared binding blocks launches there rather than shipping an incomplete environment; remove the bindings to launch on that install.

mend env show lists bindings and the service account alongside configuration and secret names. Add and remove bindings and set the service account on the Setup page’s Cluster bindings panel, or from the terminal:

Terminal window
mend env cluster add secret app-env
mend env cluster add configmap app-config
mend env cluster remove secret/app-env
mend env cluster sa workspace-runner
mend env cluster sa --clear

Each command takes --project like mend env load. At each fresh workspace launch Mend forwards the declared bindings to the platform verbatim; the worker resolves the objects server-side and their keys become workspace environment. An install that cannot resolve them refuses the launch with a failure naming every binding; remove the bindings in project setup to launch there.

Every workspace also starts with a few variables of Mend’s own, for every process in it, each person’s processes in a per-person workspace included:

Variable Why
PAGER=cat The workspace images carry no less, so git log in a terminal would fail with unable to execute pager 'less'
DISABLE_AUTOUPDATER=1, OPENCODE_DISABLE_AUTOUPDATE=1, PI_SKIP_VERSION_CHECK=1 The image owns each harness; an update inside a running workspace can break it for every later launch

A project variable of the same name wins over Mend’s, and so does what a shell profile exports. The one exception is Claude Code’s updater, which Mend turns off again when it starts claude. GIT_PAGER is left unset on purpose: git reads it before core.pager, so it would override the pager you name in your own git config.

Mend rejects names that belong to the platform or can change process startup. Examples include:

  • PATH, shell startup variables, and runtime injection variables such as NODE_OPTIONS;
  • Git and SSH controls such as GIT_SSH_COMMAND, GIT_CONFIG_GLOBAL, and SSH_AUTH_SOCK, which the platform reserves. Mend wires the workspace Git transport through system Git config (core.sshCommand) instead;
  • GITHUB_TOKEN and CLAUDE_CODE_OAUTH_TOKEN, which come from connected accounts;
  • names beginning with MEND_ or SEALANT_.

Use provider accounts for Claude, Codex, and GitHub credentials rather than copying those credentials into project secrets.

Secret values are encrypted at rest with a machine-local key. The API never returns them. At a fresh launch, Mend decrypts the current set once and passes it through Sealant’s transient secret channel.

Losing the machine key makes stored values unrecoverable. Re-enter them rather than expecting Mend to reveal or export them.