Skip to content

Credentials and resource secrets

A dashboard administrator session authorizes management operations. An app API credential authenticates supported public app APIs. A webhook signing key verifies receiver messages. Provider secrets configure external services. These are not interchangeable.

CLI login sessions remain in the OS credential store. The storage choices below apply only to app API secrets generated by apps create and credentials create, not login sessions, webhook keys or provider credentials.

Choose before creating the remote resource:

--secret-store Behavior
env Save only to the specified server env file. No app-secret Keychain copy.
keychain Save only to the profile/app-scoped OS credential store.
both Save to Keychain first, then the specified env file. Not an atomic two-destination transaction.
none Deliberately discard the generated value. Nothing is saved or printed.

There is no default destination. Interactive execution with --yes asks if the choice is missing; agents/non-interactive commands and dry-runs must pass --secret-store. Missing or invalid choices fail before remote creation. With interactive env/both selection, the CLI can also ask for the file; otherwise pass --env-output explicitly.

Terminal window
# Select the intended profile/account/app explicitly for your workspace.
privy apps create --account ACCOUNT_ID --name my-dev-app \
--secret-store env --env-output .env.local --dry-run
privy apps create --account ACCOUNT_ID --name my-dev-app \
--secret-store env --env-output .env.local --yes
# A separate credential, stored in both places:
privy credentials create --access-mode read_only \
--secret-store both --env-output .env.backend --yes
# No plaintext file:
privy credentials create --access-mode read_only --secret-store keychain --yes
# Intentional discard, for example when only frontend setup is needed:
privy apps create --account ACCOUNT_ID --name frontend-demo --secret-store none --yes

--env-output is a file destination, not an input to the CLI runtime. Do not substitute Node’s --env-file option; that option can load a file into Node before CLI validation.

The default variable is PRIVY_APP_SECRET; --env-key BACKEND_PRIVY_SECRET chooses another server-only variable. Frontend-public prefixes such as NEXT_PUBLIC_, VITE_ and EXPO_PUBLIC_ are refused. Frontend login integration uses the public App ID, not this secret. Configuring an app secret does not write the App ID or configure the frontend SDK automatically.

  • Use .env, .env.local, .env.backend or another env filename. The parent must already exist, belong to you and have no symlink components; use its canonical path.
  • Env saving requires the git executable for protection checks, including detection of a non-Git directory. Inside Git, the destination must be untracked and ignored before execution. The CLI does not silently change .gitignore. Outside a Git worktree, output explicitly reports that Git protection was not established; ignore the file before initializing a repository.
  • Unrelated assignments/comments are preserved. Existing target variables require --overwrite-env; neither --yes nor choosing both implicitly consents to replacement.
  • Files are installed with 0600 permissions. Symlinks, hardlinks, files over1MiB, duplicate target assignments and unsupported/multiline dotenv syntax are refused. Use a dedicated env file when necessary.
  • Dry-run validates the destination options but does not read/write an env file, access the vault or check Git. Execution performs filesystem/Git checks before the remote creation and rechecks before installing the value.
  • A cooperative .privy-lock prevents simultaneous CLI writers. External file changes detected since preflight cause refusal instead of overwriting. Do not edit the target during creation or remove a lock belonging to a running process.
  • Atomic installation uses a private ignored staging directory. An interrupted process may leave its lock/staging directory; inspect remote state and stop the writer before deliberate local cleanup.
  • The CLI never prints generated values, even in previews, diffs or error details. Your editor, backend, dotenv tooling and deployment environment must also keep them server-side and out of logs/Git.

A successful response reports storage.mode and each destination’s status. File/vault read-back verifies persistence, not the backend application’s configuration or successful API use.

If remote creation succeeds but storage fails, do not blindly repeat creation. Inspect the returned resource/reference, destination statuses and reason; with both, Keychain may already contain the value even if the file write failed. SECRET_INDEX_FAILED means the OS-vault write succeeded but its nonsecret index did not. A captured value is not rolled back on later metadata-verification failure. No automatic recreation or rollback occurs.

none is deliberate: a one-time value may be unrecoverable afterward. Creating another credential is a separate, explicit operation.

Terminal window
privy schema credentials create
privy credentials list
privy credentials create --access-mode read_only --secret-store keychain --dry-run
privy credentials create --access-mode read_only --secret-store keychain --yes
privy secrets list
privy secrets status app-credential CREDENTIAL_ID

Choose the least access needed; public API writes require a full-access credential. apps create handles the initial generated secret using your chosen destination. credentials create creates an additional credential, with the same storage choices. Both handle the value before fresh remote metadata verification.

For vault storage, use the exact returned reference. Separate credentials use app-credential CREDENTIAL_ID. If initial app creation returns no credential ID, its local reference is app-secret initial; initial is not a remote credential ID.

CLI operations accepting --credential CREDENTIAL_ID currently resolve an app-credential from the vault; they do not source arbitrary env files. For those operations, choose keychain or both when creating that credential. Env-only storage is appropriate for a backend/SDK that reads your env file.

Rotation is create replacement → securely deploy/use it → verify consumers → explicitly revoke old credential. Never revoke the old one merely because a new credential was created. App API-secret rotation is not app verification-key rotation or external JWT verifier replacement.

secrets commands manage OS-vault references only, not env files. References contain app ID, kind and resource ID. No values are written into privy.json or profile JSON.

  • secrets list: indexed references only; no secret reads or network. Env-only secrets do not appear here.
  • secrets status KIND ID: vault presence, never value; not remote validation.
  • secrets forget KIND ID --yes: local vault removal only, not remote revocation.
  • secrets run: give one secret to a trusted child through an explicitly named environment variable, without a shell.
Terminal window
privy secrets run app-credential CREDENTIAL_ID --env PRIVY_APP_SECRET --dry-run -- node server.js
# Only after approving that exact child program:
privy secrets run app-credential CREDENTIAL_ID --env PRIVY_APP_SECRET --yes -- node server.js
# For an initial app secret captured without a remote credential ID:
privy secrets run app-secret initial --env PRIVY_APP_SECRET --yes -- node server.js

Child output is not redacted. Do not use env, printenv, debug dumps or an untrusted program to inspect a secret. Environment injection avoids argv exposure, not a malicious child’s access. The app/profile lock is released before the child runs.

CLI logout retains independent resource secrets. Verified credential/webhook deletion clears the corresponding indexed vault value; app deletion cleans indexed app resources. An initial app-secret initial reference cannot be associated with an individual remote credential deletion; deliberately forget it if that credential is revoked, or let verified app deletion clean it. Remote deletion/revocation never rewrites your env files—remove/update obsolete values explicitly. If vault cleanup fails after remote success, repair the reference rather than repeating the remote mutation.

The env destination feature is for generated app API secrets, not arbitrary provider-secret input. Fields marked sensitive in privy schema COMMAND must still arrive as JSON on stdin (--body - or --file -), never as typed secret flags, plaintext body files, chat messages or logged shell commands. Feed stdin from an approved secret source; do not echo values or put them in an agent-recorded here-document. --file - means stdin, not a persisted file.

Missing provider credentials are a genuine human/provider prerequisite. Tell the operator what is needed and how to supply it securely, without requesting secrets in chat. Complete URLs may contain credentials. Masked read-back proves presence/public metadata, not exact stored value or external operation. Image-upload checkpoints are local recovery metadata, not image-host deletion controls.

Privy CLI is an unofficial, community project by Samarth Saxena. Not affiliated with or endorsed by Privy. The Privy name and wordmark belong to Privy. It uses undocumented dashboard APIs that can change.