Skip to content

Claude Code ​

Anthropic's terminal coding agent. It speaks the Messages API, and runs its own tools.

Plugboard options ​

One app for Claude Code, and aliases for the tiers it uses:

jsonc
"options": {
  "keys": { "claude-code": "{env:PLUGBOARD_KEY_CLAUDE_CODE}" },
  "models": ["anthropic/claude-haiku-4-5", "anthropic/claude-sonnet-4-6"],
  "aliases": {
    "fast": "anthropic/claude-haiku-4-5",
    "smart": "anthropic/claude-sonnet-4-6"
  }
}

Any model works, not only Claude: point the aliases at whatever your OpenCode server is signed in to.

Connect ​

sh
export ANTHROPIC_BASE_URL="http://127.0.0.1:4010"
export ANTHROPIC_AUTH_TOKEN="$PLUGBOARD_KEY_CLAUDE_CODE"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="fast"
export ANTHROPIC_DEFAULT_SONNET_MODEL="smart"
export ANTHROPIC_DEFAULT_OPUS_MODEL="smart"
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1

Then run claude.

  • The base URL has no /v1; Claude Code adds /v1/messages.
  • Set all three ANTHROPIC_DEFAULT_*_MODEL variables. The haiku tier also runs background calls (titles, summaries), and a name plugboard doesn't serve fails them with 404.

To keep the settings, put the same variables under env in ~/.claude/settings.json and chmod 600 the file, since it then holds the key :

json
{
  "env": {
    "ANTHROPIC_BASE_URL": "http://127.0.0.1:4010",
    "ANTHROPIC_AUTH_TOKEN": "<your app key>",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "fast",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "smart",
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "smart",
    "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
  }
}

For a script or CI, run Claude Code headless with claude -p. This is the call the example's runner makes:

ts
/**
 * The variables a plugboard setup needs, plus the ones that keep a scripted run quiet: no telemetry, error reports, updates or
 * other traffic that is not a model call. ANTHROPIC_BASE_URL has no /v1, because Claude Code adds `/v1/messages`.
 */
const connect = (baseUrl: string, key: string) => ({
  ANTHROPIC_BASE_URL: baseUrl,
  ANTHROPIC_AUTH_TOKEN: key,
  ANTHROPIC_DEFAULT_HAIKU_MODEL: "fast",
  ANTHROPIC_DEFAULT_SONNET_MODEL: "fast",
  ANTHROPIC_DEFAULT_OPUS_MODEL: "fast",
  CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1",
  DISABLE_TELEMETRY: "1",
  DISABLE_ERROR_REPORTING: "1",
  DISABLE_AUTOUPDATER: "1",
})

/** `claude -p`: one prompt, no questions. `--allowedTools` answers the permission prompts a headless run cannot. */
const headless = (prompt: string, model = "fast") => ["-p", prompt, "--model", model, "--allowedTools", "Write,Read,Agent", "--output-format", "stream-json", "--verbose"]
  • --allowedTools approves the tools a headless run cannot ask about. Add the ones your prompt needs.
  • CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, DISABLE_TELEMETRY, DISABLE_ERROR_REPORTING and DISABLE_AUTOUPDATER turn off the calls that are not model calls: telemetry, error reports and update checks.
  • Give the script its own HOME and CLAUDE_CONFIG_DIR, so it reads no ~/.claude settings and writes no session there.

All three files are in examples/claude-code/.

What works ​

Streaming, Claude Code's tools (returned to it as tool_use blocks, several in a row), sub-agents (each sub-agent makes its own /v1/messages call), compaction (/compact and auto-compaction ask the model for a summary and continue from it), extended thinking on models with a matching variant, structured outputs and token counting.

Limits ​

  • Claude Code sends its built-in tools plus every tool of each MCP server. Requests over maxTools (default 64) are refused with 400; raise maxTools if you add MCP servers.
  • For a non-Claude model, Claude Code prints claude-code:unrecognized_model and assumes a 200k context. Set CLAUDE_CODE_MAX_CONTEXT_TOKENS to the real window.
  • Anthropic server tools (web_search, code_execution) are refused with 400.
  • WebFetch checks each domain with api.anthropic.com; turn that off with skipWebFetchPreflight: true. CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 turns off Claude Code's other calls to Anthropic. Chat through plugboard works either way.