Skip to main content
Glama

tresor

Let coding agents use your API tokens without ever seeing them.

Tokens live in your operating system's keychain, stay in your password manager, or are minted fresh for a few minutes. The agent works with names (openai, github); tresor injects the real value into the command, HTTP request or .env file and redacts it from everything the agent gets back.

  • Works on macOS, Windows and Linux, with Claude Code, Cursor, OpenAI Codex, Gemini CLI and GitHub Copilot in VS Code

  • Reads from 1Password, Bitwarden / Vaultwarden, Bitwarden Secrets Manager, KeePassXC, Proton Pass, Dashlane, Keeper, pass, gopass, LastPass, AWS Secrets Manager, Azure Key Vault, Google Secret Manager, Doppler, Infisical, HashiCorp Vault / OpenBao or any CLI you configure

  • Short-lived credentials instead of long-lived tokens: AWS SSO, GitHub App installation tokens, OAuth refresh, gcloud, Azure, or any CLI

  • Finds real leaks: because tresor knows the values, tresor scan finds them in files, staged commits and Claude transcripts — no guessing by pattern

  • Migrates .env files into the keychain and keeps a committable .tresor.json mapping

  • Per-secret policies (allowed commands, confirm on use, expiry) and a usage log

  • No server, no extra master password, nothing leaves your machine

  • Ships as a Claude Code plugin: MCP server + skill that teaches the agent how to use it + guard hook

Platform

Where local values are stored

macOS

Keychain

Windows

Credential Manager (max. 2560 bytes per value)

Linux

Secret Service (gnome-keyring, KWallet, KeePassXC)

Install

As a Claude Code plugin (MCP server, skill and guard hook in one step):

/plugin install tresor --marketplace Benewe1337/tresor

On first start the plugin installs its runtime dependencies (needs Node.js ≥ 20 and npm).

Other agents — the repo is also a native plugin/extension for them:

Agent

Install

OpenAI Codex

codex plugin marketplace add Benewe1337/tresor, then install tresor from /plugins and trust its hook in /hooks

Gemini CLI

gemini extensions install https://github.com/Benewe1337/tresor (uses the archive attached to each GitHub release)

Cursor

add the repo as a plugin marketplace ("Import from Repo"), or copy it to ~/.cursor/plugins/local/tresor

VS Code

enable chat.plugins.enabled, then "Chat: Install Plugin from Source" with the repo URL (loads the Claude plugin format)

any MCP client

npx -y @benewe1337/tresor mcp as a stdio server (once published to npm and the MCP Registry as io.github.Benewe1337/tresor)

Without plugin support, the command-line tool can write the agent's config files directly:

tresor install all --dry-run      # shows which config files would change
tresor install all                # or: tresor install cursor | codex | gemini | vscode

See Other agents for what exactly is written where.

Command-line tool for storing tokens and unlocking password managers in your own terminal:

npm install -g github:Benewe1337/tresor      # or, once on npm: npm install -g @benewe1337/tresor
tresor --help
git clone https://github.com/Benewe1337/tresor && cd tresor
npm install && npm run build && npm test && npm link
claude mcp add --scope user tresor -- tresor-mcp

Add the guard hook to ~/.claude/settings.json under hooks.PreToolUse:

{ "matcher": "Bash|PowerShell|Read|Grep|Edit|MultiEdit|Write|NotebookEdit",
  "hooks": [{ "type": "command", "command": "tresor-guard", "timeout": 10 }] }

The skill lives in skills/tresor/SKILL.md; copy it to ~/.claude/skills/tresor/ if you want it without the plugin.

Related MCP server: claude-secrets

Store a token locally

tresor set openai                       # paste the value, input is hidden
tresor set github --clip                # take it from the clipboard, then clear the clipboard
tresor set openai -d "Project X" --host api.openai.com   # only ever send it to this host
tresor list
tresor rm openai

Or let Claude ask: tresor_request opens a native dialog (macOS/Windows; zenity or kdialog on Linux, otherwise a one-time form on 127.0.0.1 in your browser). You paste the token there and it goes straight into the keychain. Never paste tokens into the chat.

Link a password-manager entry

tresor link stores no value, only where it lives. tresor fetches it fresh through the manager's CLI every time it is used.

tresor providers                        # what is installed/unlocked, reference syntax
tresor link openai 1password "op://Private/OpenAI/credential"
tresor link github bitwarden "GitHub PAT#token"
tresor link stripe keepassxc "Dev/Stripe"
tresor link db pass "work/postgres#user"

Provider

CLI

Reference

Setup

1password

op

op://vault/item/field

