Guide
Use an API key with Claude Code without pasting it anywhere
Claude Code can bill an Anthropic API key from the Claude Console instead of your subscription. The usual advice, an export ANTHROPIC_API_KEY=… in your shell profile, puts the key in a plain file and in the environment of every command Claude runs. Here are three better ways, with and without Secretariat.
Checked against Claude Code's documentation on 13 November 2026.
How Claude Code picks up a key
ANTHROPIC_API_KEY: Claude Code sends it as theX-Api-Keyheader. In an interactive session it asks once whether to use it instead of your subscription; with-pit always uses it./statusshows which credential is active.apiKeyHelperinsettings.json: a shell command whose output Claude Code sends as the key. Meant for keys fetched from a vault.- Subprocesses: by default, Bash commands Claude runs inherit Claude Code's environment, so an agent can read
ANTHROPIC_API_KEYwithprintenv. SettingCLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1removes credentials from the environment of Bash commands, hooks and stdio MCP servers; Claude Code keeps the key for its own requests.
Option 1: macOS Keychain and apiKeyHelper (no extra tool)
Store the key once in your login keychain, then let Claude Code ask the keychain for it:
security add-generic-password -s anthropic-api-key -a "$USER" -w # paste the key at the prompt, it isn't echoed
// ~/.claude/settings.json
{
"apiKeyHelper": "security find-generic-password -s anthropic-api-key -w"
}
No plain file, no export. The catch: the same command works for the agent too. Claude can run security find-generic-password … -w in its Bash tool and the key lands in the conversation. Add a deny rule such as "Bash(security find-generic-password *)" under permissions.deny, and know that a rule matches the command text, not every way to reach the keychain.
Option 2: start Claude Code through Secretariat
Secretariat keeps the key in your iCloud keychain and hands it to the program you start through it. Capture the key from the Console with ⌃⌥⌘V (or import it), then bind it to a profile that works in every folder:
secretariat profile create claude-api --dir '*' secretariat profile bind claude-api ANTHROPIC_API_KEY \ personal/anthropic/api/api_key
Start Claude Code like this, for example as a shell alias:
alias claude-api='CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1 \ secretariat run claude-api -- claude'
Claude Code gets the key for its own requests; with the scrub, the commands it runs don't. Secretariat's Claude Code hook refuses printenv, cat .env and reading keychain passwords before they run (secretariat guard claude install), and every start is logged with time and origin.
One limit to know: an agent running as you can call secretariat run claude-api -- … itself, and the hook doesn't stop every way to write the value somewhere. The hard boundary is Touch ID: switch it on for this item (secretariat item set personal/anthropic/api --approval on) and every start waits for your fingerprint.
Option 3: let Claude Code use your keys for tools, not for itself
Often the question behind “Claude Code API key” is a different one: Claude needs a Stripe, OpenAI or Cloudflare key to run tests or deploy. Keep your subscription for Claude Code and let it run those tools through Secretariat by profile name; the program gets the value, Claude sees [masked]. See how it works.
What none of this prevents
- Claude Code itself must hold the key to call the API. Anything running as your user with enough effort can get at it; see the threat model.
- A key in
~/.zshrcor a project.envis still readable by any process. Remove those copies once the key lives in the keychain. - Claude Desktop and cloud sessions ignore
ANTHROPIC_API_KEYandapiKeyHelper; they sign in with your account (except desktop sessions set up for a third-party inference provider).
Sources: Claude Code docs on authentication, settings and environment variables.