LPM-cli

lpm env

Manage project environment variables and secrets — local-file storage, cloud sync, platform integrations, and OIDC policies.

lpm env set KEY=VALUE              # set one or many vars
lpm env get KEY                    # read one (masked unless --reveal)
lpm env list                       # list all (masked unless --reveal)
lpm env delete KEY                 # remove
lpm env push                       # encrypt + push to lpm.dev
lpm env pull                       # pull + decrypt
lpm env push --to vercel           # push to a connected platform

lpm env manages encrypted environment variables for the project. Local secrets live in an OS-keychain-backed vault; cloud sync persists them to lpm.dev and platform integrations push them to Vercel, Netlify, Railway, and other connected providers.

For the underlying storage and encryption model, see Secrets vault.

Local-file management

lpm env list                              # list all vars (values masked)
lpm env list --reveal                     # list with values shown
lpm env get DATABASE_URL                  # get one var
lpm env get DATABASE_URL --reveal         # get with value shown
lpm env set DATABASE_URL=postgres://...   # set one
lpm env set FOO=bar BAZ=qux               # set many at once
lpm env delete FOO BAZ                    # delete one or more
lpm env import .env.production            # import from a file
lpm env import .env --overwrite           # overwrite existing values
lpm env export .env.backup                # export to a file

Per-environment scoping

Pass --env=<name> to scope reads and writes to a named environment (e.g., staging, production). Environments are stored independently — staging and production keep separate value sets for the same key.

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

Other local commands

lpm env init                              # interactive environment setup
lpm env ls                                # environment overview table with sync/update status
lpm env copy <src> <dst>                  # copy all secrets between envs
lpm env print                             # print resolved env (for `eval`)
lpm env check                             # validate against the project schema
lpm env example                           # generate `.env.example` from the schema

Cloud sync

lpm env pull and lpm env push round-trip the local vault to lpm.dev's encrypted storage. The server only stores ciphertext — it never sees plaintext values.

lpm env push                              # encrypt + push the local vault
lpm env pull                              # pull + decrypt remote → local
lpm env diff                              # diff local vs remote (default env)
lpm env diff staging                      # diff local staging vs remote staging
lpm env diff staging production           # diff two local environments
lpm env validate                          # check remote against the schema
lpm env share --org <org-slug>            # share the vault with an org
lpm env pair <CODE>                       # pair this device via dashboard code (interactive confirmation)
lpm env pair <CODE> --yes                 # skip the confirmation prompt (NOT recommended)
lpm env unpair                            # revoke this device's pairing
lpm env log                               # last 50 audit log entries
lpm env rotate-key                        # rotate the vault wrapping key
lpm env rotate-sharing-key                # rotate your X25519 sharing key (interactive, step-up reauth)

Cloud sync is plan-gated. Free accounts get local-only storage; Pro/Org plans unlock push/pull/share.

Rotating your sharing key

lpm env rotate-sharing-key generates a fresh X25519 keypair, uploads the new public key under a vault:public-key:rotate step-up proof, and invalidates every org-vault wrapped-key entry the server held for you. The CLI keeps the new private key in a pending slot until the server has acknowledged the rotation, so a crash mid-flight is safe — re-running the command resumes the pending slot if the server already moved on. The flow:

  1. Prints the blast radius — every org vault you have access to needs an owner or admin to run lpm env share --org <slug> before pulls resume.
  2. Asks you to type ROTATE (uppercase) to confirm.
  3. Prompts for your password (and authenticator code, if MFA is enrolled) to mint the step-up proof.
  4. Uploads the new public key; the server invalidates the old wrapped-key rows and sends an out-of-band security email to your account plus an impact email to every affected org's owners and admins.
  5. Promotes the pending slot to the live keychain entry. The dashboard's vault Member Access view shows the affected rows as Needs share.

rotate-sharing-key refuses to run without a TTY — there's no --yes / non-interactive path, by design. On every machine where you want to keep pulling, you re-register the rotated key the next time the CLI needs it: any org-touching verb (env share, env pull --org, etc.) detects a missing server-side key and walks you through a vault:public-key:set step-up to register it.

The pre-rotation key never re-establishes itself. If a teammate's machine still has the old private key it cannot decrypt anything pushed under the new AES key, and the dashboard's audit log records the rotation with both fingerprints so cross-team forensics are trivial.

Platform integrations

Push the local vault out to deployment platforms — Vercel, Netlify, Railway, etc. — without copy/pasting values.

lpm env connect <platform> --project=<id>          # link a platform project
lpm env push --to vercel                            # push current env to Vercel
lpm env push --to vercel --env=production --clean   # replace platform values
lpm env pull --from vercel                          # pull from a platform
lpm env status                                      # show connected platforms

OIDC policies (CI)

Issue short-lived tokens to CI runs that prove repo identity, then exchange them for vault decrypt access — no long-lived tokens stored in CI secrets.

lpm env oidc allow --provider=github --repo=owner/repo --branch=main --env=production
lpm env oidc list                                   # list configured policies
lpm env pull --oidc --env=production --output=.env  # CI-side decrypt

lpm ci setup github-actions and lpm ci setup gitlab generate ready-to-paste snippets that wire OIDC and call lpm env pull --oidc automatically. The two providers expose OIDC differently:

  • GitHub Actions — the GitHub runtime exposes ACTIONS_ID_TOKEN_REQUEST_URL + ACTIONS_ID_TOKEN_REQUEST_TOKEN to any job that declares permissions: id-token: write, and the CLI fetches the JWT at run time. The emitted snippet relies on this — it does not set LPM_OIDC_TOKEN.
  • GitLab CI — the runtime has no equivalent of GitHub's runtime fetch, so the snippet mints LPM_OIDC_TOKEN via the id_tokens block with aud: https://lpm.dev. The CLI then routes it through the registry-exchange surface as a pre-supplied token.

You can also set LPM_OIDC_TOKEN by hand on either provider — for self-hosted GitHub runners that lack the runtime endpoint, or for any non-standard CI where you've fetched a https://lpm.dev-audience JWT some other way.

Flags

FlagEffect
--env=<name>Scope to a named environment (default: default)
--revealShow values in get / list (default is masked)
--overwriteimport overwrites existing keys instead of skipping
--to <platform>push target platform (vercel, netlify, …)
--from <platform>pull source platform
--cleanReplace platform values instead of merging
--yesSkip confirmation prompts
--oidcUse OIDC token exchange (CI) instead of stored creds
--output <file>Write pull results to a file instead of the vault
--org <slug>Org-scoped sync target

Plus the global flags.

See also

  • Secrets vault — storage and encryption design, sharing-key lifecycle, CLI step-up reauth
  • lpm ci — generate CI YAML with OIDC wiring
  • lpm.jsonenvSchema and environment definitions