The variables penv reads
Every variable penv 1.0.0-rc.1 and its installers read, what each changes, the masking triggers, and what a child process of penv run receives.
Variables penv 1.0.0-rc.1 reads. Project settings live in .penv/config.toml; flags are on each command page and on global options.
penv
| Variable | Effect |
|---|---|
PENV_ENV | Environment a command reads when --env is absent; wins over the @currentEnv key. Precedence: environments and precedence. |
PENV_TOKEN | Your pck_ machine credential. Read before the OS keychain and every other credential source (machine identity). |
PENV_URL | Our address, used instead of https://penv.cloud and before [providers.penv] url. https anywhere; plain http only for 127.0.0.1, localhost and [::1], otherwise bad_url. |
PENV_OIDC_TOKEN | A platform token exchanged as it stands, for any platform not listed below or a self-minted token. |
PENV_BUNDLE_KEY | 64 hex characters. penv run opens .penv/<env>.bundle from penv bundle with it instead of reading from us. |
PENV_LOCAL_KEY | 64 hex characters: the key for enc:v1: values (penv encrypt) on a machine with no keychain. With neither this nor a keychain, penv keeps the key in penv/local.key under XDG_CONFIG_HOME (default $HOME/.config), or APPDATA on Windows. |
SSL_CERT_FILE | A PEM bundle penv trusts instead of its compiled-in Mozilla roots, for a network that inspects TLS. Under an agent, cloud commands refuse a bundle you own or can write as untrusted_ca_bundle. |
NO_COLOR | Any non-empty value turns color off. |
CLICOLOR | 0 turns color off; other values change nothing. |
Platform credentials
| Variable | Set by | Effect |
|---|---|---|
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY | AWS runtime | Both present: penv offers the machine's AWS identity as a credential. |
AWS_SESSION_TOKEN | AWS runtime | Carried into the signed request when a role supplied one. |
AWS_REGION | AWS runtime | STS region penv signs against. |
AWS_DEFAULT_REGION | AWS runtime | Read when AWS_REGION is unset. Neither means us-east-1. |
AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_ARN | EKS IRSA | Both present, and no AWS keys: penv exchanges the token file with STS for keys. |
AWS_ROLE_SESSION_NAME | EKS IRSA | STS session name; default penv. |
AWS_ENDPOINT_URL_STS, then AWS_ENDPOINT_URL | You | STS endpoint for that exchange. |
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI | ECS | Task role credentials from the ECS endpoint, tried after web identity. |
AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_CONTAINER_AUTHORIZATION_TOKEN, AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE | EKS Pod Identity | Credentials from that endpoint: https, loopback, or the ECS and EKS link-local hosts only. |
ACTIONS_ID_TOKEN_REQUEST_URL, ACTIONS_ID_TOKEN_REQUEST_TOKEN | GitHub Actions | Both present: penv mints a GitHub Actions token for the workspace. |
ID_TOKEN | GitLab CI | A platform token penv exchanges as it stands. The retired CI_JOB_JWT_V2 is ignored. |
Order: PENV_TOKEN, your login, an enrolled keypair, a platform token, then AWS keys, web identity and container. Per-platform setup: connect. Exchange details: API authentication.
Agent detection
"Set" means set and not 0 or false.
| Variable | Agent named |
|---|---|
AGENT | amp names Amp outright; any other name on penv's list is a weaker match. |
COPILOT_CLI (set) | Copilot |
CLAUDE_CODE_CHILD_SESSION, CLAUDECODE (set) | Claude Code |
CODEX_THREAD_ID, CODEX_SESSION_ID (present) | Codex |
GEMINI_CLI (set) | Gemini |
CURSOR_SANDBOX, CURSOR_AGENT (present) | Cursor |
CLINE_ACTIVE (set) | Cline |
ROO_ACTIVE, ROO_CLI_RUNTIME (set) | Roo |
OR_APP_NAME = Aider, any case | Aider |
PS1 holding ###PS1JSON### | OpenHands |
AI_AGENT | Shared convention; parsed as name_version_mode or name@version. |
Detection is a ladder: the first matching row wins, so colliding variables still resolve to one name. Order and agent behavior: coding agents.
| Session id variable | Agent |
|---|---|
CLAUDE_CODE_SESSION_ID | Claude Code |
CODEX_THREAD_ID, then CODEX_SESSION_ID | Codex |
CURSOR_TRACE_ID | Cursor |
AMP_CURRENT_THREAD_ID, then AGENT_THREAD_ID | Amp |
COPILOT_AGENT_SESSION_ID | Copilot |
penv stamps the session id on every request it sends us.
Masking
| Trigger | Effect |
|---|---|
Any penv run | Masking on by default, including inside Node, Bun, Deno and Python through a preload (--no-preload skips it). |
| A detected agent | JSON output, masking on. |
--agent | Same treatment, on purpose (global options). |
stdout not a terminal and GIT_EDITOR set to an editor that cannot prompt (true, cat) | Session recorded as non-interactive, masking on, no agent named. penv reveal and penv pull behave as for a person. |
penv run --no-mask | Masking off; human only (penv run). |
What masking covers: keep agents out of .env.
Detection reads variables any process can set or unset, so it only changes defaults. penv guard writes refusals into the harness's own settings.
System
| Variable | Effect |
|---|---|
PATH | Lookup for the penv run command and a language target's toolchain. |
PATHEXT | Runnable suffixes on Windows, so tsc finds tsc.cmd. |
HOME | ~/.penv for target and guard lookup; cache and local key directory on macOS and Linux. |
USERPROFILE | ~/.penv on Windows when HOME is unset. |
LOCALAPPDATA, APPDATA | Encrypted cache and local key file on Windows. |
XDG_CACHE_HOME, XDG_CONFIG_HOME | Encrypted cache (default $HOME/.cache) and local key file (default $HOME/.config) on Linux. |
COMPUTERNAME, then HOSTNAME, then HOST | Machine name on a reveal approval page. Without all three: /etc/hostname, then "the penv CLI". |
Installers
| Variable | Installer | Effect |
|---|---|---|
PENV_VERSION | Both | Pin a release tag such as v1.2.3. |
PENV_INSTALL_DIR | Both | Install directory. |
PENV_RELEASE_BASE | Both | Release address; used by installer tests. The binary has one compiled address. |
PENV_TARGET | install.sh | Install for another target triple. |
PENV_ALLOW_ROOT | install.sh | 1 installs as root (refused by default). |
PENV_ALLOW_ELEVATED | install.ps1 | 1 installs from an elevated shell (refused by default). |
PENV_ADD_TO_PATH | install.ps1 | 1 writes the user PATH; the only way when piping through iex. |
SHELL | install.sh | Which PATH line is printed. No startup file is edited. |
TMPDIR | install.sh | Scratch directory; default /tmp. |
PROCESSOR_ARCHITEW6432, then PROCESSOR_ARCHITECTURE | install.ps1 | Processor for the target triple, read only when the registry value is missing. The first wins because an x64 shell on ARM64 reports AMD64. |
Usage: install the CLI.
PENV_SIGNING_KEY (release workflow secret, read by an unpublished signing tool) and PENV_BLESS (rewrites test snapshots) exist in the penv repository; nothing that ships reads them.
Child process of penv run
| Receives | Detail |
|---|---|
| penv's own environment | Inherited as it stands. |
| Every resolved key | From your value files in local mode; from us, or a bundle, in cloud mode. A key left empty takes its schema default. |
PENV_ENV | The environment this run read. |
| Preload variables | With masking on: PENV_SENSITIVE, and NODE_OPTIONS, BUN_OPTIONS and PYTHONPATH extended, never replaced. |
| Color | FORCE_COLOR=1 and CLICOLOR_FORCE=1 when penv pipes output at a terminal, unless set or NO_COLOR is. |
| Sealed run | HTTPS_PROXY, HTTP_PROXY, empty NO_PROXY, NODE_USE_ENV_PROXY=1, and a CA bundle in SSL_CERT_FILE, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE, AWS_CA_BUNDLE, NODE_EXTRA_CA_CERTS and DENO_CERT. |
| Does not receive | Detail |
|---|---|
| Missing required keys | penv run exits 3 before starting anything. |
PENV_LOCAL_KEY, PENV_BUNDLE_KEY | penv removes both. |
| Unread output | With masking on, penv pipes stdout and stderr and scrubs every value not marked public that is four characters or longer; shorter ones get a warning. |
In cloud mode penv run writes values to disk only for random() keys, into .env.local (.env.test.local for test). Its cache of your values is encrypted with a key in the OS keychain; a host with no keychain gets no cache.
Apart from the two keys above, penv removes nothing it inherits: a PENV_TOKEN in your shell reaches the child. Set a pipeline credential on the step that needs it, not the whole job (CI builds).
Next: error codes.