Quickstart
Write .env.schema from your .env, run your app on validated values, and push them to Penv Cloud.
Write the schema
penv initpenv init reads .env and .env.*, writes .env.schema and .penv/config.toml, and adds .env, .env.* and !.env.schema to .gitignore.
# @type=url
DATABASE_URL=
# @type=string
STRIPE_SECRET_KEY=
# @type=port @sensitive=false
PORT=3000At a terminal, init asks which coding-agent harnesses to guard, with installed ones preselected, and writes a typed file per detected language (penv gen).
With no .env, init writes an empty one; add keys and run penv init --force. Inference rules: from a .env file.
Run the app
penv run -- pnpm devpenv run validates your values against .env.schema and starts the child with them. A missing or invalid value stops it and names the key. penv masks every value not marked public in the child's output (keep agents out of .env).
Sign in
penv loginpenv login prints an eight-character code and our approval address, and opens it in a browser at a terminal. penv keeps the credential in your OS keychain; we honor it for 30 days from last use, and at most 90 days.
Push the values
penv pushWith no @penv= header, penv push has us create a project with a development environment, writes our slug into the header, sends the values .env and .env.<env> hold, and deletes those files. *.local files stay. Console alternative: first workspace.
Run from a fresh clone
penv run -- pnpm devTeammates with a role on the environment run it in a clone.
Repository files
| Path | Committed | Contents |
|---|---|---|
.env.schema | Yes | Keys and decorators (format). |
.env | No | Deleted by penv push. penv pull writes it again. |
.penv/config.toml | Yes | Settings, [schema] version, and [targets.<name>] for typed file output. |
Environment selection
--env, then PENV_ENV, then the value of the key @currentEnv names, then development (environments and precedence). We decide access; when we refuse, penv exits 6 with environment_refused (exit codes).