English | 简体中文
A high-fidelity multi-protocol reverse proxy bridging the Anthropic Messages API, OpenAI Responses API (for Codex CLI), and OpenAI Chat Completions API directly to cmdc (Command Code).
Written in Go with zero third-party dependencies, shipped as a single static binary. Downstream clients speaking Anthropic Messages (such as Claude Code and other CLI coding assistants), OpenAI Responses (such as Codex CLI), or OpenAI Chat Completions connect to this proxy. Requests are converted in a single hop (star topology with Anthropic Messages as the canonical internal representation) to the cmdc envelope format and forwarded upstream — preserving multi-modal images, thinking blocks, and cache markers (cache_control) — while reproducing the official CLI's client fingerprint and behavioral characteristics at the transport layer.
- Star Topology & Single-hop Conversion — Anthropic Messages (first-class citizen), OpenAI Responses (
/v1/responses), and OpenAI Chat Completions (/v1/chat/completions) all normalize directly into canonical formats without intermediary translation loss, forwarding to cmdc in a single hop. - Deep Codex CLI Compatibility — Native support for Codex custom tools, grammar definition hints, tool search discovery promotion, namespaced tools flattening/restoration, and strict Responses wire constraints (exact index zero preservation, mandatory arguments keys, array contents, reasoning item C# SDK safety).
- Robust Tool Pairing & Repair — Shared
merge → pair → mergealgorithm automatically repairs interleaved tool outputs, drops dangling/unanswered calls, strips orphan results with warnings, and enforces strict user/assistant alternation. - Full Multi-modal Support — User-message images (base64 / URL) pass through natively; images embedded inside
tool_resultblocks are automatically relocated and reconstructed. - Smart Cache Affinity — Native
cache_controlmarkers preserved; tail cache breakpoints synthesized when missing; combined with stable prefix-derived sessions to maximize Prompt Cache hit rates. - High-fidelity Client Masquerade — Win32 x64 device fingerprint persistence, scheduled lifecycle pre-requests, dynamic npm CLI version synchronization, W3C traceparent headers, and transport-layer alignment (forced HTTP/1.1 with suppressed User-Agent).
- Streaming & Non-streaming Consistency — Upstream is always streamed; a unified state machine drives both streaming SSE frames and aggregated JSON for each protocol with identical data semantics.
- Accurate Billing & Anti-overcharge — Native
noCacheTokensprioritized for deduplicated internal accounting; additive backfill for OpenAI prompt tokens (prompt = noCache + cache_read + cache_creation); zero-output abnormal responses surface as 429 withRetry-After.
Downstream Clients
├─ Claude Code / Anthropic SDK / CLI ──► POST /v1/messages
├─ Codex CLI ──► POST /v1/responses
└─ OpenAI SDK / Compatible Clients ──► POST /v1/chat/completions
│
▼
┌────────────────────────────────────────────────────────┐
│ cmdc2api Proxy (Star Topology) │
│ ├─ 1. Inbound Normalization (chatin / respin / msg) │
│ ├─ 2. Tool Pairing & Repair (merge → pair → merge) │
│ ├─ 3. Session Affinity (Header / Prefix Hash / Key) │
│ ├─ 4. Masquerade Check (Win32 Fingerprint / Version) │
│ ├─ 5. Envelope & Tail Cache Synthesis (BuildCcRequest)│
│ └─ 6. Outbound State Machine (SSE Encoders / Agg) │
└───────────────────────────┬────────────────────────────┘
│ Upstream HTTPS (HTTP/1.1, Empty UA, Win32 Headers)
▼
cmdc API (api.commandcode.ai)
Pre-built multi-arch images (linux/amd64 and linux/arm64):
docker compose up -d # ghcr.io/b1anyu/cmdc2api:latestOr run directly with Docker:
docker run -d \
--name cmdc2api \
-p 8050:8050 \
-e HOST=0.0.0.0 \
-v $(pwd)/data:/app/data \
ghcr.io/b1anyu/cmdc2api:latestgo build -o cmdc2api . && ./cmdc2apiThe server listens on 127.0.0.1:8050 by default. Authenticate using your cmdc account API Key (user_xxx), which is forwarded to the upstream unchanged.
curl http://127.0.0.1:8050/v1/messages \
-H "x-api-key: user_xxx" \
-H "content-type: application/json" \
-d '{
"model": "deepseek/deepseek-v4-flash",
"max_tokens": 1024,
"stream": true,
"messages": [{"role": "user", "content": "Hello"}]
}'Configure Codex to point to the proxy via environment variable or config file:
export CODEX_API_BASE="http://127.0.0.1:8050/v1"
export CODEX_API_KEY="user_xxx"
codexOr in ~/.codex/config.toml:
base_url = "http://127.0.0.1:8050/v1"
api_key = "user_xxx"curl http://127.0.0.1:8050/v1/chat/completions \
-H "Authorization: Bearer user_xxx" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek/deepseek-v4-flash",
"messages": [{"role": "user", "content": "Hello"}]
}'| Path | Method | Description |
|---|---|---|
/v1/messages, /messages |
POST |
Anthropic Messages endpoint (streaming SSE & non-streaming JSON) |
/v1/responses, /responses |
POST |
OpenAI Responses endpoint (optimized for Codex CLI, streaming SSE & non-streaming JSON) |
/v1/chat/completions, /chat/completions |
POST |
OpenAI Chat Completions endpoint (streaming SSE & non-streaming JSON) |
/v1/models, /models |
GET |
Model list (superset of Anthropic & OpenAI formats; forwarded upstream when authenticated) |
/health, / |
GET |
Health check endpoint |
Note on Base URL Compatibility: All protocol endpoints support both
/v1/*and non-prefix aliases (e.g./chat/completions). Downstream clients will work seamlessly whether their Base URL is configured ashttp://127.0.0.1:8050orhttp://127.0.0.1:8050/v1.
Authentication Headers:
- Supports
Authorization: Bearer user_xxxorx-api-key: user_xxxheaders. - Account API keys (typically in
user_xxxformat) are passed through to upstream cmdc unchanged without plaintext persistence.
| Variable | Default | Description |
|---|---|---|
PORT |
8050 |
HTTP listening port |
HOST |
127.0.0.1 |
HTTP listening address (use 0.0.0.0 in container environments) |
CC_API_BASE |
https://api.commandcode.ai |
cmdc upstream base API URL |
CC_STATE_FILE |
data/state.json |
Persistence path for device fingerprint and lifecycle throttle state |
CC_MAX_BODY_MB |
100 |
Inbound request body limit (in MB) |
CC_SESSION_STRATEGY |
prefix |
Session strategy: prefix (stable per conversation, recommended) / key (per-key, 12h+1h rotation) |
CC_CACHE_MARKERS |
respect |
Cache breakpoint strategy: respect (pass client markers through, tail synthesis when absent) / replace (strip markers and force tail synthesis for diagnostics) |
CC_ASSISTANT_REASONING |
1 |
Replay historical assistant thinking blocks upstream as {type: "reasoning"} (1 to enable, 0 to disable) |
CC_FAKE_NODE_VERSION |
v22.21.0 |
Node.js version reported in envelope's environment field |
CMD_ZDR |
0 |
Attach x-cmd-zdr: 1 header globally (route via ZDR only; overridable per request) |
CC_MODEL_REFRESH |
5m |
In-memory cache duration for the model list |
The cmdc envelope natively adheres to a messages-centric design (content as block arrays, tools defined with input_schema, Anthropic-style tool_choice).
cmdc2api establishes a star topology where Anthropic Messages serves as the canonical internal representation:
/v1/responsesand/v1/chat/completionsrequests are normalized directly into canonicaltypes.Requestform beforeBuildCcRequest.- Session affinity, prompt cache breakpoint synthesis, Win32 masquerading, and token usage accounting are shared transparently across all endpoints without code duplication.
- Outbound format differences are resolved strictly after
types.StreamEventgeneration through protocol-specificEventEncoderandEventAggregatorimplementations.
Anthropic and cmdc enforce strict invariants on tool execution history:
- Every
tool_resultmust immediately follow the assistant message containing the correspondingtool_use. - Every
tool_usemust be answered by a subsequent usertool_result. - User and assistant messages must strictly alternate.
Clients speaking OpenAI formats frequently violate these constraints by emitting interleaved tool results, orphan results, or sibling calls. The proxy's shared merge → pair → merge algorithm (translate/pairing.go) reconstructs correct pairings, drops unanswered calls and orphan results with observability logs, and restores valid alternating order.
Codex CLI expects strict conformances to the Responses specification:
- Wire Format: SSE events and items are constructed manually to defeat
omitemptyzero-omissions (ensuring indices likeoutput_index: 0are preserved). Function call arguments are non-optional keys (arguments: ""), messages have arraycontent: [], and reasoning items never contain fake IDs or nullstatus/contentfields (preventing C# SDK crashes). - Tool Hierarchy: Codex custom tools (
custom), tool search proxies (tool_search), and namespaced tools (namespace) are downgraded to standard functions upon ingress and restored on egress (fc_,ctc_,tsc_prefixes and namespacing). - Tool Search Discovery: Discovered tools in
tool_search_outputitems are promoted to full tool declarations dynamically.
cmdc's Prompt Cache operates at session granularity. The proxy orchestrates four tiers of cache affinity:
- Explicit Session Headers: If the request contains
x-session-id,x-claude-code-session-id, orsession_id(length ≥ 8), it is formatted and used as the upstream session ID. - Explicit Client Cache Key (
prompt_cache_key): OpenAI Chat / Responses clients can explicitly declareprompt_cache_key(length ≥ 8), taking precedence over derived heuristics. - Prefix Derivation (Default): In the absence of explicit identifiers, a stable UUID-formatted session ID is calculated from
sha256(system + tools + first_user_message). Conversations reuse the exact same upstream session across turns, automatically rotating only when system prompts, toolsets, or compressed contexts change. - Content-level & Tail Cache Breakpoints:
- Native
cache_controlannotations on content blocks (includingttl) pass through unchanged. - Breakpoints on
systemandtoolsare folded into a synthesized marker on the very last text part of the envelope (scanned backwards from the entire conversation tail across tool turns), ensuring cached prefix coverage over all prior history.
- Native
Mirrors the observable characteristics of the official Node CLI:
- Fingerprint Continuity: Persists generated Windows x64 device components to disk, avoiding anti-abuse triggers caused by frequent restarts.
- Lifecycle Heartbeats: Periodically dispatches
/alpha/fingerprint/recordand/alpha/lifecycle-eventsrequests on an 8h + 2h jittered schedule. - Dynamic CLI Version: Queries the npm registry every 24 hours to sync the latest release version into
x-command-code-version. - Transport Alignment: Enforces HTTP/1.1 connections and suppresses the default Go
User-Agentheader to match Node.jsundiciclient behavior.
Empirical verification revealed that cmdc upstream's inputTokens accumulates cached reads across internal loop steps (approximately 2× console totals). The proxy prioritizes upstream's native noCacheTokens when available, falling back to:
input_tokens = max(0, inputTokens - cachedInputTokens)
For OpenAI Responses and Chat Completions endpoints (where prompt_tokens represents the total prompt size including cache hits), usage is backfilled additively:
prompt_tokens = input_tokens (noCache) + cache_read (+ cache_creation)
cached_tokens = cache_read
total_tokens = prompt_tokens + output_tokens
- System Prompt Format: cmdc strictly enforces
params.systemas a plain string (array payloads are rejected with HTTP 400). Structured system blocks are concatenated into text, with cache markers mapped to the tail. - Thinking Signature Deterministic Forgery: Because third-party proxies cannot mint official cryptographic signatures, signatures are deterministically generated via
0x12+ sha256 prefix, ensuring stable signatures for identical thinking blocks while passing client-side shallow validation. Responses egress sends forged signatures viaencrypted_contentfor Codex CLI replay, which are safely parsed back to plain thinking blocks and stripped before forwarding upstream. - Unsupported Inbound Fields: Fields without upstream counterparts are safely dropped with logs (e.g.
stop_sequences,top_k,metadata.user_id, andtool_result.is_error). Responses and Chat endpoints also reject unsupported features likeprevious_response_idandn > 1with explicit 400 errors.
internal/
├── config/ # Environment-driven runtime configuration
├── errs/ # Error mapping and classification
├── masq/ # Client masquerading: fingerprint, session store, npm version, upstream client
├── server/ # HTTP server layer: routes, shared pipeline, CORS middleware, handlers (messages, chat, responses, models)
├── translate/ # Protocol translation: inbound normalization (chatin, respin), outbound encoders/aggregators (chatout, respout), pairing repair, stream translator
└── types/ # Protocol data structures (Anthropic, OpenAI Chat, OpenAI Responses, cmdc envelopes & events)
Running tests locally:
go test -race ./... # Unit & end-to-end tests (with built-in mock upstream)
go vet ./...- Protocol analysis and client masquerade mechanics inspired by commandcode-proxy (MIT).
- Architecture techniques and streaming state-machine designs referenced from the
apicompatpackage of sub2api (LGPL-3.0).
This project is licensed under the MIT License.
This project is provided for educational and technical research purposes only. Users are solely responsible for ensuring compliance with applicable laws, regulations, and third-party service terms. The authors assume no liability for any consequences arising from the use of this project.