From a .env file
What penv init reads from your .env, what it infers for each key, and which values it keeps out of .env.schema.
penv initpenv init reads .env and your other value files in the working directory (.env wins a duplicate key) and writes .env.schema beside them. Nothing leaves your machine, and .env stays in place.
If .env.schema exists, init keeps it, still updates .gitignore and .penv/config.toml, and points you to penv check. penv init --force writes the schema again.
Inference per key
| Property | Rule |
|---|---|
| Type | From the shape of the value, written as @type=. |
| Required | An empty value is required. A value on the line becomes the default and makes the key optional. |
| Sensitive | Sensitive unless its value is copied as a default, or the key has a bundler prefix: NEXT_PUBLIC_, VITE_, PUBLIC_, EXPO_PUBLIC_, NUXT_PUBLIC_, REACT_APP_, GATSBY_, VUE_APP_, STORYBOOK_. |
# @type=url
DATABASE_URL=
# @type=string
STRIPE_SECRET_KEY=
# @type=port @sensitive=false
PORT=3000
# @type=boolean @sensitive=false
DEBUG=trueValues kept out of the schema
A value is copied as a default only when the key has a bundler prefix, or the value is one of:
- a boolean or an integer
- a lowercase word of letters
- a short lowercase slug such as
us-east-1,gpt-4oorapi.internal - a localhost URL with no user information and no query string
A key whose name contains one of these words, or its plural, never has its value copied, whatever the value or prefix:
AUTH KEY SECRET TOKEN PASSWORD PASSWD PASSPHRASE PASS PWD PW CREDENTIAL CRED DSN SALT SEED SIGNATURE
NEXT_PUBLIC_SUPABASE_ANON_KEY therefore keeps its value out of the schema and is still marked public, because the prefix puts it in the browser bundle.
Edit the schema
# The gateway the API talks to.
# @type=string(startsWith=sk_) @rotate=90d
STRIPE_SECRET_KEY=
# @type=enum(development,staging,production)
NODE_ENV=developmentYour decorators follow @env-spec (item decorators, data types). penv's additions such as @rotate, and its deviations: the .env.schema format.
penv check reports, among others:
| Diagnostic | Severity | Cause |
|---|---|---|
unknown_decorator | Warning; penv ignores the decorator | A decorator penv does not act on. |
sensitive_public_key | Error | A bundler-prefixed key marked @sensitive. |
Unwritable lines
penv writes only the dotenv subset that Node's util.parseEnv and dotenv both read back (the .env.schema format). Its reader accepts more of your file and warns once per value with line and column, never the character. init counts those lines; penv check names them.