▸ Agent Skills
18 min read

CLI Commands Reference

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

Global Options

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
--caller <NAME>Software integration invoking SecretSpec; recorded separately from the user reason (0.20+)
--caller-version <VERSION>Version of --caller; requires --caller (0.20+)
--caller-operation <OPERATION>Integration operation; requires --caller (0.20+)
--caller-resource <RESOURCE>Non-secret resource being accessed; requires --caller (0.20+)
$ secretspec run --reason "Deploying web frontend" -- ./deploy.sh

Terminal window

SecretSpec 0.20+ lets a Git integration identify itself without replacing the user-supplied reason:

$ secretspec get GITHUB_TOKEN \    --caller git \    --caller-version 2.51.0 \    --caller-operation credential_get \    --caller-resource github.com \    --reason "push the release tag"

Terminal window

Caller context is caller-asserted audit metadata, not an authenticated identity, and never satisfies require_reason. Do not put credentials or secret values in these fields.

Commands

init

Initialize a new secretspec.toml from declarations discovered in a provider. Dotenv files are supported in every current release. SecretSpec 0.18+ accepts any provider that implements reflection, including age files, AWS Parameter Store, and Bitwarden Password Manager vaults.

$ secretspec init [--from <PROVIDER>] [--project <PROJECT>] [--profile <PROFILE>]

Terminal window

