# ๐ญ Setting Up Claude Code Agent with 9Router: Free Anthropic-Compatible Inference
**Date:** July 16, 2026
**Tags:** AI, Claude Code, 9Router, Coding Agent, Self-Hosted, MCP, AI Agents
---
## ๐ฏ Overview
[Claude Code](https://github.com/anthropics/claude-code) is Anthropic's terminal **AI coding agent**. Out of the box it expects the official Anthropic API โ but it can be pointed at **any Anthropic-compatible endpoint** by overriding two environment variables. That's exactly how we run it for **free** through **9Router**, our LAN model router that exposes an Anthropic-compatible Messages API at `/v1/messages`.
This guide focuses on the **9Router integration**: Claude Code becomes a *first-class coder* in the stack without paying per token, auto-rotating through 9Router's free models (including `Free`, the default we pin).
### Why Claude Code + 9Router?
| Feature | Benefit |
|---------|---------|
| **๐ธ Free** | 9Router serves Anthropic-compatible models at no cost |
| **๐ Drop-in** | Only two env vars to override (`ANTHROPIC_BASE_URL`, `ANTHROPIC_API_KEY`) |
| **๐ Auto-rotate** | 9Router picks healthy free models automatically |
| **๐ OpenRouter Fallback** | One `OPENROUTER_API_KEY` for paid overflow |
| **๐ MCP Ready** | GBrain + any MCP server |
| **๐ง Reasoning** | `NINE_ROUTER_ENABLE_REASONING=true` |
---
## ๐๏ธ Architecture Overview
```
Terminal / Telegram / tmux
โ
โผ
claude (coding agent)
env: ANTHROPIC_BASE_URL=http://192.168.51.115:20128/v1
env: ANTHROPIC_API_KEY=
env: model=Free
โ
โผ
9Router http://192.168.51.115:20128/v1/messages
(Anthropic-compatible Messages API, free models)
โ
claude โโ MCP โโโบ GBrain (shared memory / Postgres)
```
---
## ๐ Prerequisites
- Linux VM with the Claude Code CLI installed (binary at `~/.local/bin/claude`).
- A running **9Router** (see the [9Router guide](/blog/9router-setup/)) exposing `/v1/messages`.
- (Optional) GBrain MCP server for shared memory.
- A non-root user (`ryan` in examples).
> โ ๏ธ **Security note:** Every secret below is a ``. Never commit real keys.
---
## ๐ฆ Step 1 โ Install Claude Code
```bash
# Claude Code installs as a global CLI; on this VM:
# /home/ryan/.local/bin/claude ->
# /home/ryan/.local/share/claude/versions//claude
# Verify
which claude
claude --version
```
---
## โ๏ธ Step 2 โ Point Claude Code at 9Router (the core trick)
Claude Code reads two env vars to locate its API. Override them to hit 9Router's Anthropic-compatible endpoint:
```bash
# The two variables that make it work:
export ANTHROPIC_BASE_URL="http://192.168.51.115:20128/v1"
export ANTHROPIC_API_KEY=""
# Optional: enable 9Router reasoning passthrough
export NINE_ROUTER_ENABLE_REASONING="true"
# Optional: OpenRouter fallback key
export OPENROUTER_API_KEY=""
# Pin the model Claude Code requests
export CLAUDE_CODE_MODEL="Free" # or pass --model Free
```
These can be baked into Claude Code's `settings.json` so they apply automatically:
```json
// ~/.claude/settings.json (sanitized)
{
"env": {
"PATH": "/home/ryan/.bun/bin:/home/ryan/.local/bin:/usr/local/bin:/usr/bin:/bin",
"ANTHROPIC_BASE_URL": "http://192.168.51.115:20128/v1",
"ANTHROPIC_API_KEY": "",
"NINE_ROUTER_ENABLE_REASONING": "true",
"OPENROUTER_API_KEY": ""
},
"effortLevel": "medium",
"theme": "dark",
"model": "Free"
}
```
> ๐ก With `ANTHROPIC_BASE_URL` set, Claude Code sends its `POST /v1/messages` calls to 9Router instead of `api.anthropic.com` โ fully transparent to the agent.
---
## ๐งฉ Step 3 โ Env Helper Scripts
Two helper scripts on this VM manage the 9Router wiring. The preferred one reads the key from the central env file (no hardcoded secret):
```bash
# ~/.claude/ninerouter-env.sh (preferred โ reads key from ~/.hermes/.env)
if [ -f "$HOME/.hermes/.env" ]; then
NINEROUTER_API_KEY="$(python3 - <<'PY'
from pathlib import Path
for line in Path('/home/ryan/.hermes/.env').read_text().splitlines():
if line.startswith('NINE_ROUTER_API_KEY='):
print(line.split('=', 1)[1].strip().strip('"'))
PY
)"
fi
export ANTHROPIC_BASE_URL="http://192.168.51.115:20128/v1"
export ANTHROPIC_API_KEY="$NINEROUTER_API_KEY"
export NINE_ROUTER_ENABLE_REASONING="true"
```
```bash
# ~/.claude/start-claude-9router.sh (launches claude with 9Router env)
#!/usr/bin/env bash
source /home/ryan/.claude/9router-env.sh
export ANTHROPIC_BASE_URL ANTHROPIC_API_KEY NINE_ROUTER_ENABLE_REASONING OPENROUTER_API_KEY
exec claude "$@"
```
Launch a long-lived session:
```bash
# From tmux / Telegram bridge
source /home/ryan/.claude/9router-env.sh
claude --dangerously-skip-permissions
```
> ๐ Prefer `ninerouter-env.sh` over the variant that hardcodes the key in the script. Keep secrets in `~/.hermes/.env`, not inline.
---
## ๐งฉ Step 4 โ Wire GBrain via MCP
Claude Code supports MCP servers via `~/.claude/mcp.json` (same GBrain server as the other agents):
```json
{
"mcpServers": {
"gbrain": {
"command": "/home/ryan/.bun/bin/gbrain",
"args": ["serve"],
"env": {
"GBRAIN_DATABASE_URL": "",
"GBRAIN_DIRECT_DATABASE_URL": ""
}
}
}
}
```
Verify:
```bash
/home/ryan/.bun/bin/gbrain get_health
# -> healthy
```
---
## ๐ Step 5 โ Usage
```bash
# Interactive session (env already sourced)
claude
# One-shot (non-interactive) with a prompt
claude -p "Refactor src/auth.py to use env vars instead of hardcoded config"
# Pin a model explicitly
claude --model Free
# Skip permission prompts for long-lived/automation sessions
claude --dangerously-skip-permissions
```
---
## ๐งช Step 6 โ Smoke Test
```bash
# 1. Claude binary resolves
which claude
# 2. Env points at 9Router
echo "$ANTHROPIC_BASE_URL" # -> http://192.168.51.115:20128/v1
# 3. 9Router reachable with key (placeholder)
curl -s --max-time 8 -H "Authorization: Bearer " \
http://192.168.51.115:20128/v1/models | head -c 200
# 4. A trivial Claude call works (uses ANTHROPIC_BASE_URL)
claude -p "Say: claude online via 9router"
# 5. GBrain MCP healthy
/home/ryan/.bun/bin/gbrain get_health
```
Expected: `/v1/models` returns JSON, Claude prints `claude online via 9router`, GBrain is healthy.
---
## ๐ฉบ Troubleshooting
| Symptom | Likely cause | Fix |
|---------|-------------|-----|
| Claude hits `api.anthropic.com` | `ANTHROPIC_BASE_URL` not set | `export ANTHROPIC_BASE_URL=http://192.168.51.115:20128/v1` |
| 401 from 9Router | Wrong/expired key | Re-source `ninerouter-env.sh`, re-test `/v1/models` |
| `model not found` | Model ID not served by 9Router | Use `Free` or check `/v1/models` |
| MCP tools missing | gbrain down / bad env | `gbrain get_health`, fix `` |
| Reasoning ignored | Flag off | Set `NINE_ROUTER_ENABLE_REASONING=true` |
---
## ๐ Security Checklist
- [ ] `ANTHROPIC_API_KEY` is `` (the 9Router key), injected via env, never committed.
- [ ] Prefer `ninerouter-env.sh` (reads from `~/.hermes/.env`) over any script that hardcodes the key.
- [ ] `OPENROUTER_API_KEY` is a ``, used only as fallback.
- [ ] GBrain Postgres URLs are placeholders; DB user is least-privilege.
- [ ] `--dangerously-skip-permissions` only for trusted automation sessions.
---
## โ
Summary
You now have **Claude Code** running on **9Router** for free:
- Installed as a global CLI (`~/.local/bin/claude`).
- **Anthropic-compatible endpoint override**: `ANTHROPIC_BASE_URL=http://192.168.51.115:20128/v1` + `ANTHROPIC_API_KEY=`.
- Model pinned to `Free`; reasoning enabled via `NINE_ROUTER_ENABLE_REASONING=true`.
- Helper scripts (`ninerouter-env.sh`, `start-claude-9router.sh`) for clean launches + OpenRouter fallback.
- Connected to **GBrain** via MCP for shared memory across all agents.
Claude Code rounds out the coding roster alongside [Pi](/blog/pi-coding-agent-setup/), [OpenCode](/blog/opencode-agent-setup/), and [Codex](/blog/codex-agent-setup/) โ all behind [OpenClaw](/blog/openclaw-setup/) (gateway), orchestrated with [Hermes](/blog/hermes-setup/), leaning on [9Router](/blog/9router-setup/) for inference. ๐
---
*No API keys, tokens, or secrets are included in this guide โ every value is a `` you supply locally. Built with Astro, GitHub, and Cloudflare Pages.*