CLI Commands Reference
The SecretSpec CLI provides commands for managing secrets across different providers and profiles.
Global Options
Section titled “Global Options”These options are available on every command:
| Option | Description |
|---|---|
-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 |
$ secretspec run --reason "Deploying web frontend" -- ./deploy.shCommands
Section titled “Commands”Initialize a new secretspec.toml configuration file from an existing .env file.
secretspec init [OPTIONS]Options:
--from <PATH>- Path to .env file to import from (default:.env)
Example:
$ secretspec init --from .env.example✓ Created secretspec.toml with 5 secretsconfig init
Section titled “config init”Initialize user configuration interactively.
secretspec config initExample:
$ secretspec config init? Select your preferred provider backend:> keyring: System keychain? Select your default profile:> development✓ Configuration saved to ~/.config/secretspec/config.tomlconfig show
Section titled “config show”Display current configuration.
secretspec config showExample:
$ secretspec config showProvider: keyringProfile: developmentconfig provider add
Section titled “config provider add”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.
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:
$ 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' savedconfig provider list
Section titled “config provider list”List all configured user-level provider aliases. Project-level aliases declared in secretspec.toml are not shown by this command.
secretspec config provider listExample:
$ secretspec config provider listprod_vault → onepassword://vault/Productionshared → onepassword://vault/Sharedenv → env://config provider remove
Section titled “config provider remove”Remove a provider alias from your user-level configuration. To remove a project-level alias, edit the [providers] table in secretspec.toml directly.
secretspec config provider remove <ALIAS>Arguments:
<ALIAS>- Name of the alias to remove
Example:
$ secretspec config provider remove prod_vault✓ Provider alias 'prod_vault' removedCheck if all required secrets are available, with interactive prompting for missing secrets.
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:
$ 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)Resolution report (--json / --explain)
Section titled “Resolution report (--json / --explain)”--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:
$ secretspec check --profile production --explainprofile: productionprovider: 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.
$ 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.
secretspec get [OPTIONS] <NAME>Options:
-p, --provider <PROVIDER>- Provider backend to use-P, --profile <PROFILE>- Profile to use
Example:
$ secretspec get DATABASE_URL --profile productionpostgresql://prod.example.com/mydbschema
Section titled “schema”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.
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:
$ secretspec schema | quicktype -s schema --top-level SecretSpec --lang python -o secrets_gen.pyfrom secretspec import SecretSpecfrom 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 strThe 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.
secretspec set [OPTIONS] <NAME> [VALUE]Options:
-p, --provider <PROVIDER>- Provider backend to use-P, --profile <PROFILE>- Profile to use
Example:
$ secretspec set API_KEY sk-1234567890✓ Secret 'API_KEY' saved to keyring (profile: development)Run a command with secrets injected as environment variables.
secretspec run [OPTIONS] -- <COMMAND>Options:
-p, --provider <PROVIDER>- Provider backend to use-P, --profile <PROFILE>- Profile to use
Examples:
# Run npm with secrets available as environment variables$ secretspec run --profile production -- npm run deploy
# Verify secrets are injected$ secretspec run -- env | grep DATABASE_URLDATABASE_URL=postgresql://localhost/mydbimport
Section titled “import”Import secrets from one provider to another.
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:
# Import from environment variables to your default provider$ secretspec import envImporting 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/.envUse 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.
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:
$ secretspec audit --action run -n 52026-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")'Environment Variables
Section titled “Environment Variables”| Variable | Description |
|---|---|
SECRETSPEC_PROFILE | Default profile to use |
SECRETSPEC_PROVIDER | Default provider to use |
SECRETSPEC_FILE | Path to secretspec.toml (same as --file) |
SECRETSPEC_REASON | Reason for accessing secrets (same as --reason) |
Quick Start Workflow
Section titled “Quick Start Workflow”# 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