scrt4 — secret manager for coding agents
Claude Code can use your secrets without ever seeing them. The AI writes commands with $env[NAME] placeholders; the real values are substituted at runtime inside an isolated subprocess and scrubbed from stdout before anything returns to the model.
scrt4 is a single daemon + CLI that holds your .env values in a hardware-bound encrypted vault. The master key is derived from your FIDO2 authenticator (YubiKey, passkey, phone, Touch ID, Windows Hello) via the WebAuthn PRF extension — no passwords, no TOTP. The key is re-derived every session and never leaves the device.
Runs the same way on macOS, Linux, and WSL. AGPL-3.0. Under 10 MB end-to-end.
Install
One command. Auto-detects OS and architecture, pulls SHA256-verified binaries from GitHub Releases, and installs a systemd user unit (Linux) or launchd plist (macOS). No Docker required.
Full per-OS instructions, checksums, and a two-hosts-one-hash verify step live at llmsecrets.com/downloads. The same scrt4-native.sh.sha256 is served from install.llmsecrets.com/native.sha256 and committed to the public repo on main. Both must match.
Supported authenticators
| Authenticator | Status |
|---|---|
| YubiKey 5 series (firmware 5.2.3+) | ✅ Supported |
| YubiKey 4 / NEO | ❌ Does not support hmac-secret |
| Trezor Safe 3 / Safe 5 / Model T (recent firmware) | ✅ Supported |
| OnlyKey | ✅ Supported |
| Phone passkeys via caBLE (iPhone, Android) | ✅ Supported |
| Apple passkeys, Bitwarden, 1Password, Google Password Manager | ✅ Any PRF-capable software authenticator |
| Touch ID / Windows Hello | ✅ Supported |
First unlock
scrt4 setup
One-time FIDO2 enrollment. Registers a WebAuthn passkey tied to your hardware authenticator. This is the hardware root of trust — don't skip it.
scrt4 unlock
Opens a session. Default TTL is 20 hours; pass a different value like scrt4 unlock 3600 for a one-hour window. Every command below requires an active session.
scrt4 status
Confirms the session is live. Shows time remaining, vault location, and loaded modules.
Losing the hardware authenticator without a backup = losing the vault. Jump to Encrypted Drive backup or Recovery before you store anything important.
Your first secret
Two ways to add secrets: type them one by one, or import an existing .env file.
scrt4 list only ever shows secret names. Values are never printed on stdout — the only way to see a value is scrt4 view, which opens a GUI dialog so values render in the OS window system where a CLI agent cannot read them.
Using with Claude Code
Write commands with $env[NAME] placeholders. scrt4 substitutes the real values at runtime inside the subprocess environment. The substituted text is never returned to the model.
The placeholder is literally $env[NAME]. Not $NAME, not ${NAME}. Only $env[NAME] triggers injection.
Example: deploy a smart contract
Example: call an API
Example: push to GitHub
Discovering what's available
scrt4 llm emits an llms.txt-style dump of every secret name in the vault, every loaded module with its capabilities, current session status, and recommended next steps. Prefer this over stale docs — it reflects the live vault.
Importing existing .env files
If you already have project .env files on disk, their secrets belong in scrt4, not in plaintext. The import module parses export KEY=value forms, surrounding quotes, and # comments.
After import, delete the plaintext file — some tooling still reads .env directly, so confirm your app uses the new injection flow before removing it. A Claude Code session with scrt4 unlocked can help find .env files under your project directories with find ~/projects -name '.env' 2>/dev/null and walk through them one at a time.
Encrypted Google Drive backup (cloud-crypt)
No authenticator + no backup = no recovery, by design. There is no server-side reset because there is no server-side anything. The recommended backup path is client-side encrypted upload to your own Google Drive: AES-256-GCM runs locally before upload, so Drive only ever receives .scrt4 ciphertext. Google cannot decrypt it.
The cloud-crypt module ships with the native installer by default. Setup has three steps: Drive-scoped OAuth, save the master key, push the vault.
1. Give cloud-crypt Drive access
Three setup paths — pick whichever matches what you already have:
scrt4 cloud-crypt auth setup --from-gws
Runs the Google Workspace CLI (gws) consent flow. Easiest if you don't already have an OAuth blob.
scrt4 cloud-crypt auth setup --from-secret personal_google_workspace
Reuses an OAuth blob already in the vault. Nothing is copied — cloud-crypt reads it through the daemon.
scrt4 cloud-crypt auth setup --paste
Interactive paste of an existing OAuth blob. For users who manage their own Google OAuth.
2. Save your master key somewhere durable
The Drive ciphertext is useless without the master key. Save it password-protected to a USB stick, a password manager, or both.
Move the exported backup file to a location you actually trust — a hardware key, a USB stick, or your password manager's attachment slot. Desktop = convenient for you = convenient for anything else that can read your disk.
3. Push the encrypted vault to Drive
Everything encrypted by cloud-crypt lives in a single Drive folder named claude-crypt, auto-created on first push. You can rename or move the folder later — the module tracks archives by ID, not path. Filenames and sizes are not encrypted.
4. Restore on a new machine
- Install scrt4 on the new machine (
curl -fsSL https://install.llmsecrets.com/native | sh). - Run
scrt4 setupto enroll a new authenticator. - Unlock, then run
scrt4 recover /path/to/backup-file.enc— this restores the original master key from the password-protected export you saved in step 2. - Authenticate cloud-crypt (
scrt4 cloud-crypt auth setup ...) andscrt4 cloud-crypt pull-and-decrypt <driveId>to pull the encrypted vault back down and decrypt it.
list, where, status, push, pull, encrypt-and-push, pull-and-decrypt, auth setup/status/guide, ui — run scrt4 cloud-crypt help for the full surface area. Every read command supports --json for script consumption.
Encrypt a folder
The encrypt-folder module produces a standalone .scrt4 archive using the same vault key. Useful for backing up source trees, ops notebooks, or anything else you'd rather not leave in plaintext.
Pair with cloud-crypt push ~/notes.scrt4 to ship the archive to Drive without a second round of encryption — the archive is already ciphertext.
Recovery
Three recovery paths, in order of preference:
| Path | What you need | What it restores |
|---|---|---|
| Drive backup | Password-protected master-key file + Drive access | Full vault |
| Local backup | Copy of ~/.scrt4/vault.enc + master key |
Full vault |
| Emergency key | Raw base64 master key (scrt4 recover-key) |
Full vault — bypasses FIDO2, use only if hardware is gone |
scrt4 has no server-side state — no account, no password reset, no customer-success ticket that can rescue a lost vault. If both the authenticator and the backup are gone, the vault is permanently unrecoverable. This is the security model, not a bug.
How the key works
Your vault key is derived from the FIDO2 authenticator via the WebAuthn PRF extension — CTAP2's hmac-secret under the hood. Each scrt4 unlock triggers a tap/touch/biometric check on the authenticator, which returns a device-bound HMAC. scrt4 uses that HMAC as input to the vault KDF. The key is re-derived every session and never leaves the device.
This is why scrt4 doesn't need a password, doesn't need TOTP, and doesn't need cloud state: the hardware authenticator IS the key. Steal the vault file alone and you have nothing; steal the authenticator alone and you have nothing. You need both.
Vault encryption
- AES-256-GCM authenticated encryption at rest (
~/.scrt4/vault.enc). - Decrypted only in daemon memory during an active session; never written unencrypted.
- The daemon scrubs every stored value from subprocess stdout before returning it to the calling agent.
scrt4 viewopens a Zenity GUI dialog — values render in the OS window system where a CLI agent cannot read them.
Daemon & TCB split
scrt4 is split into a small trusted computing base (TCB) and a larger set of modules:
- Daemon (Rust, <2k LoC) — crypto, vault handling, session state, and subprocess injection. Values never leave daemon memory.
- Core CLI (bash, ~2,800 LoC) — command dispatch, UX, module loader.
- Modules — extend functionality (
cloud-crypt,encrypt-folder,import-env,github, etc.) without expanding the TCB. Modules see ciphertext and metadata only; encrypt/decrypt stays in the daemon.
See ARCHITECTURE.md for the full module/TCB split and SECURITY.md for the threat model.
What the AI sees (and doesn't)
| Claude CAN see | Claude CANNOT see |
|---|---|
Secret names (GITHUB_PAT, STRIPE_SECRET_KEY, ...) | Secret values — ever |
| Command structure and exit codes | Private keys, passwords, tokens |
stdout from scrt4 run (with stored values redacted) | The master key |
| Session status, vault metadata, loaded modules | Anything shown in scrt4 view (GUI-only) |
Commands reference
scrt4 setupOne-time FIDO2 enrollmentscrt4 unlock [ttl]Start a session (default 20 h)scrt4 statusSession info, TTL remainingscrt4 extend [ttl]Reset the session timerscrt4 logoutLock the sessionscrt4 list [--tags]List secret namesscrt4 add K=vAdd secretsscrt4 import FILEImport an existing .envscrt4 view [--cli]View/edit in GUI (or terminal)scrt4 run 'cmd $env[K]'Run with secret injectionscrt4 rotateRotate the vault master keyscrt4 backup-vaultTar the vault directoryscrt4 backup-key --save DIRExport password-protected master keyscrt4 recover FILERestore from an encrypted backupscrt4 recover-key KEYEmergency restore from raw keyscrt4 share [--all] [NAME...]Share secrets via Magic Wormholescrt4 receive [--code CODE]Receive shared secretsscrt4 verify-selfCheck binary against published SHA256SUMSscrt4 llm [--json]Emit capability dump for AI agentsscrt4 helpFull command referenceRun scrt4 help locally for the canonical list — this page drifts, the binary doesn't.
Modules
Modules extend scrt4 without expanding the trusted computing base. The native installer ships three by default; the rest are explicit opt-in via --module NAME.
| Module | Default? | What it does |
|---|---|---|
cloud-crypt | ✅ | Client-side encrypted Google Drive backup. AES-256-GCM runs locally before upload. |
encrypt-folder | ✅ | Encrypt any directory to a standalone .scrt4 archive using the vault key. |
import-env | ✅ | Parse an existing .env (including export K=v, quoted values, # comments) into the vault. |
github, gcp, stripe, dns, ... | Opt-in | Whitelisted in modules-whitelist.json and SHA256-verified at install time. |
Run scrt4 modules list to see what's loaded in your install.
Trust & verification
- Downloads page — llmsecrets.com/downloads lists every release with per-platform install commands and published SHA256 checksums.
- Two-hosts, one-hash — the same
scrt4-native.sh.sha256is served frominstall.llmsecrets.com/native.sha256and committed atscrt4/install/scrt4-native.sh.sha256on the public repo'smainbranch. Both must match before piping tosh; tampering either source alone fails the check. - Release manifest —
install.llmsecrets.com/releases/latest.txtpoints to the current tag; each tag directory has aSHA256SUMSover every daemon binary and the bash CLI. - Self-verification —
scrt4 verify-selfchecks its own bytes against the published manifest. - Reproducible layout — source + bash modules + install scripts + docs is about 1.5 MB. "Under 10 MB" is the conservative public claim; the core bash (~2,800 lines) and daemon (Rust, <2k LoC) are small enough to read line by line.
Don't want to read 2,000 lines of Rust yourself? DeepWiki indexes the public repo and answers questions like "Does the daemon ever write secret values to disk?" or "How is the master key derived?" against the actual source.
Uninstall
Removes the daemon, CLI, and session data. The encrypted vault at ~/.scrt4/ stays on disk until you delete it — that's deliberate, so a reinstall can pick up where the old one left off.
Troubleshooting
"Secret not found"
The name may differ from what the command expects. Run scrt4 list to see exactly what's stored.
"Session locked"
Run scrt4 unlock. Check scrt4 status for TTL. Sessions can be extended with scrt4 extend.
"hmac-secret not supported"
Your authenticator doesn't support the WebAuthn PRF extension. YubiKey 4 and NEO are the common culprits — YubiKey 5 firmware 5.2.3+ is required. Check firmware with ykman info.
cloud-crypt: gcloud not found
cloud-crypt uses the Google Cloud SDK to mint OAuth tokens. Install it from cloud.google.com/sdk or use auth setup --from-secret / --paste to bring your own OAuth blob.
Need a new secret?
scrt4 add NAME=value or scrt4 import FILE. Both work mid-session.
Still stuck?
File an issue at llmsecrets/llm-secrets, or email security@llmsecrets.com for anything sensitive.
The Windows-Hello CLI, Electron desktop app, and WSL2 alpha guides live on the archive page. New installs should use scrt4.