Docs
Guidesince cloud@2026-09-10

Staging and production

Create an environment in the console, push to it by name, and grant the role that lets someone read it.

A project starts with one environment called development. Staging and production are more of the same shape: a name inside your project, holding its own version of every key. Reaching one is a permission question, answered by the roles someone granted you on the project's Access page.

Create the environment

An environment is created in the console. Open your project and use its environment list, which shows each environment with how many keys it holds.

The command line creates only the first one. penv push on a schema with no @penv= header creates the project with a single development environment and writes the slug into the header. Anything after that is a console action, or POST /api/v1/orgs/{org}/projects at the moment you create the project, whose body carries the environment names you want.

Push to it by name

penv push --env staging

--env picks the environment this command writes to. Everything else about push is unchanged: it sends every key with its decorators and the value your local .env holds, and it deletes .env when the write succeeds.

Two flags are worth knowing before you point one at a live environment:

  • --org <slug> says which workspace owns a project penv is about to create. It matters only on the first push of a repository.
  • --prune deletes cloud keys the schema no longer lists. A coding agent session is refused it outright, so a person has to run it.

--prune deletes values. Open the environment in the console and read the key list first, because the version history of a deleted key goes with it.

Which environment a command reads

--env, then PENV_ENV, then development. That order holds for every command that touches the cloud.

Where you areWhat you get
Local mode, no @penv= headerdevelopment only. Every other name is refused with exit code 6.
Cloud mode, signed in as a personWhatever your role assignments reach.
Cloud mode, a machine credentialThe one environment that credential is bound to.

An identity asking for an environment it holds nothing on gets 403 forbidden from the server, which penv reports as environment_refused and exit code 6, naming the address it was refused:

penv: this identity may not read acme/api-gateway/production.
      Ask the console for a role on that environment, or pick another with --env.

Who may read production

There is no separate unlock for production. It is reached the same way staging is: someone grants you a role scoped to that project or that environment on the project's Access page, and the server answers your reads from that grant. That page lists who holds which role and where, and grants or revokes those grants. Granting one needs member:role_assign at the scope you are granting.

What you want to doPermission you need
See the Access pagemember:read at that project
Grant or revoke a role theremember:role_assign at the target scope
Read values in an environmentsecret:reveal at that environment
List keys and decorators without valuessecret:read at that environment

penv pull and penv run read values, so they need secret:reveal. A read that asks for decorators alone (?values=false on the API) needs only secret:read, which is how a build can validate a schema without opening anything.

Every value opened this way writes one row in the record of who did what, carrying the credential and, when a coding agent is driving, the harness and session that opened it.

Do it in order

  1. Open your project in the console and create the environment.
  2. Grant yourself, or the person who needs it, a role scoped to that environment on the Access page.
  3. Put the values in a local .env for that environment, or set them one at a time with penv set KEY --env staging.
  4. penv check until it prints ok.
  5. penv push --env staging.
  6. penv run --env staging -- <your command> to prove the environment resolves.
  7. Repeat for production once someone with member:role_assign has granted you a role there.

Run your app locally