Claude Cowork
Claude Cowork routes Claude Code's inference through Corveil using a gateway inference config plus a small credential helper. Your Claude Code OAuth token flows upstream to Anthropic, while a separate x-citadel-api-key header authenticates with Corveil for tracking and guardrails — the same passthrough model as the Claude Code guide, but driven by a JSON config file and a keychain helper script instead of environment variables.
Prerequisites
- A running Corveil instance (see deployment options)
- A Corveil virtual API key (
sk-citadel-...) — create one under Corveil → Settings → API Keys - macOS — the helper reads from the macOS Keychain
- Claude Code installed and logged in, so the
Claude Code-credentialskeychain entry exists jqinstalled (brew install jq)
Mode
Passthrough mode. Unlike the Claude Code guide's ANTHROPIC_CUSTOM_HEADERS approach, Cowork reads a versioned JSON inference config and sources the upstream token from a helper script at request time.
1. Configure the inference passthrough
Add the following to your Claude Cowork inference config. The credential.command is an absolute path to the helper script from the next step.
{
"$schemaVersion": 2,
"inference": {
"provider": "gateway",
"baseUrl": "https://corveil.io",
"customHeaders": {
"x-citadel-api-key": "sk-citadel-your-key-here"
},
"credential": {
"kind": "helper-script",
"command": "/absolute/path/to/claudecode.sh"
}
},
"chatSurface": {
"enabled": true
}
}Field reference
$schemaVersion— config schema version; use2.inference.provider— must begatewayto route inference through Corveil.inference.baseUrl— your Corveil host (https://corveil.iofor the hosted gateway).inference.customHeaders.x-citadel-api-key— your Corveil virtual API key (sk-citadel-...). This is what authenticates the call with Corveil.inference.credential.kind—helper-script; tells Cowork to run a command to fetch the upstream token.inference.credential.command— absolute path toclaudecode.sh(below). Cowork runs it and uses stdout as the upstream bearer token.chatSurface.enabled—trueturns on the Cowork chat surface.
2. Install the credential helper
Save this as claudecode.sh. It reads the Claude Code OAuth token from the Claude Code-credentials keychain entry and prints the access token on stdout:
#!/bin/sh
security find-generic-password -s "Claude Code-credentials" -w | jq -r '.claudeAiOauth.accessToken'Then make it executable and point credential.command at its absolute path:
chmod +x claudecode.sh
# use the absolute path, e.g. /Users/you/bin/claudecode.sh, in credential.command
pwd- The
commandmust be an absolute path — a relative path won't resolve when Cowork runs it. - Requires
jqonPATHto extract the token from the keychain JSON. - The token comes from the
Claude Code-credentialskeychain entry, so Claude Code must be logged in on this machine.
3. Confirm passthrough
Sanity-check the helper by itself. Running it should print a long, non-empty token — not
nulland not an error:bash./claudecode.shLaunch Cowork (or Claude Code with this config) and send a simple prompt.
A successful passthrough returns a normal completion and the request shows up in Corveil. Confirm via the CLI or the request-log / spend dashboard in the UI:
bashcorveil logs --tail 5
If the prompt answers and the call appears in the Corveil logs, inference is round-tripping through the gateway.
Troubleshooting
jq: command not found/ empty token: installjq(brew install jq) and re-run the helper.- Helper prints
nullor errors: Claude Code isn't logged in, or the token expired — re-login to Claude Code. A stale token surfaces as a 401 from the upstream provider. - 401 from Corveil: the
x-citadel-api-keyis missing or invalid — verify the value under Settings → API Keys. - "permission denied" running the helper: run
chmod +x claudecode.sh, and confirmcredential.commandis the correct absolute path. - Connection refused: ensure the Corveil instance is running and
inference.baseUrlis reachable.