A growing number of providers expose Anthropic-compatible API endpoints for Claude Code:
They all work the same way: set ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN, and Claude Code talks to them instead of Anthropic. Their docs typically suggest putting the key straight into ~/.claude/settings.json:
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.minimax.io/anthropic",
"ANTHROPIC_AUTH_TOKEN": "<MINIMAX_API_KEY>"
}
}That, unfortunately, involves saving a plaintext secret on disk. Plaintext secrets anywhere near Claude Code are risky – it has been known to read .env files and leak their contents into session transcripts and tool-result logs under ~/.claude/, and settings.json itself is no safer. A popular workaround is a ~/.secrets file sourced from your shell profile, but that still means the key is stored in plaintext, just somewhere else.
One nice way of going around this that I found useful was to use keepassxc-proxy-getpw, which talks to a running KeePassXC instance over its browser integration protocol and returns the password for a matching entry. We can then wrap it in a fish function and make sure the key never touches disk:
function claude-minimax \
--wraps='claude' \
--description 'Run Claude Code against MiniMax M2.7 API'
ANTHROPIC_BASE_URL="https://api.minimax.io/anthropic" \
ANTHROPIC_AUTH_TOKEN=(keepassxc-proxy-getpw \
"https://api.minimax.io" \
--filter name="MiniMax API Key") \
ANTHROPIC_MODEL="MiniMax-M2.7" \
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC="1" \
API_TIMEOUT_MS="3000000" \
claude $argv
endThere are two optional (but relevant!) env variables added to the “alias function” above, that it might make sense to keep there in general. CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 stops Claude Code from phoning home to Anthropic for telemetry and update checks, which you may not want to do for a third-party provider anyway. API_TIMEOUT_MS bumps the request timeout to avoid cuts on longer responses.
The --wraps='claude' flag gives the function the same tab completions as claude itself.
This approach is very general – here is the same thing for Z.AI:
function claude-zai \
--wraps='claude' \
--description 'Run Claude Code against Z.AI GLM-4.7'
ANTHROPIC_BASE_URL="https://api.z.ai/api/anthropic" \
ANTHROPIC_AUTH_TOKEN=(keepassxc-proxy-getpw \
"https://api.z.ai" \
--filter name="Z.AI API Key") \
ANTHROPIC_MODEL="GLM-4.7" \
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC="1" \
API_TIMEOUT_MS="3000000" \
claude $argv
endThe env vars are set inline as prefixes to claude, so they only exist for that process – they won’t show up in env or leak into the rest of your shell session. And since the key is fetched at invocation time, there’s nothing to update when you rotate it in KeePassXC.
In bash/zsh the equivalent uses $() instead of fish’s () for command substitution. A function (rather than an alias) keeps the _key variable scoped:
claude-minimax() {
local _key
_key=$(keepassxc-proxy-getpw "https://api.minimax.io" \
--filter name="MiniMax API Key") &&
ANTHROPIC_AUTH_TOKEN=$_key \
ANTHROPIC_BASE_URL="https://api.minimax.io/anthropic" \
ANTHROPIC_MODEL="MiniMax-M2.7" \
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC="1" \
API_TIMEOUT_MS="3000000" \
claude "$@"
}The same pattern works for any provider that uses ANTHROPIC_BASE_URL – just swap the URL, model name, and KeePassXC entry. Alorse/cc-compatible-models maintains a living list of compatible providers if you want to see what else is out there.
And if you don’t use KeePassXC, the same idea applies with other password manager CLIs: op read for 1Password, bw get password for Bitwarden, or pass show for pass.