This guide covers the clictl vault and the vault:// protocol for managing secrets safely across tool workflows.
Most developer workflows store API keys and tokens in one of these places:
.envfiles that risk being committed to git- Environment variables visible in
ps aux,/proc/PID/environ, and CI logs - Shell history (
export STRIPE_KEY=sk_live_...) - Plaintext config files
Any of these can leak secrets to teammates, CI systems, log aggregators, or attackers who gain read access to the filesystem.
The vault:// protocol replaces plaintext secrets with encrypted references. Instead of storing the actual value, you store a pointer:
# Before (insecure):
STRIPE_API_KEY=sk_live_abc123
# After (secure):
STRIPE_API_KEY=vault://STRIPE_API_KEYWhen clictl executes a tool, it sees the vault:// prefix, decrypts the real value from the vault, and passes it to the tool. The actual secret exists only in memory during execution.
clictl vault set STRIPE_API_KEY sk_live_abc123
clictl vault set GITHUB_TOKEN ghp_def456After running vault set, clictl:
- Encrypts the value and stores it in
~/.clictl/vault.enc - If a
.envfile exists in the current directory with a matching key, updates its value tovault://STRIPE_API_KEY - If no
.enventry exists, prints thevault://reference for you to add manually
The vault file is encrypted and protected with 0600 permissions (owner read/write only).
If you already have a .env file with plaintext secrets:
clictl vault import .envThis reads every key-value pair, stores the values in the vault, and replaces the plaintext values in the file with vault:// references. Comments and blank lines are preserved.
To skip non-secret values:
clictl vault import .env --exclude NODE_ENV,DEBUG,PORTValues that are already vault:// references are skipped automatically.
By default, secrets go to the user vault at ~/.clictl/vault.enc. For secrets specific to a single project, use the --project flag:
clictl vault set DATABASE_URL postgres://user:pass@host/db --projectThis stores the secret in .clictl/vault.enc relative to the current git root. The CLI auto-adds this path to .gitignore.
Resolution order (first match wins):
- Project vault (
.clictl/vault.encin the current git root) - User vault (
~/.clictl/vault.enc) - Workspace vault (enterprise, via API with caching)
- Raw environment variable value
This means you can have project-specific overrides that take precedence over your global secrets.
Enterprise workspaces can manage secrets centrally. Admins set secrets via the web UI or API, and team members' CLIs resolve them automatically.
Admin sets a shared secret:
In the web UI, go to Settings > Secrets and click "Add Secret". Provide the name, value, and cache TTL.
Developer uses the secret:
Add a vault:// reference to your .env:
STRIPE_KEY=vault://STRIPE_KEY
The CLI resolves workspace secrets with server-driven caching:
- First resolve: the CLI fetches the secret from the API, caches it locally (encrypted), and respects the
Cache-Controlheader for freshness - Within the cache window: the CLI reads from the local cache with no API call
- After cache expiry: the CLI revalidates with an
ETag. If the secret has not changed, the server responds with 304 (no payload) and the cache is extended
Admins control the cache TTL per secret. Shorter TTLs mean faster rotation propagation but more API calls.
# List secret names and timestamps (never shows values)
clictl vault list
# Retrieve a value (requires confirmation prompt)
clictl vault get STRIPE_API_KEY
# Delete a secret
clictl vault delete STRIPE_API_KEY
# Update a secret (same as set - overwrites the existing value)
clictl vault set STRIPE_API_KEY sk_live_newkey789
# Export all secrets as plaintext (for CI migration, requires --confirm)
clictl vault export --format env --confirmThe vault key is generated automatically during clictl install (self-install). No extra setup is needed.
Reset the vault (destroys all existing secrets):
clictl vault init --forceUse a password-based key (for portability across machines):
clictl vault init --passwordThis derives the encryption key from a password you enter instead of random bytes. The password is never stored. You enter it once per session on first vault access. This lets you use the same vault file across multiple machines.
| Attack | Without vault:// | With vault:// |
|---|---|---|
.env committed to git |
Secrets leaked in repository | Only vault:// references leaked |
ps aux or process listing |
Secrets visible in environment | Only references visible |
| CI/CD log leak (env dump) | Secrets appear in logs | Only references in logs |
| Shoulder surfing terminal | export KEY=secret visible |
export KEY=vault://KEY visible |
| Malicious tool reads env | Gets actual secrets | Gets vault:// reference (useless without vault file) |
| Stolen laptop (disk access) | .env files are readable |
Vault file is encrypted, requires key or password |
| MCP server prompt injection | Tool dumps env vars with real values | Env vars only contain references |
- Memory dump during tool execution. The secret is in memory briefly while the tool runs.
- Compromised CLI binary. If an attacker modifies the clictl binary, they can intercept secrets during resolution.
- Stolen vault file and vault key together. Both are needed to decrypt, but if an attacker has both, secrets are exposed.
- Root access on the user's machine. A root-level attacker can read anything in memory or on disk.
The vault is not a replacement for infrastructure-level secret management in production environments. It is designed to protect developer workstations and CI pipelines from common secret exposure patterns.
See also: Security Model | CLI Reference | Spec Format