Claude Code

Claude Code is Anthropic’s agentic coding CLI: it reads your files, runs your commands, and edits your repository in a loop. It speaks the Anthropic Messages API, so it points at the gateway’s messages surface and needs no proxy, plugin or shim — only a base URL and a key.

Warning The Anthropic base URL stops at the organisation UUID. Do not append /v1 — the Anthropic client appends it itself. https://guardrails.vulnetix.com/anthropic/{orgUuid}/v1 is wrong and produces a 404. This is the single most common hand-configuration mistake; vulnetix ai-firewall install claude-code gets it right for you.

Why put Claude Code behind the firewall

  • Your provider key never sits in the agent’s config. Claude Code carries your Vulnetix API key. Your Anthropic key stays in the KMS-encrypted BYOK vault and is decrypted just-in-time by the gateway, on the server side of the request.
  • Every prompt the agent sends is screened by your guardrails — and for an agent, “prompt” means far more than what you typed. The contents of every file it reads and the output of every command it runs are fed back into the conversation as tool results, and those go through your guardrails too.
  • Provider and model policy is enforced centrally. Claude Code cannot silently switch to a model your organisation has not approved: the decision is made at the gateway, on every request, not in a local config file a developer can edit.

Quick start

CLI
vulnetix ai-firewall key set anthropic --from-env ANTHROPIC_KEY
vulnetix ai-firewall install claude-code

That writes an env block into ~/.claude/settings.json — or into <repo>/.claude/settings.json if you pass --scope project.

vulnetix ai-firewall install claude-code --scope project --dry-run

--dry-run prints the exact file and the exact block it would write, and changes nothing.

Then make sure your Vulnetix API key is in the environment Claude Code inherits:

export VULNETIX_API_KEY=vlx_...
Tip vulnetix ai-firewall install shell adds a managed block to your shell rc that exports VULNETIX_API_KEY for you, so every client on the machine picks it up.
Manual

Claude Code reads three environment variables. Set them either in your shell profile, or in the "env" key of .claude/settings.json.

Option A — shell profile (~/.zshrc, ~/.bashrc, ~/.config/fish/config.fish):

export ANTHROPIC_BASE_URL="https://guardrails.vulnetix.com/anthropic/{orgUuid}"
export ANTHROPIC_AUTH_TOKEN="$VULNETIX_API_KEY"
export ANTHROPIC_API_KEY=""

Option B — .claude/settings.json (user-level at ~/.claude/settings.json, or project-level at <repo>/.claude/settings.json):

{
  "env": {
    "ANTHROPIC_BASE_URL": "https://guardrails.vulnetix.com/anthropic/{orgUuid}",
    "ANTHROPIC_AUTH_TOKEN": "vlx_...",
    "ANTHROPIC_API_KEY": ""
  }
}

Three things to get right:

  1. No /v1 on ANTHROPIC_BASE_URL.
  2. ANTHROPIC_AUTH_TOKEN is your Vulnetix API key, not an Anthropic key.
  3. ANTHROPIC_API_KEY must be set to an explicit empty string. If it still holds a stale Anthropic key, that key conflicts with the auth token and you get confusing authentication behaviour.
Warning If you have previously logged in to Claude Code with an Anthropic account, run /logout first. A cached login takes precedence over these settings, and your traffic will keep going straight to Anthropic — bypassing the firewall entirely.

How it works

Claude Code sends POST /v1/messages to https://guardrails.vulnetix.com/anthropic/{orgUuid} — the gateway’s messages surface. The gateway authenticates the Vulnetix API key to your organisation, applies provider and model policy, runs your guardrails over every text segment in the request, decrypts your Anthropic key from the vault, and forwards the call. Prompts and completions are never logged.

No local proxy is required. Claude Code is talking to the gateway directly, over the same protocol it would use to talk to Anthropic.

Verify

Inside Claude Code:

/status