Options:

  • --from <PROVIDER> - Provider URI to discover (default: dotenv://.env); use a dotenv:// URI for dotenv files
  • --project <PROJECT> - Project used to render the provider namespace (SecretSpec 0.18+; default: current directory name)
  • -P, --profile <PROFILE> - Profile used to render the provider namespace and written to the manifest (SecretSpec 0.18+; default: default)

Reflection creates declarations only: values are never written to the manifest. Configure the discovered provider as the profile’s source to keep using it, or run secretspec import afterward to copy the declared values to a different destination.

Examples:

$ secretspec init --from dotenv://.env.example✓ Created secretspec.toml with 5 secrets
# SecretSpec 0.18+: discover one rendered Parameter Store hierarchy$ secretspec init \    --from 'awsps://us-east-1?template=/{profile}/{project}/{key}' \    --project payments \    --profile production✓ Created secretspec.toml with 12 secrets
# SecretSpec 0.18+: discover items in one Bitwarden collection$ secretspec init --from 'bw://dev-secrets?type=login'✓ Created secretspec.toml with 8 secrets

Terminal window

For Bitwarden in SecretSpec 0.20+, items under the selected secretspec/{project}/{profile}/ title prefix become convention declarations; bare existing items are emitted with explicit ref.item coordinates.

config global init

Initialize user-global configuration. The explicit global namespace is available in SecretSpec 0.17+; without options, the command prompts for the provider and profile.

$ secretspec config global init [--provider <PROVIDER>] [--profile <PROFILE>] # 0.17+

Terminal window

SecretSpec 0.17+ accepts --provider and --profile so installations can save both defaults without interaction. Each omitted option still prompts; use --profile none to clear the saved default profile. The corresponding SECRETSPEC_PROVIDER and SECRETSPEC_PROFILE environment variables are also accepted. Project requirements remain in secretspec.toml; the namespace makes it clear that this command writes user-wide defaults. The legacy secretspec config init spelling remains supported as a hidden alias.

Example:

$ secretspec config global init  # 0.17+? Select your preferred provider backend:> keyring: System keychain? Select your default profile:> development✓ Configuration saved to ~/.config/secretspec/config.toml

Terminal window

# SecretSpec 0.17+: save both defaults without prompting$ secretspec config global init --provider env --profile default✓ Configuration saved to ~/.config/secretspec/config.toml

Terminal window

config global show

Display current user-global configuration. The explicit namespace is available in SecretSpec 0.17+; secretspec config show remains a hidden alias.

$ secretspec config global show # 0.17+

Terminal window

Example:

$ secretspec config global show  # 0.17+Provider: keyringProfile:  development

Terminal window

config global 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 global provider add <ALIAS> <URI> [--credential NAME=PROVIDER]... # 0.17+

Terminal window

Arguments:

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

Options:

  • --credential <NAME=PROVIDER> - Declare a provider credential and its source. NAME is semantic and provider-specific, such as access_token or role_id. Repeatable. Only the bare-string source form is expressible on the command line; add a ref by editing the config.

Example:

$ secretspec config global provider add prod_vault "onepassword://Production" # 0.17+✓ Provider alias 'prod_vault' added: 'onepassword://Production'
$ secretspec config global provider add bws "bws://project-uuid" --credential access_token=keyring # 0.17+✓ Provider alias 'bws' added: 'bws://project-uuid'  credentials: access_token=keyring  run 'secretspec config provider login bws' to store the credentials

Terminal window

config global provider list

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

$ secretspec config global provider list # 0.17+

Terminal window

Example:

$ secretspec config global provider list  # 0.17+prod_vault  → onepassword://Productionshared      → onepassword://Sharedenv         → env://

Terminal window

config global 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 global provider remove <ALIAS> # 0.17+

Terminal window

Arguments:

  • <ALIAS> - Name of the alias to remove

Example:

$ secretspec config global provider remove prod_vault  # 0.17+✓ Provider alias 'prod_vault' removed

Terminal window

config provider login

Store the credentials a provider alias declares. Prompts (hidden input) for each credential and writes it to its source provider at the exact location resolution reads it back from. Runs in a project, like set and check.

$ secretspec config provider login <ALIAS>

Terminal window

Arguments:

  • <ALIAS> - Name of the alias whose credentials to store

Example:

$ secretspec config provider login bwsEnter access_token for provider 'bws' (source: keyring): ****✓ stored access_token in keyring at myproject/default/access_token
Run 'secretspec check --provider bws' to verify authentication.

Terminal window

A read-only source provider is rejected. An alias that declares no credentials reports that there is nothing to store.

docker configure

Configure Docker to retrieve credentials for one registry through SecretSpec.

$ secretspec docker configure --registry <REGISTRY> --username <USERNAME> [OPTIONS]

Terminal window

Options:

  • --registry <REGISTRY> - Registry hostname, optionally including a port; Docker Hub aliases are normalized to Docker’s canonical registry key
  • --username <USERNAME> - Non-secret registry username; required for the embedded store, or as an alternative to --username-secret with --file
  • --token-secret <KEY> - Custom manifest key containing the password or access token; requires --file
  • --username-secret <KEY> - Custom manifest key containing the username; requires --file and conflicts with --username
  • -P, --profile <PROFILE> - Custom manifest profile; requires --file
  • -p, --provider <PROVIDER> - Provider override the helper should use
  • -y, --yes - Confirm the Docker configuration change non-interactively

Without --file, the command configures the embedded registry-isolated store and prints the corresponding secretspec docker login command. With --file, --token-secret and either username option are required. The command adds a registry-specific credHelpers entry to Docker’s config.json, prompts with a default of No, and refuses to replace an existing helper.

docker login

Store a password or token in the embedded Docker credential store:

$ secretspec docker login <REGISTRY> [--provider <PROVIDER>]

Terminal window

The registry is normalized exactly as it is for configure. Each registry and physical Docker configuration pair uses a separate SecretSpec project identity. This command rejects --file; use secretspec set for custom-manifest credentials.

docker logout

Remove a password or token from the embedded Docker credential store:

$ secretspec docker logout <REGISTRY> [--provider <PROVIDER>]

Terminal window

Use the same provider override supplied to login. This does not remove the Docker helper registration; use unconfigure for that.

docker unconfigure

Remove one or all Docker credentials configured by SecretSpec in the active Docker configuration.

$ secretspec docker unconfigure --registry <REGISTRY>$ secretspec docker unconfigure --all

Terminal window

Use --yes to confirm the change non-interactively. --all removes only entries SecretSpec owns; it preserves the default credential store, other registry helpers, stored authentication entries, and unrelated Docker options. See Docker credentials for complete setup, custom manifest, and ownership details.

git configure

Configure Git to retrieve an HTTP(S) or SMTP password or token through SecretSpec. Repository-local configuration is the default.

$ secretspec git configure --url <URL> [OPTIONS]

Terminal window

Options:

  • --url <URL> - HTTP(S) or SMTP URL this credential may authenticate; an HTTP(S) path limits it to that part of the host, while SMTP requires an explicit port
  • --username <USERNAME> - Non-secret username to keep in the managed Git configuration; required for SMTP and must match sendemail.smtpUser
  • -p, --provider <PROVIDER> - Provider override the helper should use
  • --global - Configure the current user’s global Git settings instead
  • -y, --yes - Confirm a global change non-interactively; requires --global

Without --file, the command uses the embedded Git manifest with required PASSWORD and optional USERNAME declarations. It records no manifest path and isolates storage by the canonical protocol, host, and configured path.

With --file, --token-secret <KEY> is required; --username-secret <KEY> and -P, --profile <PROFILE> select custom manifest declarations and conflict with the embedded defaults. --username-secret conflicts with --username.

Global changes prompt with a default of No. Existing helpers and unrelated Git configuration are not replaced. See Git credentials for setup examples and the ownership model.

git login

Store an embedded Git password or token, prompting securely on a terminal or reading it from piped standard input.

$ secretspec git login <URL> [--username <USERNAME>] [--provider <PROVIDER>]

Terminal window

--username also stores the optional embedded username. The URL must match the one passed to configure, including a path scope. For SMTP, the username is read from managed Git configuration unless passed explicitly. git login rejects --file; use secretspec set for custom manifest declarations.

git logout

Remove the embedded username and password or token for one exact target without removing its Git helper configuration.

$ secretspec git logout <URL> [--username <USERNAME>] [--provider <PROVIDER>]

Terminal window

For SMTP, the username is read from managed Git configuration unless passed explicitly. git logout rejects --file; use secretspec delete for custom manifest declarations.

git unconfigure

Remove one or all Git credentials configured by SecretSpec in the selected scope.

$ secretspec git unconfigure --url <URL>$ secretspec git unconfigure --all$ secretspec git unconfigure --all --global

Terminal window

Use --global to select global configuration and --yes to confirm that global change non-interactively. --all removes only entries SecretSpec owns; it does not remove existing helpers, usernames, or unrelated includes.

check

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

$ secretspec check [OPTIONS]

Terminal window

Options:

  • -p, --provider <PROVIDER> - Provider backend to use
  • -P, --profile <PROFILE> - Profile to use
  • -S, --scope <SCOPE> - Resolve only a [scopes] subset of the profile (SecretSpec 0.17+)
  • -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)# SecretSpec 0.19+: the exact write destination is shown before prompting.Writing secret 'API_KEY' to keyring (profile: production)  target: item=secretspec/my-app/production/API_KEY[1/1] Enter value for API_KEY: ****✓ Secret 'API_KEY' saved to keyring (profile: production)

