mirror of
https://github.com/dtzp555-max/ocp.git
synced 2026-07-21 21:15:09 +00:00
feat: v2.0.0 — on-demand spawning, session management, full tool access
Major architectural upgrade: - Replace pool system with on-demand spawning (eliminates crash loops, DEGRADED states, and stdin timeout errors from v1.x) - Add session management with --resume support (reduces token waste on multi-turn conversations) - Expand default allowed tools (Bash, Read, Write, Edit, Glob, Grep, WebSearch, WebFetch, Agent) with configurable CLAUDE_ALLOWED_TOOLS - Add system prompt pass-through (CLAUDE_SYSTEM_PROMPT) - Add MCP config support (CLAUDE_MCP_CONFIG) - Add concurrency control (CLAUDE_MAX_CONCURRENT, default 5) - Add periodic auth health monitoring - Add session API endpoints (GET/DELETE /sessions) - Improve /health with full diagnostics (stats, sessions, errors, config) - Fix timeout race condition (graceful SIGTERM → SIGKILL) - Fix ERR_HTTP_HEADERS_SENT by checking headersSent in all response helpers - Document coexistence with Claude Code interactive mode (Telegram, IDE) - No conflict with CC: different ports, protocols, and process models Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,13 +4,27 @@
|
||||
|
||||
A lightweight, zero-dependency proxy that lets [OpenClaw](https://github.com/openclaw/openclaw) agents talk to Claude through your existing subscription. One command to set up, one file to run.
|
||||
|
||||
**Why?**
|
||||
- **$0 API cost** — uses your Claude Pro/Max subscription, not pay-per-token API
|
||||
- **Zero dependencies** — single Node.js file, no `npm install`
|
||||
- **One command setup** — `node setup.mjs` handles everything
|
||||
- **OpenAI-compatible** — standard `/v1/chat/completions` endpoint
|
||||
- **All Claude models** — Opus 4.6, Sonnet 4.6, Haiku 4
|
||||
- **Streaming support** — real-time SSE responses
|
||||
## v2.0.0 — Major Upgrade
|
||||
|
||||
**What's new:**
|
||||
- **On-demand spawning** — eliminates the pool crash loops, DEGRADED states, and stdin timeout errors from v1.x. Each request spawns a fresh `claude -p` process with stdin written immediately. No more stale workers, no more backoff spirals.
|
||||
- **Session management** — multi-turn conversations use `--resume` to avoid resending full history. Reduces token waste and enables Claude Code's built-in context compression on long conversations.
|
||||
- **Full tool access** — expanded default tools (Bash, Read, Write, Edit, Glob, Grep, WebSearch, WebFetch, Agent). Configurable via `CLAUDE_ALLOWED_TOOLS` or bypass all checks with `CLAUDE_SKIP_PERMISSIONS=true`.
|
||||
- **System prompt pass-through** — set `CLAUDE_SYSTEM_PROMPT` to inject context into every request.
|
||||
- **MCP config support** — set `CLAUDE_MCP_CONFIG` to load MCP servers (Telegram, etc.) into claude -p calls.
|
||||
- **Concurrency control** — `CLAUDE_MAX_CONCURRENT` prevents runaway process spawning (default: 5).
|
||||
- **Auth health monitoring** — periodic `claude auth status` checks with status exposed on `/health`.
|
||||
- **Session API** — `GET /sessions` to list, `DELETE /sessions` to clear active sessions.
|
||||
- **Improved diagnostics** — `/health` endpoint shows stats, active sessions, recent errors, auth status, and full config.
|
||||
|
||||
**Coexistence with Claude Code interactive mode:**
|
||||
OCP and Claude Code (interactive/Telegram) run on completely different paths and can coexist on the same machine without conflict:
|
||||
- OCP: `localhost:3456` (HTTP) → spawns `claude -p` processes (per-request, stateless)
|
||||
- CC: MCP protocol (in-process) → persistent interactive session
|
||||
- No shared ports, no shared processes, no shared sessions
|
||||
|
||||
**Daemon advantage over CC:**
|
||||
OCP runs as a system daemon (launchd/systemd) that auto-starts on boot and auto-recovers from crashes. Unlike Claude Code interactive mode, OCP does not require a terminal session to stay open — it survives disconnects, reboots, and SSH drops. Combined with OpenClaw's memory system, this means your agents never lose continuity.
|
||||
|
||||
## How it works
|
||||
|
||||
@@ -22,7 +36,7 @@ The proxy translates OpenAI-compatible `/v1/chat/completions` requests into `cla
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Node.js** ≥ 18
|
||||
- **Node.js** >= 18
|
||||
- **Claude CLI** installed and authenticated (`claude login`)
|
||||
- **OpenClaw** installed
|
||||
|
||||
@@ -49,6 +63,33 @@ openclaw config set agents.defaults.model.primary "claude-local/claude-opus-4-6"
|
||||
openclaw gateway restart
|
||||
```
|
||||
|
||||
## Session Management (v2.0)
|
||||
|
||||
Multi-turn conversations can use sessions to avoid resending full message history on every request.
|
||||
|
||||
**How to enable:** Include a `session_id` or `conversation_id` field in your request body, or set the `X-Session-Id` / `X-Conversation-Id` header.
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "claude-opus-4-6",
|
||||
"session_id": "conv-abc-123",
|
||||
"messages": [
|
||||
{"role": "user", "content": "Hello"},
|
||||
{"role": "assistant", "content": "Hi there!"},
|
||||
{"role": "user", "content": "What did I just say?"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**First request** with a new session_id: all messages are sent, session is persisted via `--session-id`.
|
||||
**Subsequent requests** with the same session_id: only the latest user message is sent via `--resume`, reducing token consumption.
|
||||
|
||||
Sessions expire after 1 hour of inactivity (configurable via `CLAUDE_SESSION_TTL`).
|
||||
|
||||
**API endpoints:**
|
||||
- `GET /sessions` — list all active sessions
|
||||
- `DELETE /sessions` — clear all sessions
|
||||
|
||||
## Security
|
||||
|
||||
- **Localhost only** — the proxy binds to `127.0.0.1` and is not exposed to the internet or your local network
|
||||
@@ -123,105 +164,77 @@ openclaw gateway restart
|
||||
|
||||
| Model ID | Claude CLI model | Notes |
|
||||
|----------|-----------------|-------|
|
||||
| `claude-opus-4-6` | opus | Most capable, slower |
|
||||
| `claude-sonnet-4-6` | sonnet | Good balance of speed/quality |
|
||||
| `claude-haiku-4` | haiku | Fastest, lightweight |
|
||||
|
||||
## Authentication
|
||||
The proxy supports optional Bearer token authentication via the `PROXY_API_KEY` environment variable.
|
||||
|
||||
**When `PROXY_API_KEY` is set**, all requests (except `GET /health`) must include a valid `Authorization: Bearer <token>` header. Requests with a missing or invalid token receive a `401 Unauthorized` response.
|
||||
|
||||
**When `PROXY_API_KEY` is not set**, authentication is disabled and all requests are accepted (backwards compatible with v1.6.x and earlier).
|
||||
|
||||
For local Claude Max / OAuth usage, avoid exporting `ANTHROPIC_API_KEY` globally into the shell that launches the proxy. `v1.7.1` also sanitizes `ANTHROPIC_*` variables before spawning Claude subprocesses to reduce accidental auth-path pollution.
|
||||
|
||||
|
||||
The proxy supports optional Bearer token authentication via the `PROXY_API_KEY` environment variable.
|
||||
|
||||
**When `PROXY_API_KEY` is set**, all requests (except `GET /health`) must include a valid `Authorization: Bearer <token>` header. Requests with a missing or invalid token receive a `401 Unauthorized` response.
|
||||
|
||||
**When `PROXY_API_KEY` is not set**, authentication is disabled and all requests are accepted (backwards compatible with v1.6.x and earlier).
|
||||
|
||||
```bash
|
||||
# Start with auth enabled
|
||||
PROXY_API_KEY=my-secret-token node server.mjs
|
||||
|
||||
# Configure OpenClaw provider with the matching key
|
||||
# In openclaw.json, set apiKey under the claude-local provider:
|
||||
"claude-local": {
|
||||
"baseUrl": "http://127.0.0.1:3456/v1",
|
||||
"api": "openai-completions",
|
||||
"apiKey": "my-secret-token",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
The proxy logs auth status on startup: `Auth: enabled (PROXY_API_KEY set)` or `Auth: disabled (no PROXY_API_KEY)`.
|
||||
| `claude-opus-4-6` | claude-opus-4-6 | Most capable, slower |
|
||||
| `claude-sonnet-4-6` | claude-sonnet-4-6 | Good balance of speed/quality |
|
||||
| `claude-haiku-4` | claude-haiku-4-5-20251001 | Fastest, lightweight |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `CLAUDE_PROXY_PORT` | `3456` | Listen port |
|
||||
| `CLAUDE_BIN` | `claude` | Path to claude binary |
|
||||
| `CLAUDE_TIMEOUT` | `120000` | Request timeout (ms) |
|
||||
| `PROXY_API_KEY` | *(unset)* | Bearer token for API authentication; when unset, auth is disabled |
|
||||
| `CLAUDE_BIN` | *(auto-detect)* | Path to claude binary |
|
||||
| `CLAUDE_TIMEOUT` | `300000` | Request timeout (ms) |
|
||||
| `CLAUDE_ALLOWED_TOOLS` | `Bash,Read,...,Agent` | Comma-separated tools to pre-approve |
|
||||
| `CLAUDE_SKIP_PERMISSIONS` | `false` | Set `true` to bypass all permission checks |
|
||||
| `CLAUDE_SYSTEM_PROMPT` | *(empty)* | System prompt appended to all requests |
|
||||
| `CLAUDE_MCP_CONFIG` | *(empty)* | Path to MCP server config JSON file |
|
||||
| `CLAUDE_SESSION_TTL` | `3600000` | Session expiry in ms (default: 1 hour) |
|
||||
| `CLAUDE_MAX_CONCURRENT` | `5` | Max concurrent claude processes |
|
||||
| `PROXY_API_KEY` | *(unset)* | Bearer token for API authentication |
|
||||
|
||||
## API Endpoints
|
||||
|
||||
- `GET /v1/models` — List available models
|
||||
- `POST /v1/chat/completions` — Chat completion (streaming + non-streaming)
|
||||
- `GET /health` — Health check
|
||||
- `GET /health` — Comprehensive health check (stats, sessions, auth, config)
|
||||
- `GET /sessions` — List active sessions
|
||||
- `DELETE /sessions` — Clear all sessions
|
||||
|
||||
## Server / Advanced: Docker
|
||||
## Authentication
|
||||
|
||||
For server deployments or if you prefer Docker:
|
||||
The proxy supports optional Bearer token authentication via the `PROXY_API_KEY` environment variable.
|
||||
|
||||
**When `PROXY_API_KEY` is set**, all requests (except `GET /health`) must include a valid `Authorization: Bearer <token>` header. Requests with a missing or invalid token receive a `401 Unauthorized` response.
|
||||
|
||||
**When `PROXY_API_KEY` is not set**, authentication is disabled and all requests are accepted.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/dtzp555-max/openclaw-claude-proxy.git
|
||||
cd openclaw-claude-proxy
|
||||
cp .env.example .env # add your CLAUDE_SESSION_TOKEN / CLAUDE_COOKIES
|
||||
docker compose up -d
|
||||
# Start with auth enabled
|
||||
PROXY_API_KEY=my-secret-token node server.mjs
|
||||
```
|
||||
|
||||
Or as a single command if you already have a `.env` ready:
|
||||
## Architecture: v1 vs v2
|
||||
|
||||
```bash
|
||||
git clone https://github.com/dtzp555-max/openclaw-claude-proxy.git && cd openclaw-claude-proxy && docker compose up -d
|
||||
```
|
||||
| | v1.x (pool) | v2.0 (on-demand) |
|
||||
|---|---|---|
|
||||
| Process lifecycle | Pre-spawn idle workers | Spawn per request |
|
||||
| Crash handling | Backoff → DEGRADED → manual restart | No crash loops (no idle workers) |
|
||||
| Session support | None (stateless) | --resume with session tracking |
|
||||
| Tool access | 6 tools hardcoded | Configurable, expanded defaults |
|
||||
| System prompt | None | CLAUDE_SYSTEM_PROMPT env |
|
||||
| MCP support | None | CLAUDE_MCP_CONFIG env |
|
||||
| Concurrency | Unlimited (dangerous) | CLAUDE_MAX_CONCURRENT limit |
|
||||
| Auth monitoring | None | Periodic health checks |
|
||||
| Diagnostics | Basic /health | Full stats, sessions, errors |
|
||||
|
||||
Health check: `curl http://localhost:3456/health`
|
||||
## Coexistence with Claude Code
|
||||
|
||||
OCP and Claude Code interactive mode (including Telegram bots) are completely independent:
|
||||
|
||||
| | OCP (this proxy) | CC interactive |
|
||||
|---|---|---|
|
||||
| Protocol | HTTP (localhost:3456) | MCP (in-process) |
|
||||
| Process model | Per-request spawn | Persistent session |
|
||||
| Lifecycle | Daemon (auto-start, auto-recover) | Requires terminal |
|
||||
| Permission model | Pre-approved tools | Interactive prompts |
|
||||
| Use case | Automated agent work | Human-in-the-loop |
|
||||
|
||||
Both can run on the same machine simultaneously. No shared state, no port conflicts.
|
||||
|
||||
## Recovery after OpenClaw upgrade
|
||||
|
||||
OpenClaw upgrades (`npm update -g openclaw`) **do not overwrite** the user config at `~/.openclaw/openclaw.json`. However, if the claude-local models stop working after an upgrade, follow these steps:
|
||||
|
||||
### Quick diagnosis
|
||||
|
||||
```bash
|
||||
# 1. Check if proxy is running
|
||||
curl http://127.0.0.1:3456/health
|
||||
# Expected: {"status":"ok"}
|
||||
|
||||
# 2. Verify Claude CLI works
|
||||
claude -p "hello" --model sonnet --output-format text
|
||||
# Expected: text response
|
||||
|
||||
# 3. Verify OpenClaw config
|
||||
cat ~/.openclaw/openclaw.json | grep -A3 claude-local
|
||||
```
|
||||
|
||||
### Common issues and fixes
|
||||
|
||||
| Symptom | Cause | Fix |
|
||||
|---------|-------|-----|
|
||||
| Agent doesn't reply, no proxy logs | Gateway didn't load claude-local provider | Check `models.providers.claude-local` in `openclaw.json` |
|
||||
| Proxy reports `exit 1` | Claude CLI not logged in or token expired | Run `claude login` to re-authenticate |
|
||||
| `🔑 unknown` in `/status` | Normal — no API key, using OAuth | Does not affect functionality, safe to ignore |
|
||||
| `/status` shows Context 0% | Messages not reaching proxy (SSE format issue) | Ensure proxy is latest version with streaming support |
|
||||
| Gateway reports `invalid api type` | OpenClaw renamed API type in new version | Check `api` field is still valid (e.g., `openai-completions`) |
|
||||
| Proxy startup `EADDRINUSE` | Port 3456 already in use | `lsof -i :3456` to find and kill the old process |
|
||||
OpenClaw upgrades (`npm update -g openclaw`) **do not overwrite** the user config at `~/.openclaw/openclaw.json`. However, if the claude-local models stop working after an upgrade:
|
||||
|
||||
### One-command recovery
|
||||
|
||||
@@ -232,19 +245,12 @@ node setup.mjs # reconfigure OpenClaw + start proxy
|
||||
openclaw gateway restart
|
||||
```
|
||||
|
||||
### Pre-upgrade backup (recommended)
|
||||
|
||||
```bash
|
||||
cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Cost shows as $0 because billing goes through your Claude subscription
|
||||
- The `🔑` field in `/status` shows the configured auth key (or `unknown` if auth is disabled) — this is normal
|
||||
- Each request spawns a `claude -p` process; concurrent requests are supported
|
||||
- Each request spawns a `claude -p` process; concurrent requests are capped by `CLAUDE_MAX_CONCURRENT`
|
||||
- The proxy must run on the same machine as the Claude CLI (uses local OAuth)
|
||||
- The same Claude account can be used on multiple machines (shared usage quota)
|
||||
- Session data is stored by Claude CLI on disk; session map is in-memory (lost on proxy restart)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Reference in New Issue
Block a user