It prints the auth token source and the base URL it is using. You are looking for:

Auth token: ANTHROPIC_AUTH_TOKEN
Base URL:   https://guardrails.vulnetix.com/anthropic/{orgUuid}

If the base URL is https://api.anthropic.com — or the auth source is an OAuth login rather than ANTHROPIC_AUTH_TOKEN — you are not going through the firewall. Run /logout, restart the session, and check again.

From outside:

vulnetix ai-firewall status

Claude Code should show as wired, with no bypasses_firewall warning.

Limitations

Once wired, every model request Claude Code makes goes through the firewall — including the small-model calls it makes for background work, because those use the same base URL and credential.

Two honest caveats:

  • The arguments the model generates for a tool call are not scanned. Prompt content and tool results are; the tool-call arguments the model emits are not.
  • A developer who unsets ANTHROPIC_BASE_URL, or logs back in with /login, is talking to Anthropic directly again. The firewall is a control, not a cage. vulnetix ai-firewall status exists so you can find that machine — its bypasses_firewall check is exactly this case.

Common errors

401 — invalid Vulnetix API key

{
  "type": "error",
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "invalid Vulnetix API key"
  }
}

Almost always the two-keys confusion: ANTHROPIC_AUTH_TOKEN is holding an Anthropic key (sk-ant-…) instead of your Vulnetix API key. Your provider key belongs in the vault, never in the agent.

Fix:

  1. Put your Anthropic key in the vault: vulnetix ai-firewall key set anthropic --from-env ANTHROPIC_KEY.
  2. Set ANTHROPIC_AUTH_TOKEN to your Vulnetix API key.
  3. Set ANTHROPIC_API_KEY to an explicit empty string.
  4. Restart the Claude Code session and confirm with /status.

403provider_key_missing

{
  "type": "error",
  "error": {
    "type": "permission_error",
    "code": "provider_key_missing",
    "message": "no Anthropic API key configured for your organisation: add one with 'vulnetix ai-firewall key set anthropic' or at https://www.vulnetix.com/vdb-ai-firewall#byok"
  }
}

You are authenticated, but your organisation has no Anthropic key in the vault, so the gateway has nothing to forward the request with.

Fix:

  1. export ANTHROPIC_KEY=sk-ant-...
  2. vulnetix ai-firewall key set anthropic --from-env ANTHROPIC_KEY
  3. vulnetix ai-firewall status — the anthropic row should now show a stored key.

403model_not_allowed

{
  "type": "error",
  "error": {
    "type": "permission_error",
    "code": "model_not_allowed",
    "message": "model claude-opus-4-1 is not in the organisation allowlist"
  }
}

Your organisation runs an allowlist for this provider, and the model Claude Code asked for is not on it. (A model that is explicitly denied returns model_denied instead.)

Fix:

  1. Ask your administrator which models are allowed, or run vulnetix ai-firewall get.
  2. Point Claude Code at an approved model with /model inside the session.
  3. If the model should be allowed, an administrator adds it to the policy.

404unsupported_api

{
  "type": "error",
  "error": {
    "type": "not_found_error",
    "code": "unsupported_api",
    "message": "provider openai does not support the Anthropic Messages API (POST /v1/messages). Use POST /v1/chat/completions for openai, or point your Anthropic client at a provider that serves the Messages API: https://guardrails.vulnetix.com/anthropic/{orgUuid} (note: no /v1 suffix — the Anthropic SDK appends it)"
  }
}

Two causes, and the message distinguishes them: either the provider slug in your base URL is not anthropic, or you appended /v1 and the client appended another one on top.

Fix:

  1. Check ANTHROPIC_BASE_URL with /status inside Claude Code.
  2. It must be exactly https://guardrails.vulnetix.com/anthropic/{orgUuid} — the slug anthropic, and no trailing /v1.
  3. Re-run vulnetix ai-firewall install claude-code to have the CLI write it correctly.