LOCAL SECRETS · CLAUDE CODE · MACOS · LINUX · WINDOWS
Let Claude use your secrets,
not
see
them.
MCP-native. Local-first. Zero telemetry. Apache-2.0 crypto.
@you/clsec — ~/.clsec
# Claude generates this in the conversation: $ curl -H "Authorization: Bearer {{GITHUB_TOKEN}}" api.github.com/user # PreToolUse hook rewrites to (transcript keeps the placeholder): $ clsec-exec -- curl -H "Authorization: Bearer {{GITHUB_TOKEN}}" api.github.com/user # stdout returned to Claude (scrubbed): {"login":"octocat","id":42,"public_repos":17}
# MCP tools exposed to the model: → secret_list list all stored names → secret_describe metadata only — no value → secret_rotate prompt user, encrypt new → secret_tag organize without revealing → secret_audit_log read who accessed what # Tools the MCP server cannot expose — by API shape: ✗ secret_reveal does not exist ✗ secret_read does not exist ✗ secret_export_plaintext does not exist
# clsec audit --since 1h 2026-05-18T20:14:03Z resolve GITHUB_TOKEN caller=clsec-exec child=curl exit=0 2026-05-18T20:14:51Z resolve VERCEL_TOKEN caller=clsec-exec child=vercel exit=0 2026-05-18T20:17:22Z denied GITHUB_TOKEN caller=mcp reason=role_forbidden 2026-05-18T20:19:08Z rotate OPENAI_API_KEY caller=cli old=superseded 2026-05-18T20:21:44Z resolve SLACK_WEBHOOK caller=clsec-exec child=curl exit=0
curl -fsSL https://claulock.com/install.sh | sh macOS 13+ · Apple Silicon / Intel · verifies minisign + cosign before extracting
curl -fsSL https://claulock.com/install.sh | sh Linux arm64 / x86_64 · glibc 2.31+ · same signature verification chain
irm https://claulock.com/install.ps1 | iex Windows 10 1803+ · arm64 / x86_64 · drops binaries under %LOCALAPPDATA%\ClauLock\bin
v0.6.0 drag-to-Applications · first-run wizard · menu-bar + Dock What's new →
- Leak surfaces enumerated
- 5 leak surfaces
- Network calls from the daemon
- 0 telemetry calls
- Platforms supported
- 3 platforms
- Crypto license
- Apache-2.0 crypto core
WORKS WITH
- Claude Code (MCP + shell hooks)
- Cursor (MCP)
- Continue (MCP)
- Zed (MCP)
- Codex CLI (shell hooks)
- Aider (shell hooks)
Anything that speaks MCP or shell hooks. Ship a client we're missing? Open an issue.
WHAT CLAULOCK IS
A local socket between Claude and your secrets.
Five guarantees that hold by the shape of the system, not by promise.
- Never-reveal invariant. The MCP surface exposes no tool that returns a plaintext value. Exfiltration isn't unlikely — it's structurally impossible by API shape.
- MCP-native. Drop-in for Claude Code, Cursor, Continue — anything that speaks MCP. One install registers the server, the hooks, and the daemon.
- Local-first. Daemon + Unix socket + ~/.clsec/vault.clsec on your machine. No cloud account, no telemetry, no update server that phones home.
- Auditable crypto. XChaCha20-Poly1305 + Argon2id (256 MiB, t=3, p=4), AAD-bound per record. Apache-2.0 licensed so auditors read the code first.
- Signed binaries. macOS notarized, Linux + Windows minisign + cosign with reproducible builds and a CycloneDX SBOM in every release.
HOW IT WORKS
Three hooks, one socket, zero leaks.
The invariant — Claude references a secret by name, never by value — is enforced at three layers. All three must hold. We test the invariant in CI on every push.
STEP 1 — PRETOOLUSE HOOK
Rewrite the command before it runs.
# Claude generates this command:
curl -H "Authorization: Bearer {{GITHUB_TOKEN}}" api.github.com/user
# PreToolUse hook rewrites to:
clsec-exec -- curl -H "Authorization: Bearer {{GITHUB_TOKEN}}" api.github.com/user
The placeholder stays in Claude's transcript. The plaintext is fetched out-of-band by clsec-exec and substituted at fork/exec — only the child process sees it.
STEP 2 — MCP SERVER
List, describe, rotate. Never reveal.
# Tools the MCP server exposes:
secret_list secret_describe secret_rotate secret_tag secret_audit_log
# Tools that don't exist (by API shape — not removed, never built):
secret_reveal secret_read secret_export_plaintext
The MCP server runs under role Mcp. At the IPC layer, the daemon blocks role Mcp from calling Method::Resolve. A compromised MCP binary still cannot ask for a value.
STEP 3 — POSTTOOLUSE SCRUBBER
Redact anything that leaked into stdout.
# Raw output from a curl that printed the token:
Authenticated as octocat (token: ghp_live_AbCd1234EfGh5678…)
# Scrubbed before Claude's tool result returns:
Authenticated as octocat (token: [REDACTED:GITHUB_TOKEN])
Aho-Corasick scan over stdout for any value resolved during the call. Base64, percent-encoded, and hex-escaped variants are precomputed — leaks through JSON, URLs, and debug traces are caught automatically.
MCP SERVER
ClauLock speaks MCP natively.
ClauLock ships an MCP server so Claude can list, describe, and rotate your secrets — but never read their plaintext. Drop it into your claude_desktop_config.json and your existing MCP-aware clients pick it up automatically. The clsec install command does this for you on the supported platforms.
// ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"claulock": {
"command": "clsec-mcp",
"args": []
}
}
} The server runs under role Mcp and is forbidden from Resolve at the daemon. It exposes secret_list, secret_describe, secret_rotate, secret_tag, secret_audit_log — and nothing else.
What every shortcut actually leaks
Where your secrets actually go
Five common patterns, four leak surfaces. The boxes you can't repaint after the fact are the ones in red.
| Pattern | In Claude transcript | In shell history | In model's context window | Reversible after the fact |
|---|---|---|---|---|
| Paste in chat | Yes — verbatim | No | Yes | No |
| export VAR=… | Sometimes | Yes | If Claude reads env | Manual scrub |
| .env file | If Claude `cat`s it | No | If Claude `cat`s it | Manual delete |
| Vault / 1Password CLI | If exported | No | If exported | Rotation |
| ClauLock | Placeholder only | No | Placeholder only | clsec rotate |
The problem isn't where you keep the secret. It's the moment it crosses into the model's view. ClauLock makes that crossing optional.
What Claude sees vs what runs
Same command, five layers. The plaintext appears on exactly one
line — inside the child process that actually needs it, for the
lifetime of that one execve.
| Layer | Content |
|---|---|
| Claude's transcript | curl -H "Authorization: Bearer {{GITHUB_TOKEN}}" api.github.com/user |
| Bash tool call | curl -H "Authorization: Bearer {{GITHUB_TOKEN}}" api.github.com/user |
| After PreToolUse hook | clsec-exec -- curl -H "Authorization: Bearer {{GITHUB_TOKEN}}" … |
| Inside clsec-exec (child argv only) | curl -H "Authorization: Bearer ghp_live_…" api.github.com/user |
| stdout returned to Claude | {"login":"octocat",…} (scrubbed) |
Only the fourth line ever contains the real value. See how this differs from Vault, Composio, Doppler, and .env.
I WANT CLAUDE TO…
Every workflow you've already given Claude, safely
These are the credentials that quietly accumulate in your transcripts today. With ClauLock, each one becomes a placeholder Claude can reference but not read.
- push commits to my private repo.
GITHUB_TOKENClaude calls `git push` with `Authorization: Bearer {{GITHUB_TOKEN}}`. The token never appears in the diff, the message, or the transcript. - deploy to Vercel.
VERCEL_TOKEN`vercel deploy --token {{VERCEL_TOKEN}}` runs from inside `clsec-exec`. The model sees the placeholder, the deploy sees the real value, the audit log sees both events. - run a Supabase migration.
DATABASE_URL · SUPABASE_SERVICE_KEYTwo secrets, one popup each — only on first use. After that, `clsec migrate up` works for every future session without re-asking. - fine-tune an OpenAI model.
OPENAI_API_KEYThe most expensive paste-and-forget mistake. ClauLock keeps the key in your local vault; usage shows up in `clsec audit` with byte counts and exit codes. - send a Slack message to my team.
SLACK_WEBHOOK_URLClaude posts release notes via `curl -d ... {{SLACK_WEBHOOK}}`. The webhook URL stays out of every Claude window — past, present, future. - rotate my keys when something feels off.
any name`clsec rotate {{NAME}}` re-prompts you, encrypts the new value, and marks the old as superseded in the audit log. No grep through history.
Total visibility
Every time Claude touched your tokens
Locally written, locally readable. Tamper-evident hash chain so a compromised tool call can't quietly edit history. Run `clsec audit --since 24h` whenever you want a copy.
read = secret resolved into a child process · revealed-blocked = scrubber caught a leak attempt · rotated = you replaced the value
Why this exists
Claude Code can run shell commands. That's the whole point. But the
usual ways of giving it credentials — environment variables,
.env files, pasting a token into
chat — all end with the plaintext sitting in a transcript or a log.
✗ export GITHUB_TOKEN=ghp_Ab12...
→ value lands in shell history, env, and every tool output
✗ "Here's my token: ghp_Ab12..." → value lands in the model's context and the transcript
✓ curl -H "Authorization: Bearer {{GITHUB_TOKEN}}" ... → ClauLock resolves at fork/exec. Transcript keeps the placeholder.
Founders — Pre-1.0 backers
Help ship 1.0. Become a Founder.
$49 one-time → 2 years of Pro ($98 value). Pay year one, year two is on us. Plus your name in the public repo, early access to Pro features, and a vote on the roadmap. 2,500 slots — closes when v1.0 ships.
$49 — save $49 vs. $49/year Pro after launch
Try it in five minutes.
One command installs the daemon, the MCP server, and the Claude Code hooks. Free forever for individuals — Pro tier unlocks sync and breach detection.
curl -fsSL https://claulock.com/install.sh | sh