Penv Cloud
Start free
Docs
Guidesince 1.0.0-alpha.3

Run your app locally

penv run layers your value files, validates them against your schema, masks secrets in the output, and starts one child process with them.

penv run -- pnpm dev
penv run --env staging -- pnpm dev
penv why DATABASE_URL

penv run finds the nearest .env.schema upward, resolves and validates your values, and starts the command after -- with them. penv exits with the command's exit code. penv why names where a key's value comes from and whether it is masked, public or sealed; it never prints the value.

Value files

OrderFileScope
1.envShared
2.env.localThis machine. Skipped when the environment is test
3.env.<env>Shared
4.env.<env>.localThis machine

Later files win. A variable already set in your shell wins over every file. When your schema names a Penv Cloud project, the files layer on top of the values we serve, and penv names each cloud value a local file replaced.

Environment selection

--env, then PENV_ENV, then the key @currentEnv names, then development. See environments and precedence.

SourceRefusal
Value files onlyA name that cannot be a file name (local, schema, ../x) exits 3. With no .env.<env>, penv warns and uses the other layers
Penv Cloud, your loginExit 6 for an environment your roles do not reach
Penv Cloud, machine credentialExit 6 for any environment but the one bound

Cloud values

StateSource
Warm cacheEncrypted cache, keychain key
RevalidatingHEAD with the cached ETag
ChangedGET, then cache rewrite

development stays fresh for 60 seconds; every other environment revalidates on each run. When penv cannot reach us, it runs development from the cache with a daily warning, or from your local files with a warning; any other environment fails at exit 5. Details: local and cloud modes.

Child process

PropertyBehaviour
EnvironmentYour shell's environment, overridden by the resolved values, plus PENV_ENV
Command lookupA bare name is resolved along PATH (npm finds npm.cmd on Windows)
DiskNothing written, except a generated random() value, kept in .env.local (.env.test.local for test)
stdoutThe command's output only. penv writes its messages to stderr
Ctrl-CDelivered to the child
Killed by signal (Unix)Exit 128 plus the signal number

Masking

CaseBehaviour
Every penv runMasks your sensitive values in the command's output
Node, Bun, Deno, PythonA preload masks them inside the process too
Sensitive value under 4 charactersCannot be masked; penv warns
--no-maskWorks only when you run penv yourself in a terminal, with no pipe and no AI agent; otherwise ignored with a warning
--no-preloadHuman only

Variables: environment variables. Agent sessions: keep agents out of .env.

Validation

A missing or invalid value, or a failed @assert, stops the run at exit 3, naming the key, before the command starts. An empty key takes the default on its schema line.

ConditionBehaviour
Drift: a key with a value and no schema blockRuns. The value is masked and not validated. penv check names it
A value file, no .env.schemapenv writes the schema first, using the guards installed on your machine, without prompting

Exit codes

ExitCauseAction
3A value failed validation, or the environment name is invalidSet the named key, or fix the name
5Offline or no credentialReconnect. Only a cached development or your local files run offline
6Environment refused for this identityCheck the name, or request a role on it

All codes: errors.

Procedure

Run penv check and fix every reported key.

Run penv run -- <dev command> for development.

Run penv why <KEY> when a value is not the one you expected.