1Password app → Developer → CLI integration (Touch ID / Windows Hello), or OP_SERVICE_ACCOUNT_TOKEN

bitwarden

bw

item id or exact name[#password|username|notes|totp|uri|field]

bw login, then tresor unlock bitwarden (session kept in the keychain until tresor lock bitwarden). Vaultwarden works the same way.

bws

bws

secret UUID

tresor setup bws (access token)

keepassxc

keepassxc-cli

group/entry[#attribute|#totp]

tresor setup keepassxc --db file.kdbx [--keyfile k] [--no-password]

pass

pass

path[#field]

gpg-agent

gopass

gopass

path[#key]

gpg-agent / age

protonpass

pass-cli

pass://vault/item/field

pass-cli login (personal access token sessions last 2 h)

dashlane

dcli

dl://<item id>/<field>

dcli devices register + DASHLANE_SERVICE_DEVICE_KEYS, or an unlocked dcli

keeper

keeper

record UID[#password|username|totp|field]

keeper this-device persistent-login on

pass

pass

path[#field]

gpg-agent

gopass

gopass

path[#key]

gpg-agent / age

lastpass

lpass

name or id[#field]

lpass login

aws-sm

aws

name or ARN[@stage][#jsonKey]

any AWS credentials (AWS_PROFILE, SSO …)

azure-kv

az

vault/secret[/version] or the secret id URL

az login

gcp-sm

gcloud

[project/]secret[@version][#jsonKey]

gcloud auth login

doppler

doppler

[project/config/]NAME

doppler login or DOPPLER_TOKEN

infisical

infisical

projectId/env/[folder/…]NAME

infisical login or INFISICAL_TOKEN

vault / openbao

vault / bao

mount/path[@version]#field

VAULT_ADDR + VAULT_TOKEN (BAO_*)

The agent can link entries too (tresor_link), but only after you approve it in a dialog. All CLIs run without a terminal; if one would ask for a login, tresor times out and tells you what to run instead.

Custom providers (anything else with a CLI) go into providers.json in the tresor folder (~/.config/tresor, on Windows %APPDATA%\tresor):

{
  "custom": {
    "sops":   { "command": ["sops", "--decrypt", "--extract", "{ref}", "secrets.enc.yaml"] },
    "teampw": { "command": ["teampw-cli", "get", "{ref}", "--json"], "jsonPath": "data.password" }
  }
}

{ref} is passed as a single argument, never through a shell. jsonPath (optional, dot-separated) picks the value out of JSON output.

Short-lived credentials

A dynamic secret stores no token at all. It names a generator that mints a fresh credential when it is used; tresor caches it in memory until shortly before it expires (the later of 60 s or 10 % of its lifetime) and never caches failures.

tresor dynamic aws-dev aws-sso --profile dev                 # bundle: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
tresor dynamic gcp gcloud --impersonate ci@proj.iam.gserviceaccount.com
tresor dynamic arm azure --resource https://management.azure.com/
tresor dynamic bot github-app --app-id 123456 --installation-id 7890 --private-key-file app.pem \
                              --repos tresor --permissions contents=read
tresor dynamic crm oauth --token-url https://login.example.com/oauth/token --client-id abc --auth basic
tresor dynamic db command --argv '["vault","read","-format=json","database/creds/app"]' \
                          --output PGUSER=data.username --output PGPASSWORD=data.password --ttl-path lease_duration
  • Single tokens (gcloud, azure, github-app, oauth, command --json-path/raw) are used like any secret: env: {"GH_TOKEN": "bot"}, {{secret:crm}}.

  • Bundles (aws-sso, command --output …) set several variables at once: tresor run -b aws-dev -- aws s3 ls, "bundles": ["aws-dev"] in .tresor.json, or bundles in tresor_run.

  • GitHub App: the private key goes into the OS keychain (you can delete the .pem afterwards); tokens live 1 h and can be limited to repositories and permissions. Signed locally with node:crypto.

  • OAuth: client secret and refresh token are asked for hidden and kept in the keychain. Rotated refresh tokens are saved before the access token is used, under a lock, so parallel uses never burn the grant.

  • Expired logins (aws sso login, gcloud auth login, az login, an invalid_grant) are reported with the command to run. tresor never starts a login itself.

Move a .env into tresor

tresor import .env --dry-run            # see what would be imported (credentials only by default)
tresor import .env --remove             # store them, verify, then delete those lines from .env
tresor run -- npm run dev               # start your app with the values injected

import picks entries that look like credentials (*_KEY, *_TOKEN, *SECRET*, PASSWORD, URLs with a password, long opaque values). Use --all, --only A,B or --except C to choose. It writes .tresor.json next to the .env:

{ "env": { "OPENAI_API_KEY": "openai-api-key", "DATABASE_URL": "database-url" } }

That file holds names only — commit it, and everyone on the team maps the same variables to their own tresor secrets. tresor run (without -e) and Claude's tresor_run apply it automatically. Because a cloned repository could ship a .tresor.json asking for your secrets, a profile is only used after you approve its exact content once (tresor profile allow, or the dialog Claude triggers); any change needs approval again.

tresor profile                           # show the profile for this directory and whether it is trusted
tresor profile add STRIPE_KEY=stripe     # edit it

If the .env was ever committed, tresor tells you — those values are in your git history and should be rotated.

Find leaks

tresor scan                     # this directory (node_modules/.git skipped)
tresor scan --staged            # exactly what the next commit would contain
tresor scan --transcripts       # your Claude Code session history (~/.claude/projects)
tresor scan --install-hook      # git pre-commit hook that runs "tresor scan --staged"

Every stored value is searched in raw, Base64, Base64url, URL-encoded and JSON-escaped form. Findings show secret name, file and line — never the value. Exit code 1 on a hit, so it works in hooks and CI. Linked password-manager secrets are fetched for the scan too (--local-only skips them); values shorter than 8 characters are skipped to avoid false alarms.

Health check

tresor doctor                   # expired / soon expiring, old, unused, missing, locked
tresor doctor --transcripts     # also: which tokens leaked into agent transcripts

Every finding comes with what to do and, for well-known services (GitHub, GitLab, OpenAI, Anthropic, Stripe, Vercel, Cloudflare, Hugging Face, Supabase, Sentry, AWS, Google Cloud …), a link to the page where the token is rotated. Exit code 1 if something needs action now.

Policies and usage log

tresor policy github --allow-cmd gh,git      # tresor_run may only start gh or git with it (and never write it to a file)
tresor policy stripe --confirm always        # dialog before every use (or: session = once per Claude session)
tresor policy openai --expires 2027-01-31    # still works afterwards, but Claude is told to ask you to rotate it
tresor policy openai --host api.openai.com   # tresor_http only sends it there
tresor policy openai                         # show
tresor log                                   # who used what, when, for which command/host/file

Policies only apply to what the agent does through the MCP server; your own tresor run is not restricted. Claude can read policies (tresor_list) but cannot change them.

What the agent can do (MCP tools)

Tool

Purpose

tresor_list

Names, descriptions, allowed hosts, source. Never values.

tresor_providers

Installed/unlocked password managers and their reference syntax

tresor_request

Open a dialog so you can enter a value

tresor_link

Link a password-manager entry, only after you confirm in a dialog

tresor_run

Run a command with env: {"GH_TOKEN": "github"}, bundles: ["aws-dev"] and the project's .tresor.json; output is redacted

tresor_http

HTTPS request with {"Authorization": "Bearer {{secret:openai}}"}

tresor_write_file

Write e.g. a .env with KEY={{secret:openai}} (mode 600); Claude cannot read it back

tresor_scan

Look for stored values in files, staged changes or transcripts

tresor_import

Move credentials from a .env into tresor

tresor_log

Read the usage log

tresor_doctor

Health check with rotation links

Deliberately missing: any tool that returns a value, deletes one, or changes a policy.

The bundled skill (skills/tresor/SKILL.md) tells the agent when to reach for these tools, how to name secrets, and what to do with each error message.

Other agents

tresor install <agent> merges three things into the agent's user configuration, backs every file up first (*.bak-tresor-<time>), and tresor uninstall <agent> removes exactly those entries again. Files with comments (JSONC) are refused rather than rewritten.

Agent

MCP server

Guard hook

Skill

Cursor

~/.cursor/mcp.json

~/.cursor/hooks.json – beforeShellExecution, beforeReadFile, preToolUse, fail-closed

~/.agents/skills/tresor

OpenAI Codex

~/.codex/config.toml [mcp_servers.tresor]

~/.codex/hooks.json PreToolUse – trust it once via /hooks

~/.agents/skills/tresor

Gemini CLI

~/.gemini/settings.json mcpServers

same file, hooks.BeforeTool

~/.agents/skills/tresor

VS Code (Copilot)

<VS Code user dir>/mcp.json servers

~/.copilot/hooks/tresor.json preToolUse

~/.agents/skills/tresor

The guard speaks each agent's hook protocol (tresor-guard --format claude|cursor|gemini|copilot; Codex and VS Code's local harness use the Claude format). Everything above follows the vendors' documentation as of November 2026. Not verified against the live tools: the Cursor CLI running hooks.json, VS Code's hook location for its local agent harness, the exact Gemini CLI tool_input field names, and whether Antigravity CLI (Gemini CLI's successor for some accounts) reads the same settings. If a blocked command is not reported in your agent, please open an issue.

Starting other MCP servers with tokens

Instead of putting tokens into ~/.claude.json:

"my-mcp": { "command": "tresor", "args": ["run", "-e", "API_KEY=mymcp", "--", "npx", "-y", "my-mcp"] }

Threat model

tresor protects against accidental leaks: tokens in the chat, in logs, in config files, in tool output (env, verbose curl, error messages). It redacts the value plus its Base64, URL-encoded and JSON-escaped forms.

It does not protect against an agent that is determined to get a value: anything allowed to run arbitrary commands with an injected token can transform it (reverse it, split it) or send it to a server of its choosing. What helps here: host pinning (--host, enforced by tresor_http), password-manager links requiring your approval, and reviewing tresor_run calls in the permission prompt.

The guard hook (tresor-guard) blocks, inside Claude sessions:

  • reading OS credential stores directly (security find-generic-password, secret-tool lookup, keyctl print, Get-StoredCredential, PasswordVault, keyring libraries),

  • read commands of password-manager CLIs (op read, bw get/unlock/list, bws secret, keepassxc-cli show, pass show, gopass show, lpass show, pass-cli item view, dcli read, keeper clipboard-copy),

  • secret and token commands of cloud CLIs (aws secretsmanager get-secret-value, aws configure export-credentials, az keyvault secret show, az account get-access-token, gcloud secrets versions access, gcloud auth print-access-token, doppler secrets get, infisical secrets get, vault kv get),

  • tresor set|rm|run|link|unlock|setup|policy|dynamic|install|uninstall and tresor profile allow|add|rm,

  • editing anything in the tresor folder (index, policies, trusted profiles, log) — via edit tools or shell,

  • reading files written by tresor_write_file.

Status commands like bw status, op whoami or pass ls stay allowed. If the hook input is malformed, it blocks (fails closed). It matches command text, so it can occasionally block a harmless command that merely mentions one of these patterns.

Configuration

Variable

Effect

TRESOR_HOME

Metadata folder (default ~/.config/tresor, %APPDATA%\tresor on Windows)

TRESOR_PROMPT=browser

Always use the browser form instead of a native dialog (e.g. WSL)

TRESOR_LINUX_STORE=keyutils

Linux without Secret Service: kernel keyring, lost on reboot

How it works

  • Local values: @napi-rs/keyring, service tresor, account = secret name. Provider sessions and passwords (Bitwarden session, KeePassXC password, bws token) are stored there as __internal.*.

  • Dynamic credentials are cached in the memory of the running MCP server only; GitHub App keys and OAuth client secrets / refresh tokens live in the keychain under __internal.*.

  • Metadata files contain no values: index.json (names, sources, hosts, policies), providers.json, written-files.txt, trusted-profiles.json, audit.log (JSON lines, rotated at 5 MB).

  • Processes are started without a shell via cross-spawn (including .cmd shims on Windows). The KeePassXC password is piped through stdin, never passed as an argument.

Development

npm install && npm run build && npm test
TRESOR_INTEGRATION=1 npm test          # also hit the real OS credential store, pass and KeePassXC if installed
docker run --rm -v "$PWD":/src:ro node:22-bookworm bash /src/scripts/linux-integration.sh

dist/ is committed so the plugin runs without a build step; CI fails if it is out of date. CI runs on macOS, Linux and Windows.

License

PolyForm Noncommercial 1.0.0: free for personal use, hobby projects, research, education and non-profit organisations.

Commercial use (at work, for clients, inside a company) needs a separate license. Open an issue or contact @Benewe1337 on GitHub.

Versions up to and including 0.2.0 (commit c282ed5) were published under the MIT License; copies of those versions keep that license.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables secure API key management for development projects by storing keys in OS keychains, auto-generating .env files and SDK client code, and providing AI-assisted key management through Claude Code integration.
      1
      MIT
    • F
      license
      A
      quality
      D
      maintenance
      Encrypted token store for Claude Code sessions, providing MCP tools for secure secret management with macOS Keychain integration, per-project allowlists, and native dialog input.
      6
      15 npm
      6
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables Claude to access and search local messages and contacts across multiple platforms (iMessage, Discord, Gmail, Slack) via a local-first datastore, ensuring data never leaves the Mac.
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables Claude or any MCP client to read Apple Mail, Calendar, Photos, and create Apple Notes locally on macOS, without any data leaving the machine.
      MIT