Terminal window

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 development --explainprofile:  developmentprovider: keyring://  DATABASE_URL        ok        source keyring://  DEV_SESSION_SECRET  ok        default value  JWT_SECRET          ok        will generate  SENTRY_DSN          missing   optional  STRIPE_KEY          MISSING   required

Terminal window

Both surfaces resolve without minting anything, so a generate secret that no provider holds yet reads as will generate rather than as an existing value.

Since SecretSpec 0.20, a required generate secret is reported as MISSING required while no provider holds it, and both surfaces exit non-zero. The value does not exist until a pass writes it, so a preflight that called it resolved would pass while the store is still empty. Run secretspec check (or secretspec run) once to mint and store it; afterwards the preflight reports it as resolved from its provider. will generate is reserved for the cases where nothing has to be provisioned: an optional generate secret, or a provider such as null that never retains a generated value and therefore mints a fresh one every resolution.

--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 }  ]}

Terminal window

get

Get a secret value.

$ secretspec get [OPTIONS] <NAME>

Terminal window

Options:

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

Example:

$ secretspec get DATABASE_URL --profile productionpostgresql://prod.example.com/mydb

Terminal window

For a composed secret, get resolves its transitive dependencies and prints the derived value. Available since SecretSpec 0.16.

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]

Terminal window

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.py

