tofupilot env

Last updated on October 21, 2026

The env command manages environment variables: the values a procedure reads through its config: and secrets: keys. An environment variable has one of two types:

TypeFeedsAfter saving
Secret (default)A secrets: key, read as {secrets.KEY}Never shown again: list and resolve show a digest. Use for passwords, API keys and tokens
ConfigA config: key, read as {config.KEY}Readable by members with access. Use for non-sensitive values

It needs a user login (tofupilot login). A station's login is refused. Every subcommand accepts --json, whose entries carry kind: "config" or "secret" and note.

Levels

Every subcommand works on one level, chosen with flags:

FlagsLevel
noneThe procedure the current directory is linked to
--procedure <ID_OR_NAME>That procedure
--station <ID_OR_NAME>That station: every procedure it runs
--sharedShared: every procedure of the organization

--station and --shared cannot be combined. Procedures and stations are named by ID or by exact name.

Environments

ENVIRONMENTS is a comma-separated list of production, preview and development. A procedure or shared variable added without one targets all three. A station variable has no environment and counts as production.

One key can have several values at one level when their environments do not overlap. update and remove then need the environment of the value they change.

add

The add subcommand creates an environment variable. Without --value, the value is read from stdin, or asked for at a prompt (hidden for a Secret).

add environment variables
# Secret, the default type
tofupilot env add MES_TOKEN production --value "..." --yes

# Config, readable after saving
tofupilot env add LINE preview,development --no-sensitive --value "line-1"
tofupilot env add MES_URL production --type config --value https://mes.example.com
tofupilot env add DMM_RESOURCE --station line-1-bench-2 --no-sensitive --value "TCPIP0::10.0.0.7::INSTR"
tofupilot env add SETTLE_MS --shared --no-sensitive --value-type integer --value 200

# In a script: reads stdin, without its final line break
printf %s "$TOKEN" | tofupilot env add MES_TOKEN --station line-1-bench-2
FlagMeaning
--type <TYPE>secret (default) or config
--sensitiveSame as --type secret
--no-sensitiveSame as --type config
--value <VALUE>The value. A Secret passed here lands in the shell history: prefer stdin or the prompt
--note <TEXT>Where to rotate the value, or who to contact. Shown where the value is set
--value-type <TYPE>string, number, integer or boolean. The value is checked against it
--forceOverwrite an existing variable with the same key and level whose environments overlap the ones given; it then targets exactly those, and a Config given --type secret becomes a Secret. Both are confirmed first unless --yes. Without it, add stops and names --force
-y, --yesSkip confirmations
--procedure, --station, --sharedThe level

A key is upper case letters, digits and _, not starting with a digit; TOFUPILOT_* is reserved. An empty value sets nothing.

Adding with --type secret and --force, or update --type secret, over an existing Config converts it to a Secret in place. A Secret cannot become a Config: Saved secrets are write-only, so this variable can't be changed to Config. Remove it and add it again.

list

The list subcommand (alias ls) lists the environment variables of one level: key, type, value (Config) or digest (Secret), environments, level and last update. Pass an environment to show only the values that target it.

list environment variables
tofupilot env list
tofupilot env ls production --station line-1-bench-2
tofupilot env ls --shared --type secret
FlagMeaning
[ENVIRONMENT]production, preview or development
--type <TYPE>Only config or only secret
--procedure, --station, --sharedThe level

A digest changes when its value changes. Digests are specific to a row, so two rows holding the same value show different digests.

update

The update subcommand sets a new value on an existing environment variable, and stops when there is none. It takes the same value flags as add.

rotate a secret
tofupilot env update MES_TOKEN production

The version increases, so each run records which value it used.

remove

The remove subcommand (alias rm) removes an environment variable. It asks for confirmation unless --yes is passed.

remove an environment variable
tofupilot env rm MES_URL preview --yes

pull

The pull subcommand writes the procedure's development values, Config and Secret, into .env.local, where a source run reads them.

pull development values
tofupilot env pull
tofupilot env pull .env.bench --station line-1-bench-2
OptionMeaning
[FILENAME]The file to write, default .env.local
--procedure <ID_OR_NAME>Default: the directory's linked procedure
--station <ID_OR_NAME>Include that station's Config values
-y, --yesOverwrite an existing file

A Secret is included only when it targets development. The file is written with mode 0600, and the command warns when .gitignore does not list it.

run

The run subcommand runs a command with the linked procedure's development values in its environment, without writing a file.

run with development values
tofupilot env run -- python scripts/check_mes.py

resolve

The resolve subcommand shows, for each key a procedure would receive, the value that wins, its level and the lower levels it shadows. It resolves for an environment (default production), and includes a station's values with --station.

which value wins
tofupilot env resolve production --station line-1-bench-2

Secrets follow the precedence rules: a station Secret is left out of a non-production environment. Only keys with a value are listed; the YAML default: is applied when the run starts.

Permissions

RoleCan
Viewer and abovelist and resolve (Secrets as digests only)
DeveloperAdd, update and remove Config variables that do not target production
Admin, OwnerAlso Secrets, station variables and anything that targets production

Since the default type is Secret and the default environments include production, a Developer passes --no-sensitive and preview or development explicitly.

How is this guide?

On this page