Skip to content

CLI Commands Reference

The SecretSpec CLI provides commands for managing secrets across different providers and profiles.

These options are available on every command:

OptionDescription
-f, --file <FILE>Path to secretspec.toml (default: auto-detect). Env: SECRETSPEC_FILE
--reason <REASON>Reason for accessing secrets, recorded by providers that support audit logging (e.g. Proton Pass agent sessions). Takes precedence over PROTON_PASS_AGENT_REASON. Env: SECRETSPEC_REASON
Terminal window
$ secretspec run --reason "Deploying web frontend" -- ./deploy.sh

Initialize a new secretspec.toml configuration file from an existing .env file.

Terminal window
secretspec init [OPTIONS]

Options:

  • --from <PATH> - Path to .env file to import from (default: .env)

Example:

Terminal window
$ secretspec init --from .env.example
Created secretspec.toml with 5 secrets

Initialize user configuration interactively.

Terminal window
secretspec config init

Example:

Terminal window
$ secretspec config init
? Select your preferred provider backend:
> keyring: System keychain
? Select your default profile:
> development
Configuration saved to ~/.config/secretspec/config.toml

Display current configuration.

Terminal window
secretspec config show

Example:

Terminal window
$ secretspec config show
Provider: keyring
Profile: development

Add a provider alias to your user-level configuration (~/.config/secretspec/config.toml).

To share aliases with your team, declare them in a top-level [providers] table in secretspec.toml instead — they take precedence over user-level aliases on name conflict.

Terminal window
secretspec config provider add <ALIAS> <URI>