Terminal window

from 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 str

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

add

Add a secret declaration to an existing secretspec.toml. This edits only the selected profile and preserves the manifest’s comments, formatting, and unrelated tables. The new declaration follows the profile’s defaults; without a required profile default, it is required like any other declaration.

$ secretspec add <NAME> [--description <DESCRIPTION>] [--profile <PROFILE>] # 0.18+

Terminal window

Arguments and options:

  • <NAME> - Secret name. It must be a valid identifier: letters, numbers, and underscores, without a leading number.
  • -d, --description <DESCRIPTION> - Human-readable description. When omitted, SecretSpec prompts for it.
  • -P, --profile <PROFILE> - Profile to edit. When omitted, SecretSpec uses the normal active-profile resolution, including SECRETSPEC_PROFILE and the user-global default.
$ secretspec add API_KEY --description "API access token" # 0.18+✓ Added secret 'API_KEY' to profile 'development' in secretspec.tomlSet its value with: secretspec set API_KEY --profile development

Terminal window

add changes only the declaration; it never asks for or stores the secret value. Use secretspec set afterward to store the value. It rejects names that are already available in the selected profile, including declarations inherited from default or an extended manifest.

set

Set a secret value.

$ secretspec set [OPTIONS] <NAME> [VALUE]

Terminal window

Options:

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

Example:

$ secretspec set API_KEY sk-1234567890 --profile production --provider sops://secrets.enc.yaml# SecretSpec 0.19+:Writing secret 'API_KEY' to sops://secrets.enc.yaml?format=yaml (profile: production)  target: /work/my-app/secrets.enc.yaml ["my-app"]["production"]["API_KEY"]✓ Secret 'API_KEY' saved to sops (profile: production)

Terminal window

In SecretSpec 0.19+, set shows the resolved provider, profile, and native write target before reading a piped value or opening the password prompt. For SOPS this includes the exact encrypted file and sops set selector, making a missing --profile visible before the write.

set rejects composed secrets because their values are derived and read-only. Available since SecretSpec 0.16.

delete

Delete stored provider values without changing their declarations in secretspec.toml.

$ secretspec delete <NAME>... [--provider <PROVIDER>] [--profile <PROFILE>]
$ secretspec delete --all [--yes] [--provider <PROVIDER>] [--profile <PROFILE>]

Terminal window

Arguments and options:

  • <NAME>... - One or more declared secrets to delete.
  • --all - Delete every provider-backed secret declared in the active profile. It cannot be combined with a name.
  • -y, --yes - Skip the interactive confirmation for --all. Non-interactive use of --all requires this option.
  • -p, --provider <PROVIDER> - Delete from this provider instead of the manifest’s primary write provider.
  • -P, --profile <PROFILE> - Profile whose values are addressed.
# Delete one value from its primary write provider$ secretspec delete API_KEYDeleted 'API_KEY'Deleted 1 secret value; 0 already absent
# Delete selected values from an old dotenv provider$ secretspec delete API_KEY DATABASE_URL --provider dotenv://.env.old
# Explicitly delete every stored value in production$ secretspec delete --all --profile production --yes

Terminal window

Deletion is idempotent: an already-absent value is reported as such and does not fail the command. Without --provider, routing mirrors set: only the primary write provider is changed, never every provider in a fallback chain. Any cache entry declared for the secret is invalidated so it cannot continue to serve the deleted value.

The providers that support deletion in 0.18 are keyring, dotenv, pass, gopass, Vault, OpenBao, and Keeper Secrets Manager; age supports it starting with 0.20. Other providers return an explicit unsupported-operation error. Vault, OpenBao, and Keeper refuse to delete native ref entries because their backends would have to destroy a whole externally managed path or record rather than only the referenced field.

run

Run a command with secrets injected as environment variables.

$ secretspec run [OPTIONS] -- <COMMAND>

Terminal window

