CLI Reference: Secrets

Commands for managing the Sealed Credential Store.

Secrets are sensitive values (API keys, tokens, passwords) encrypted with AES-256-GCM and stored in a SQLite database. At runtime, decrypted values live exclusively in agentd's heap memory as Zeroizing<String>; they are never included in IPC responses, never written to observation logs, and never appear in audit entries (only [REDACTED:<name>] placeholders are recorded).

See Secrets Overview for background on the full architecture.


ash secrets unlock

Unlock the encrypted store. On first run (no KDF params exist yet), this initialises the store with the supplied passphrase. On subsequent runs, it derives the master key from the stored salt, decrypts all blobs, and loads them into the runtime store.

ash secrets unlock

The passphrase is read via an echo-disabled prompt.

First run:

Enter master passphrase: [hidden]
Secret store initialised and unlocked.

Subsequent starts:

Enter master passphrase: [hidden]
Secret store unlocked. 3 secret(s) loaded.

Until unlock succeeds, all {{secret:<name>}} handle substitutions return StoreLocked.


ash secrets lock

Immediately zeroize all in-memory plaintext. Subsequent secret resolutions return StoreLocked until ash secrets unlock is called again.

ash secrets lock

The encrypted database is not modified. Use this before stepping away from a running daemon or handing off a session.


ash secrets rekey

Rotate the master key. All encrypted blobs are re-encrypted in a single atomic SQLite transaction. The old passphrase is verified before any changes are made.

ash secrets rekey

Prompts (all echo-disabled):

Enter current passphrase: [hidden]
Enter new passphrase:     [hidden]
Confirm new passphrase:   [hidden]
Master key rotated. All secrets re-encrypted.

The daemon remains fully operational throughout. After rekey completes, the in-memory store is refreshed under the new key.


ash secrets add

Register a new secret in agentd's sealed store.

ash secrets add <name> [--description <text>]
Argument/FlagDescription
nameLogical name used in {{secret:<name>}} handles
--descriptionOptional human-readable description

The secret value is read via an echo-disabled (hidden) prompt. If the store is currently unlocked, the value is also encrypted and persisted to SQLite immediately.

Example:

ash secrets add openai-api-key --description "OpenAI production API key"
# Prompts: Enter secret value: [hidden]

ash secrets list

List all registered secret names. Values are never shown.

ash secrets list

Output: name, description (if set), and registered-at timestamp.

NAME            DESCRIPTION                    REGISTERED AT
openai-api-key  OpenAI production API key      2026-01-15T10:00:00Z
db-password     Production database password   2026-01-10T08:00:00Z

ash secrets remove

Remove a registered secret.

ash secrets remove <name>

The plaintext is zeroized from heap memory and the encrypted blob is deleted from the SQLite store. Any agent that subsequently tries to resolve {{secret:<name>}} will receive a SecretNotFound error.


ash secrets grant

Grant a specific agent delegation access to a named secret. The agent will be able to use the secret in tool calls even if it does not have a standing secret.use:<name> capability, subject to existing pre-approval policies.

ash secrets grant <name> --to-agent <agent-id> [--ttl <seconds>]
Argument/FlagDescription
nameName of the secret to delegate
--to-agentUUID of the agent receiving the grant
--ttlOptional TTL in seconds. If omitted, the grant is valid until explicitly revoked or the daemon restarts.

Example:

ash secrets grant openai-api-key --to-agent f47ac10b-58cc-4372-a567-0e02b2c3d479 --ttl 3600
# Grant ID: 9b1deb4d-...
# Secret 'openai-api-key' delegated to agent f47ac10b-... (expires in 3600s)

Grants are ephemeral: they live only in daemon memory and do not survive a restart. Re-grant after ash secrets unlock if needed.


ash secrets revoke

Revoke a previously issued delegation grant.

ash secrets revoke <grant-id>

The grant is removed immediately. The target agent can no longer use the delegated secret.

Example:

ash secrets revoke 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d
# Grant 9b1deb4d-... revoked.

ash secrets policy add

Add a runtime pre-approval policy for automated secret resolution.

ash secrets policy add \
  --label <text> \
  [--secret <glob>] \
  [--tool <glob>] \
  [--host <glob>] \
  [--expires <rfc3339>] \
  [--max-uses <n>] \
  [--trust-level <level>]
FlagDefaultDescription
--label-Human-readable name for this policy (required)
--secret*Glob matching secret names
--tool*Glob matching tool names
--host(any)Optional glob matching destination host
--expires(never)RFC3339 expiry timestamp
--max-uses(unlimited)Maximum auto-approvals before policy is exhausted
--trust-level(any)Minimum trust level floor (untrusted/sandboxed/trusted/privileged)

Policies are persisted to SQLite and survive daemon restarts.

Examples:

# Unlimited access for any agent using openai-key via web.fetch to api.openai.com
ash secrets policy add \
  --label "OpenAI standard access" \
  --secret "openai-api-key" \
  --tool "web.fetch" \
  --host "api.openai.com"

# Time-limited policy expiring at end of day
ash secrets policy add \
  --label "Nightly batch" \
  --secret "db-password" \
  --tool "sandbox.exec" \
  --expires "2026-01-16T06:00:00Z"

ash secrets policy list

List all registered pre-approval policies.

ash secrets policy list

Output: policy ID, label, secret pattern, tool pattern, host pattern, expiry, use count.


ash secrets policy show

Print full details for a single policy, including the current use count.

ash secrets policy show <policy-id>

Example:

ash secrets policy show a1b2c3d4-e5f6-7890-abcd-ef1234567890
# ID:          a1b2c3d4-e5f6-7890-abcd-ef1234567890
# Label:       OpenAI standard access
# Secret:      openai-api-key
# Tool:        web.fetch
# Host:        api.openai.com
# Expires:     never
# Max uses:    unlimited
# Use count:   42
# Created by:  operator
# Created at:  2026-01-15T10:00:00Z

ash secrets policy remove

Remove a pre-approval policy by UUID.

ash secrets policy remove <policy-id>

Immediately revokes the policy. Subsequent secret resolutions that would have matched this policy are denied.