Routes OpenClaw agent requests through Claude Code — so your agents get full tool use, file editing, and multi-step reasoning via an OpenAI-compatible HTTP server backed by the claude CLI.
Works on macOS and Linux (Ubuntu 22.04+).
Use at your own risk. Personal experiment, shared as-is. No warranty. Review the code before running it on anything you care about. Built with Claude Opus 4.6 — audit accordingly.
- ✅ OpenClaw installed and running (get it here)
- ✅ Python 3.11+ (download)
- ✅ Node.js 20+ (download)
- ✅ Claude Code — install and authenticate:
Then either set
npm install -g @anthropic-ai/claude-code
ANTHROPIC_API_KEYin your environment, or runclaude login(works with any Claude plan, but a Claude Max subscription is advised).
git clone https://github.com/0xD-Fabio/openclaw-claude-code-adapter.git
cd openclaw-claude-code-adapter
bash setup.shThe script checks dependencies, asks ~6 questions (all have sensible defaults — press Enter to accept), shows you a summary, and waits for y before changing anything.
Your OpenClaw agents are now using Claude Code.
| What | Where |
|---|---|
| Health check | http://127.0.0.1:8080/health |
| Logs | ~/.openclaw/logs/claude-code-adapter.log |
| Error logs | ~/.openclaw/logs/claude-code-adapter.err.log |
The setup script prints the exact undo command at the end. You can also run it manually:
openclaw config set --json agents.defaults.model '"<your-previous-model-id>"'Health check doesn't load.
Run tail -20 ~/.openclaw/logs/claude-code-adapter.err.log. Most likely cause: Claude Code isn't installed or isn't logged in. Check with claude --version.
"Port 8080 is already in use."
Re-run bash setup.sh and enter a different port (e.g. 8081), or stop whatever is using 8080.
Agents stopped responding.
Open http://127.0.0.1:8080/health. If it doesn't load, check the error log. If you need to recover quickly, run the undo command above.
Setup failed partway through.
Safe to re-run bash setup.sh — it overwrites the previous attempt cleanly.
No inbound authentication. The adapter binds to 127.0.0.1 only, so only local processes can reach it. That's the only protection.
If you ever expose this port via port forwarding, reverse proxy, or any network tunnel — anyone who can reach it has full access to your Claude Code session. Don't do that without adding your own auth layer first.
For developers who want to understand the internals, do a manual install, or integrate with OpenClaw by hand.
The adapter is a small Python HTTP server (FastAPI) that implements the OpenAI chat completions API. When a request arrives, it derives a stable agent_id from the SHA-256 hash of the system prompt, then starts or resumes a claude CLI session via the claude-agent-sdk-python SDK. Each agent gets its own isolated workspace directory and its own persistent session, stored in a local SQLite database so sessions survive adapter restarts.
cd openclaw-claude-code-adapter
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
python -m adapter.mainServer starts on http://127.0.0.1:8080.
| Variable | Default | Description |
|---|---|---|
ADAPTER_HOST |
0.0.0.0 |
Bind address |
ADAPTER_PORT |
8080 |
Listen port |
ADAPTER_CLAUDE_MODEL |
claude-sonnet-4-6 |
Model passed to Claude Code |
ADAPTER_CLAUDE_CLI_PATH |
(auto-detect) | Absolute path to the claude binary |
ADAPTER_WORKSPACE_DIR |
/tmp/claude-adapter |
Working directory for Claude Code sessions |
ADAPTER_DB_PATH |
./adapter_sessions.db |
SQLite file for session persistence |
ADAPTER_REQUEST_TIMEOUT_SECONDS |
120 |
Per-request timeout before a 504 is returned |
ADAPTER_LOG_LEVEL |
INFO |
Python log level (DEBUG, INFO, WARNING, ERROR) |
If you prefer to configure OpenClaw by hand instead of using setup.sh:
openclaw config set --json models.providers.claude-code \
'{"baseUrl":"http://127.0.0.1:8080/v1","apiKey":"local-adapter","api":"openai-completions","models":[
{"id":"claude-opus-4-6","name":"Claude Opus 4.6 (via Code Adapter)","reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":200000,"maxTokens":16384},
{"id":"claude-sonnet-4-6","name":"Claude Sonnet 4.6 (via Code Adapter)","reasoning":false,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":200000,"maxTokens":8192},
{"id":"claude-haiku-4-5-20251001","name":"Claude Haiku 4.5 (via Code Adapter)","reasoning":false,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":200000,"maxTokens":8192}
]}'openclaw config set --json agents.defaults.model '"claude-code/claude-sonnet-4-6"'Or with a fallback:
openclaw config set --json agents.defaults.model \
'{"primary":"claude-code/claude-sonnet-4-6","fallbacks":["anthropic/claude-sonnet-4"]}'openclaw gateway restartsetup.sh handles systemd automatically. The template below is for fully manual installs only.
Create ~/.config/systemd/user/claude-code-adapter.service:
[Unit]
Description=Claude Code Adapter
After=network.target
[Service]
Type=simple
ExecStart=/path/to/claude-code-adapter/.venv/bin/python -m adapter.main
WorkingDirectory=/path/to/claude-code-adapter
Restart=always
RestartSec=5
StandardOutput=append:/home/<user>/.openclaw/logs/claude-code-adapter.log
StandardError=append:/home/<user>/.openclaw/logs/claude-code-adapter.err.log
Environment="HOME=/home/<user>"
Environment="PATH=/usr/local/bin/claude:/usr/local/bin:/usr/bin:/bin"
Environment="ADAPTER_HOST=127.0.0.1"
Environment="ADAPTER_PORT=8080"
Environment="ADAPTER_CLAUDE_CLI_PATH=/usr/local/bin/claude"
Environment="ADAPTER_WORKSPACE_DIR=/home/<user>/.openclaw/workspace"
Environment="ADAPTER_DB_PATH=/home/<user>/.openclaw/adapter-sessions.db"
Environment="ADAPTER_CLAUDE_MODEL=claude-sonnet-4-6"
Environment="ADAPTER_LOG_LEVEL=INFO"
Environment="ADAPTER_REQUEST_TIMEOUT_SECONDS=180"
[Install]
WantedBy=default.targetReplace /path/to/claude-code-adapter and <user> with your actual paths, then:
systemctl --user daemon-reload
systemctl --user enable --now claude-code-adapter| Method | Path | Description |
|---|---|---|
POST |
/v1/chat/completions |
OpenAI-compatible completions. Supports stream: true (SSE) and stream: false (JSON). |
GET |
/health |
Returns {"status":"ok","sessions":<count>,"models":[...]} |
GET |
/v1/models |
Returns configured models in OpenAI list format |
DELETE |
/v1/sessions/{agent_id} |
Kills all Claude Code processes for the agent and deletes the session record, forcing a fresh session on the next request. |
POST /v1/chat/completions — key fields:
model(required) — one ofclaude-opus-4-6,claude-sonnet-4-6,claude-haiku-4-5-20251001messages(required) — array of{role, content}objectsstream(optional, defaultfalse) — set totruefor SSE streaminguser(optional) — fallback for agent ID derivation when no system prompt is present
-
Session drops. A Claude Code session may terminate mid-conversation (internal CLI timeout, resource pressure, or a CLI update). The adapter starts a fresh session automatically on the next request, but prior context is lost.
-
Model ID passthrough. The adapter forwards the
modelfield directly to the CLI. If OpenClaw sends a provider-prefixed ID likeclaude-code/claude-sonnet-4-6, the CLI may reject it. Make sure the model IDs in your OpenClaw provider config match what Claude Code expects (claude-sonnet-4-6,claude-opus-4-6, etc.).