Options:

  • -p, --provider <PROVIDER> - Provider backend to use
  • -P, --profile <PROFILE> - Profile to use
  • -S, --scope <SCOPE> - Inject only a [scopes] subset of the profile (SecretSpec 0.17+)

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/mydb
# Inject only the `api` scope's secrets (SecretSpec 0.17+); secrets the# scope excludes are removed from the child even if the parent exported them$ secretspec run --scope api -- ./api-server

Terminal window

SecretSpec 0.19+ can securely request a declared missing value before the child starts. The selected provider normally saves the answer; choose null when it must be ephemeral:

[profiles.default]DEPLOY_PASSWORD = { description = "One-time deployment password", required = true, prompt = true, providers = ["null"] }

secretspec.toml

$ secretspec run -- ./deploy? Enter value for DEPLOY_PASSWORD (profile: default):

Terminal window

The hidden prompt reads from the controlling terminal, leaving the child’s stdin unchanged even when it is piped or redirected. The answer is injected only for that invocation when the provider is null; writable providers save it and make the prompt a first-use provisioning step. If no controlling terminal exists, run fails before starting the child. Only declarations with prompt = true opt into this behavior; ordinary missing secrets still fail without a prompt.

On Unix, SecretSpec 0.20+ forwards SIGTERM, SIGINT, and SIGHUP to the started command. This lets applications run their graceful-shutdown handlers when secretspec run is a container entrypoint, including when SecretSpec is PID 1. If the command is terminated by a signal, run exits with the conventional 128 + signal status (for example, 143 for SIGTERM).

The --provider override applies to every secret, including those with a ref field: refs are redirected to the overriding provider just like convention secrets. This makes it easy to point refs at fixtures during tests without editing the manifest:

# Resolve every secret, refs included, from a fixtures file$ secretspec run --provider dotenv:.env.fixtures -- cargo test

Terminal window

export

Resolve every secret for the active profile and write it to stdout in a chosen format, without running a command. Unlike run, it never prompts and exits non-zero when a required secret is missing, so CI can gate on it.

$ secretspec export [OPTIONS]

Terminal window

Options are -p, --provider <PROVIDER>, -P, --profile <PROFILE>, -S, --scope <SCOPE> (a [scopes] subset of the profile, SecretSpec 0.17+), and --format <FORMAT> (default shell).

Unlike run --scope, export --scope only emits the scoped subset; it unsets nothing, because no output format can express an unset. A shell that already holds a wider set keeps those values after a scoped export, so use run --scope when the point is to narrow an existing environment.

FormatOutput
shellexport KEY='value' lines, ready for eval "$(secretspec export)"
dotenvKEY=value lines in dotenv syntax. In 0.20+, values are unquoted when they already round-trip and otherwise double-quoted and escaped; $ remains literal.
jsona single compact JSON object mapping each secret name to its value
ghaappends KEY=value to the file named by $GITHUB_ENV and prints an ::add-mask:: command per value to stdout, so later workflow steps and third-party actions see the secrets
# Load secrets into the current shell$ eval "$(secretspec export --profile production)"
# Emit JSON for another tool to consume$ secretspec export --profile production --format json{"DATABASE_URL":"postgresql://prod.example.com/mydb"}

Terminal window

The gha format targets a secretspec export --format gha step in a GitHub or Forgejo Actions job: it masks the values in the runner log and persists them to the job environment for the steps that follow.

import

Import secrets from one provider to another.

$ secretspec import <FROM_PROVIDER> [--delete-source]

Terminal window

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

In SecretSpec 0.19+, the source and destination resolve their addresses independently. A source alias can use its own provider ref template or per-secret scoped ref, while the destination uses its selected alias’s mapping.

Also in SecretSpec 0.19+, a literal source remains convention-addressed, but import warns when it shares a storage container with a defined alias whose template or active scoped refs resolve any imported secret to a different entry. The warning is informational: keep the literal to migrate convention-named entries, or select the alias when its alias-specific coordinates describe the intended source. Import output retains the selected alias name alongside its resolved, credential-free provider URI.

Arguments:

  • <FROM_PROVIDER> - Provider to import from (e.g., env, dotenv:/path/to/.env)
  • --delete-source - After copying, delete a source value only when the destination is verified to contain the same value. Available in SecretSpec 0.18+.

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/.env
# Move values out of an old provider (SecretSpec 0.18+)$ secretspec import dotenv:/home/user/old-project/.env --delete-source

