K0KEYZERO

Use Case

Secret Management for Claude Code

Keep API keys out of context windows, conversation logs, and MCP tool calls when using Claude Code with KeyZero.

Claude Code is Anthropic's CLI-based coding agent. It reads your codebase, executes shell commands, calls MCP tools, and writes code -- all inside a terminal session that maintains a running conversation context. Every token in that context is sent to the Anthropic API on each turn. If an API key enters the context window, it persists for the entire session and is transmitted with every subsequent request.

How Claude Code Handles Secrets Today

Most developers give Claude Code access to credentials in one of three ways:

  1. Environment variables set in .bashrc, .zshrc, or the shell profile. Claude Code inherits these when it spawns subprocesses.
  2. .env files in the project root. Claude Code can read these files directly and will often cat .env to understand the project setup.
  3. MCP server configuration in .mcp.json, where credentials are passed as command-line arguments or environment variables to MCP server processes.

All three approaches put raw credentials within reach of the agent. When Claude Code runs env or reads a .env file, those values enter the context window. When it calls an MCP tool that returns an error containing a connection string, that credential is now part of the conversation.

The Problem

The risk is not that Claude Code is malicious. The risk is that credentials in context windows are transmitted, stored, and logged in places you do not control -- a pattern explored in depth in why AI agents leak secrets:

  • API request logs at the LLM provider contain the full context, including any secrets that entered the conversation.
  • Conversation history persisted locally includes every tool response.
  • MCP tool call arguments and responses are serialized into the context. A GitHub MCP server that echoes back a token in an error message has leaked that token into the conversation permanently.
  • Code generation may include secrets. If Claude Code sees OPENAI_API_KEY=sk-abc123 in the environment, it might hardcode that value into generated configuration files.

How KeyZero Solves This

Wrapping Claude Code with kz run

The simplest integration: wrap the claude process so secrets are injected at runtime but resolved from a vault backend, not from plaintext files.

kz run -- claude

Your .keyzero.toml maps environment variable names to vault references:

[secrets]
GITHUB_TOKEN     = { provider = "keychain", ref = "github-pat" }
OPENAI_API_KEY   = { provider = "1password", ref = "op://Dev/OpenAI/api-key" }
DATABASE_URL     = { provider = "vault", ref = "secret/data/dev/db/url" }
ANTHROPIC_API_KEY = { provider = "keychain", ref = "anthropic-key" }

When kz run starts, it resolves each secret from the configured backend and injects the values as environment variables into the claude process. No .env file on disk. No plaintext credentials in your shell profile. If Claude Code runs cat .env, there is nothing to find.

Blind Mode for MCP Tools

Blind mode is the stronger protection. Instead of injecting real credentials, KeyZero gives the subprocess opaque tokens like KZ_TOK_a8f3e1. A local MITM proxy intercepts outgoing HTTP requests and swaps these tokens for real credentials at the network edge.

kz run --blind -- claude

Now when Claude Code (or any MCP tool it invokes) makes an API call with KZ_TOK_a8f3e1 in the Authorization header, the proxy replaces it with the real token before the request leaves your machine. The agent never sees the real credential. If it leaks the token into context, that token is useless outside the proxy. See blind mode explained in detail for the full mechanics.

KeyZero as an MCP Server

For tool-calling workflows, you can run KeyZero as an MCP server that Claude Code invokes directly. This pattern is covered in detail in our guide to securing MCP servers with KeyZero, and you can learn more about MCP-specific considerations on the MCP servers integration page. Add this to your project's .mcp.json:

{
  "mcpServers": {
    "keyzero": {
      "command": "kz",
      "args": ["server", "start", "--bundle", "./bundle.yaml", "--mcp"]
    }
  }
}

This exposes two tools to Claude Code:

  • resolve -- returns a secret value after policy evaluation. Use when the agent genuinely needs the value (e.g., to construct a config file).
  • fetch -- resolves the credential and makes the HTTP request on behalf of the agent. The agent sees the API response but never the credential itself.

The fetch tool is the preferred pattern. Instead of Claude Code calling the GitHub API directly with a token, it asks KeyZero to make the request. The response comes back without the credential ever touching the context window.

Example: Full Claude Code Setup

A typical project using Claude Code with GitHub, OpenAI, and a database:

# .keyzero.toml
[secrets]
GITHUB_TOKEN   = { provider = "1password", ref = "op://Dev/GitHub-PAT/token" }
OPENAI_API_KEY = { provider = "keychain", ref = "openai-api-key" }
DATABASE_URL   = { provider = "vault", ref = "secret/data/dev/postgres/url" }

Start Claude Code with blind mode:

kz run --blind -- claude

Or with shell hooks, secrets load automatically when you cd into the project:

cd ~/projects/myapp   # shell hook detects .keyzero.toml, resolves secrets
claude                 # Claude Code inherits resolved env vars

The result: Claude Code has full access to the APIs it needs, but raw credentials never enter the conversation context, never appear in tool responses, and never get hardcoded into generated files.

Why This Matters for Claude Code Specifically

Claude Code sessions are long-running. A typical session might span dozens of turns over an hour, with the context window accumulating tool responses, shell output, and file contents. A credential that leaks into turn 3 is retransmitted on turns 4 through 50. KeyZero eliminates this class of exposure entirely -- credentials are resolved at the process boundary or the network edge, and the agent operates with opaque references that have no value outside the controlled environment.