Open source · Keys stay on your devices
Hort – secrets for you and your agents.
One encrypted vault for your API keys, tokens and passwords. You use it. Your coding agents use it. Your keys never leave your devices.
The CLI works today. Sync, passkeys and the web app arrive with Hort 1.0. No account needed to start.
$ hort --list openai-key OpenAI API key [env: *] db-password PostgreSQL password [env: *, prod] $ hort --secret db-password --env prod ••••••••••••
// agents
Your agent asks. You answer. It never sees the secret.
Agents need credentials. Today you paste them into the chat, the agent forgets, and next session it asks again. Hort gives your agents one place to look, and one polite way to ask for what's missing.
Discover
The agent runs hort --list and sees what exists: names, descriptions, environments. No values.
Read
hort --secret <name> prints just the value on stdout. Ready for $(...) and pipes. Locked vault? Exit code 2, and the agent asks you to unlock.
Ask for what's missingComing with 1.0
The agent requests a secret by name via MCP. You get a link, open hort.pm and type the value there. The agent only learns that the secret now exists.
Today
# What's there? $ hort --list --json # Use it $ export STRIPE_KEY=$(hort --secret stripe-key --env prod) # Different value per customer $ hort --secret tenant-id --env prod --context acme
Fallback built in: env+context → env+* → *+*. Specific wins, the baseline catches the rest.
Coming with 1.0
agent › I need the Stripe client ID for this integration. hort › Requested "stripe / client_id". Waiting for you on hort.pm … you › (open the link, enter the value, done) agent › $ hort get stripe client_id
The value goes from your browser into your vault. The chat only ever sees the name.
Using Claude Code? The hort-secrets plugin already lets an agent ask for a secret without seeing it: you type the value into a field above the prompt, Hort stores it, the chat gets the name.
// features
Small tool. Sharp edges where they belong.
Available today
- One encrypted vault.AES-256-GCM, key derived with Argon2id. One file on your disk.
- Built for agents.
hort --helpteaches an agent the whole interface in one call. Plain values on stdout, errors on stderr,--jsonwhen it wants structure. - Environments and contexts.One name, many values: dev, prod, per tenant or customer. Lookups fall back to the baseline.
- History.Every change is a revision.
hort history <name>shows what changed and when. - Offline first.No network calls, no telemetry. Hort works on a plane.
- Device sync through a folder.Point Hort at a folder that iCloud Drive or another sync service already replicates. Hort writes encrypted copies only.
- Values stay out of your shell history.
--value-stdinkeeps secrets out of process arguments.
Coming with 1.0
- Secret Key + passphrase.Coming with 1.0Unlock with your passphrase plus a device-generated Secret Key. A stolen copy of your vault is useless without both.
- Passkey unlock in the browser.Coming with 1.0Unlock hort.pm with a passkey (WebAuthn PRF). No passphrase typing on every visit.
- Named fields.Coming with 1.0One secret, several parts:
hort get stripe client_id,hort get stripe secret. - Encrypted sync, hosted in the EU.Coming with 1.0Sync runs on Cloudflare in the EU. The server stores ciphertext and never sees a key.
- hort.pm web app.Coming with 1.0Read, copy and set secrets in the browser, on any device you trust.
- Agents ask, you answer.Coming with 1.0Agents request missing secrets via MCP. You enter them on hort.pm; the agent gets the name, not the value.
// security
Where your secrets live, honestly.
A secret manager earns trust by saying what it protects and what it doesn't. Here's ours.
What Hort protects
- Keys and plaintext exist only on your devices, and in your browser while hort.pm is unlocked.Browser part: 1.0
- The vault is encrypted with AES-256-GCM. Tampering is detected.
- The sync server stores ciphertext only. It cannot read your secrets.Coming with 1.0
- Agents get values through the CLI on your machine. With the 1.0 request flow, they never get values you type for them.Coming with 1.0
What Hort does not protect against
- Someone who controls your machine. Root or malware on an unlocked device can read what you can read. That's true for every local secret manager.
- Whoever controls the hort.pm deployment.Coming with 1.0 The web app is JavaScript served by hort.pm. Whoever controls that deployment could ship code that reads secrets after you unlock in the browser. We reduce the risk: strict Content Security Policy, no third-party scripts, open source code you can check. If you don't want this risk at all, use only the CLI. Or run the backend yourself.
- Losing both Secret Key and passphrase.Coming with 1.0 Then your data is gone. Nobody can reset it, including us. Print your Emergency Kit and keep it somewhere safe.
Today, specifically: The CLI never talks to a server. Folder sync puts encrypted vault copies in your sync folder; anyone who can read that folder can try to guess your passphrase offline. Use a long, random one.
// install
Install in one line.
macOS (Homebrew)
brew install sebastian-breitzke/tap/hort && hort init
npm (any OS)
npm install -g @s16e/hort && hort init
Windows (Scoop)
scoop bucket add sebastian-breitzke https://github.com/sebastian-breitzke/scoop-bucket scoop install hort hort init
Linux and Windows binaries
After install
hort --set-secret openai-key --value-stdin --description "OpenAI API key" hort --secret openai-key
Set a passphrase during hort init. That's it. Then tell your agent to run hort --help.
// open source
Yours to read, run and keep.
Hort is open source under the MIT license. Read the code, audit the crypto, send a pull request.
The CLI needs no server at all. When Hort 1.0 brings sync and the web app, you can use the hosted service at hort.pm or run the backend yourself.Coming with 1.0
Why "Hort"?
"Hort" is German for a safe place, and for a treasure hoard, like the Nibelungenhort. The logo is a key in a nest: your secrets, kept safe, close to home.