Terminal window

Use Cases:

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

import skips composed secrets because they have no stored value to copy; their component secrets are imported normally. Available since SecretSpec 0.16.

With --delete-source, source and destination must resolve to different physical entries. In SecretSpec 0.19+, distinct scoped refs in the same store are allowed. SecretSpec preflights every source and destination, performs all writes, reads back and validates every copied value, and only then begins source cleanup. If a destination already contains an identical value, the source is also safe to delete; if it differs, SecretSpec retains the source and reports the conflict. A source provider that does not support deletion fails explicitly instead of pretending the migration completed. Source deletion was introduced in SecretSpec 0.18; independent endpoint refs and operation-wide preflight are available in 0.19+.

cache clear

Delete cached provider values for one secret, or for every cached secret in the active profile. Authoritative fallback providers are not modified.

$ secretspec cache clear [NAME] [--profile <PROFILE>]

Terminal window

Arguments and options:

  • [NAME] - Cached secret to clear. Omit it to clear all cached secrets in the profile.
  • -P, --profile <PROFILE> - Profile whose logical cache entries are cleared.

The reported count is the number of entries that were actually removed, so a profile with nothing cached reports Cleared 0 cache entries. --provider and SECRETSPEC_PROVIDER are ignored: clearing always addresses the cache of the route the manifest declares. When one cache store cannot be cleared, the remaining secrets are still cleared and the command then reports what failed.

# Force the next API_KEY read through its authoritative fallback route$ secretspec cache clear API_KEYCleared 1 cache entry
# Clear every cached secret in production$ secretspec cache clear --profile productionCleared 4 cache entries

Terminal window

See Provider caching for configuration and resolution behavior.

audit

Show the local audit log of secret access.

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

Terminal window

Options:

  • --project <NAME> - Only show entries for this project
  • --action <ACTION> - Only show entries for this action (get, set, check, run, import, export, cache_clear and cache_refresh in 0.17+, or delete in 0.18+)
  • -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 get -n 52026-06-04T18:06:29Z  get    found  GITHUB_TOKEN  (my-app/production)  reason: push release tag  caller: [email protected]/credential_get github.com
# Pipe raw entries to jq$ secretspec audit --json | jq 'select(.outcome == "missing")'

Terminal window

completions

Generate a completion script that asks the same command definition used by secretspec --help for suggestions. Completion results include every command, option, possible value, and description supported by the target shell. They also provide contextual suggestions for profile, scope, secret, provider, and provider-alias names. File arguments complete paths, while secretspec run completes executables and command-argument paths.

When you press Tab, the completion script invokes secretspec to calculate the current suggestions. SecretSpec reads the nearest secretspec.toml (or the manifest selected by --file or SECRETSPEC_FILE) and user configuration to discover names and descriptions. It does not contact providers or read secret values.

$ secretspec completions <SHELL>

Terminal window

Supported shells are bash, elvish, fish, nushell, powershell, and zsh. Load completions for the current session with the command for your shell:

  • Bash: source <(secretspec completions bash)
  • Elvish: eval (secretspec completions elvish | slurp)
  • Fish: secretspec completions fish | source
  • PowerShell: secretspec completions powershell | Out-String | Invoke-Expression
  • Zsh: autoload -U compinit && compinit && source <(secretspec completions zsh)

For persistent Bash, Elvish, Fish, PowerShell, or Zsh completions, put the corresponding command in your shell’s startup file. Generating the script at startup keeps it synchronized after a SecretSpec upgrade.

Nushell loads completion modules from a file:

secretspec completions nushell | save -f ~/.config/nushell/completions-secretspec.nuuse ~/.config/nushell/completions-secretspec.nu *

Terminal window

Regenerate that file after upgrading SecretSpec.

Environment Variables

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)

Quick Start Workflow

# Initialize from existing .env$ secretspec init --from .env
# Set up user-global defaults (0.17+)$ secretspec config global 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

Terminal window


Last updated Oct 08, 2026