Arguments:

  • <ALIAS> - Short name for the provider (e.g., prod_vault, shared)
  • <URI> - Provider URI (e.g., onepassword://vault/Production, env://)

Example:

Terminal window
$ secretspec config provider add prod_vault "onepassword://vault/Production"
Provider alias 'prod_vault' saved
$ secretspec config provider add shared "onepassword://vault/Shared"
Provider alias 'shared' saved

List all configured user-level provider aliases. Project-level aliases declared in secretspec.toml are not shown by this command.

Terminal window
secretspec config provider list

Example:

Terminal window
$ secretspec config provider list
prod_vault onepassword://vault/Production
shared onepassword://vault/Shared
env env://

Remove a provider alias from your user-level configuration. To remove a project-level alias, edit the [providers] table in secretspec.toml directly.

Terminal window
secretspec config provider remove <ALIAS>

Arguments:

  • <ALIAS> - Name of the alias to remove

Example:

Terminal window
$ secretspec config provider remove prod_vault
Provider alias 'prod_vault' removed

Check if all required secrets are available, with interactive prompting for missing secrets.

Terminal window
secretspec check [OPTIONS]

Options:

  • -p, --provider <PROVIDER> - Provider backend to use
  • -P, --profile <PROFILE> - Profile to use
  • -n, --no-prompt - Don’t prompt for missing secrets (exit with error if any are missing)
  • --json - Print a value-free resolution report as JSON instead of prompting
  • --explain - Print a value-free, human-readable resolution trace instead of prompting

Example:

Terminal window
$ secretspec check --profile production
DATABASE_URL - Database connection string
API_KEY - API key for external service (required)
Enter value for API_KEY (profile: production): ****
Secret 'API_KEY' saved to keyring (profile: production)

--json and --explain report how every declared secret resolved for the active profile without prompting and without ever printing a secret value. Both exit non-zero when a required secret is missing, so they work as a CI gate.

--explain prints a human-readable trace:

Terminal window
$ secretspec check --profile production --explain
profile: production
provider: keyring://
DATABASE_URL ok source keyring://
JWT_SECRET ok generated
LOG_LEVEL ok default value
SENTRY_DSN missing optional
STRIPE_KEY MISSING required

--json emits a versioned, machine-readable object for tooling and CI. Each entry reports the status (resolved, missing_required, missing_optional), whether the value came from a provider (source_provider, credential-free), a generator (generated), or a committed default (default_applied), and whether it is exposed as_path. No secret values appear. The canonical JSON Schema is committed at schema/resolution-report.schema.json.

Terminal window
$ secretspec check --profile production --json
{
"schema_version": 1,
"provider": "keyring://",
"profile": "production",
"secrets": [
{ "name": "DATABASE_URL", "status": "resolved", "required": true, "source_provider": "keyring://", "default_applied": false, "generated": false, "as_path": false },
{ "name": "STRIPE_KEY", "status": "missing_required", "required": true, "default_applied": false, "generated": false, "as_path": false }
]
}

Get a secret value.

Terminal window
secretspec get [OPTIONS] <NAME>

Options:

  • -p, --provider <PROVIDER> - Provider backend to use
  • -P, --profile <PROFILE> - Profile to use

Example:

Terminal window
$ secretspec get DATABASE_URL --profile production
postgresql://prod.example.com/mydb

Emit a single-root JSON Schema for the manifest’s typed shape: by default the union SecretSpec (safe for any profile); with --profile, that profile’s exact fields. Value-free: reads only the manifest, never a provider.

Terminal window
secretspec schema [OPTIONS]

Options:

  • -P, --profile <PROFILE> - Emit the schema for this profile’s fields instead of the union
  • -o, --output <FILE> - Write to this file instead of stdout

Rather than ship a typed-accessor generator per language, feed this schema to quicktype, which generates an idiomatic type and deserializer for any language. Name the type with --top-level. At runtime, hand the generated deserializer the flat {SECRET_NAME: value} map from the SDK’s fields() helper:

Terminal window
$ secretspec schema | quicktype -s schema --top-level SecretSpec --lang python -o secrets_gen.py
from secretspec import SecretSpec
from secrets_gen import SecretSpec as Secrets # quicktype-generated, typed
resolved = SecretSpec.builder().with_reason("boot").load()
s = Secrets.from_dict(resolved.fields())
print(s.database_url) # typed str

The same pattern works in every SDK: Go UnmarshalSecretSpec(resolved.FieldsJSON()), TypeScript Convert.toSecretSpec(resolved.fieldsJson()), Ruby SecretSpec.from_dynamic!(resolved.fields).

Set a secret value.

Terminal window
secretspec set [OPTIONS] <NAME> [VALUE]

Options:

  • -p, --provider <PROVIDER> - Provider backend to use
  • -P, --profile <PROFILE> - Profile to use

Example:

Terminal window
$ secretspec set API_KEY sk-1234567890
Secret 'API_KEY' saved to keyring (profile: development)

Run a command with secrets injected as environment variables.

Terminal window
secretspec run [OPTIONS] -- <COMMAND>

Options:

  • -p, --provider <PROVIDER> - Provider backend to use
  • -P, --profile <PROFILE> - Profile to use

Examples:

Terminal window
# Run npm with secrets available as environment variables
$ secretspec run --profile production -- npm run deploy
# Verify secrets are injected
$ secretspec run -- env | grep DATABASE_URL
DATABASE_URL=postgresql://localhost/mydb

Import secrets from one provider to another.

Terminal window
secretspec import <FROM_PROVIDER>

The destination provider and profile are determined from your configuration. Secrets that already exist in the destination provider will not be overwritten.

Arguments:

  • <FROM_PROVIDER> - Provider to import from (e.g., env, dotenv:/path/to/.env)

Example:

Terminal window
# Import from environment variables to your default provider
$ secretspec import env
Importing secrets from env to keyring (profile: development)...
DATABASE_URL - Database connection string
API_KEY - API key for external service (already exists in target)
REDIS_URL - Redis connection URL (not found in source)
Summary: 1 imported, 1 already exists, 1 not found in source
# Import from a specific .env file
$ secretspec import dotenv:/home/user/old-project/.env

Use Cases:

  • Migrate from .env files to a secure provider like keyring or OnePassword
  • Copy secrets between different profiles or projects
  • Import existing environment variables into SecretSpec management

Show the local audit log of secret access.

Terminal window
secretspec audit [--project <NAME>] [--action <ACTION>] [-n <N>] [--json]

Options:

  • --project <NAME> - Only show entries for this project
  • --action <ACTION> - Only show entries for this action (get, set, check, run, import)
  • -n, --tail <N> - Show only the last N entries
  • --json - Output raw JSON Lines instead of the formatted summary

The log location is read from your user-global config ([audit] in ~/.config/secretspec/config.toml), defaulting to the per-user state directory.

Example:

Terminal window
$ secretspec audit --action run -n 5
2026-06-04T18:06:29Z run found ./deploy.sh API_KEY,DATABASE_URL (my-app/production) reason: deploy [claude-code]
# Pipe raw entries to jq
$ secretspec audit --json | jq 'select(.outcome == "missing")'
VariableDescription
SECRETSPEC_PROFILEDefault profile to use
SECRETSPEC_PROVIDERDefault provider to use
SECRETSPEC_FILEPath to secretspec.toml (same as --file)
SECRETSPEC_REASONReason for accessing secrets (same as --reason)
Terminal window
# Initialize from existing .env
$ secretspec init --from .env
# Set up user configuration
$ secretspec config init
# Import existing secrets (optional)
$ secretspec import env # or: secretspec import dotenv:.env.old
# Check and set missing secrets
$ secretspec check
# Run your application
$ secretspec run -- npm start