# Managing secrets across environments (/docs/guides/managing-secrets)



`lpm env` is LPM CLI's surface for environment-scoped secrets. It stores values in encrypted form on disk, organizes them per-environment (`dev` / `staging` / `production`), and validates them against an env schema declared in `lpm.json`. This guide walks through the full lifecycle.

## 1. Set a few vars [#1-set-a-few-vars]

```bash
lpm env set DATABASE_URL=postgres://localhost/myapp
lpm env set API_KEY=sk-... LOG_LEVEL=debug          # multiple at once
```

`set` writes to the project's vault. Values are stored encrypted; only LPM CLI can read them back.

```bash
lpm env list                  # values are masked
lpm env list --reveal         # show actual values
lpm env get API_KEY --reveal  # show one
lpm env delete API_KEY        # remove
```

## 2. Per-environment vars [#2-per-environment-vars]

Use `--env=<name>` to scope a var to one environment:

```bash
lpm env set --env=staging API_URL=https://staging.example.com
lpm env set --env=production API_URL=https://api.example.com
lpm env list --env=staging
```

`lpm run start --env=staging` (or `lpm dev --env=staging`) loads only the staging-scoped vars plus any unscoped defaults.

## 3. Bulk import / export [#3-bulk-import--export]

Bring in a `.env`-style file:

```bash
lpm env import .env.production --env=production
lpm env import .env --overwrite       # overwrite any existing keys
```

Export back out (e.g., for a deploy hand-off):

```bash
lpm env export .env.backup
lpm env export .env.staging --env=staging
```

The exporter writes a plain `.env` format — be careful where the file lands. `.env.backup` should be in `.gitignore`.

## 4. Declare a schema [#4-declare-a-schema]

Project-shared validation goes in `lpm.json`:

```json title="lpm.json"
{
  "envSchema": {
    "vars": {
      "DATABASE_URL": { "required": true, "format": "url" },
      "API_KEY":      { "required": true, "secret": true },
      "LOG_LEVEL":    { "default": "info", "pattern": "^(trace|debug|info|warn|error)$" },
      "PORT":         { "default": "3000", "format": "port" }
    }
  }
}
```

Per-var fields:

| Field      | Effect                                                                                     |
| ---------- | ------------------------------------------------------------------------------------------ |
| `required` | Fail if not set                                                                            |
| `format`   | Built-in validator. One of: `url`, `email`, `port`, `boolean`, `integer`, `hostname`, `ip` |
| `pattern`  | Regex the value must match                                                                 |
| `default`  | Default value if unset                                                                     |
| `secret`   | Treat as sensitive — masked in logs and `lpm env list`                                     |

The check runs before `lpm run`, `lpm dev`, `lpm <file>`, and `lpm exec`. Skip with `--no-env-check` (don't do this in CI).

## 5. Named environments with inheritance [#5-named-environments-with-inheritance]

For projects with many `.env.*` variants:

```json title="lpm.json"
{
  "environments": {
    "base":    { "file": ".env" },
    "staging": { "extends": "base", "file": ".env.staging" },
    "preview": { "extends": "staging", "file": ".env.preview" }
  }
}
```

`extends` chains resolve transitively. `lpm dev --env=preview` loads `.env`, then `.env.staging` on top, then `.env.preview` on top of that — last write wins. Useful for "preview is staging plus a few overrides."

## 6. Onboarding a new contributor [#6-onboarding-a-new-contributor]

For a teammate joining a project that uses cloud sync (Pro/Org):

```bash
git clone <repo>
cd <repo>

# 1. Generate a pairing code in the LPM.dev Registry dashboard ("Pair device").
#    The dashboard will prompt you to re-enter your password (or your TOTP
#    code if you have MFA enrolled) before it issues the code — this
#    step-up check is what keeps an unattended unlocked browser from
#    silently pairing a new device on your behalf. Then redeem the code
#    on this machine. One-time per machine.
#
#    The CLI prints the browser-key fingerprint, the device label the
#    dashboard reported, and a two-digit "match number". Verify the same
#    match number is shown on your dashboard before answering 'y' — that
#    glance is what defeats a copy-pasted pairing command from an
#    untrusted source.
lpm env pair <code>

# 2. Pull the latest secrets — decrypted locally with the wrapping key
#    that pairing just installed in this machine's OS keychain.
lpm env pull

lpm install
lpm dev
```

The `vault` field in `lpm.json` is what links the working directory to the right cloud vault — see [Secrets vault — Per-project identity](/docs/infra/secrets-vault#per-project-identity). It's a UUID, not a secret; it ships with the repo so every clone resolves to the same vault.

For teams without cloud sync, hand secrets over out-of-band and use the import flow instead:

```bash
lpm env import .env.shared
```

Either way, the schema (`lpm.json > envSchema`) catches missing vars before runtime. The `secret: true` flag prevents accidental leaking into logs.

## What about `lpm vault`? [#what-about-lpm-vault]

The supported CLI surface for secrets is `lpm env`. "Vault" elsewhere in the docs refers to the underlying storage layer — OS keychain + encrypted file fallback + cloud-sync infrastructure. See [Secrets vault](/docs/infra/secrets-vault) for the storage and encryption design.

## Common pitfalls [#common-pitfalls]

* **`.env.backup` and `.env.shared` should be in `.gitignore`.** `lpm env export` writes plaintext — committing it defeats the encryption.
* **`--reveal` shows real values.** Don't pipe `lpm env list --reveal` into a CI log. Use it locally for verification only.
* **`--no-env-check` should never be on in CI.** Schema violations are usually real bugs surfaced early.

## See also [#see-also]

* [`lpm env`](/docs/dev/env) — full subcommand reference
* [`lpm.json` envSchema](/docs/reference/lpm-json#envschema) — schema field reference
* [`lpm.json` environments](/docs/reference/lpm-json#environments) — named environments with inheritance
* [Secrets vault](/docs/infra/secrets-vault) — storage and encryption design
