ccproxy is a Claude Code plugin with 2 hand-picked skills, indexed on Flowy in the Debugging category.
$ npx -y skills add starbaser/ccproxy --agent claude-code
ccproxy — CLI Proxy ccproxy is a transparent network interceptor for LLM tooling and AI harnesses,
built on mitmproxy and WireGuard with full TLS inspection and Wireshark keylog
export. Originally purpose-built for Claude Code, ccproxy now works with any LLM
client: Aider, Cursor, OpenAI SDK, or anything else that speaks HTTP. It jails a
process inside a rootless WireGuard namespace, intercepts at the network layer,
and feeds it through a DAG-driven pipeline that can decompose, transform, and
re-route traffic between providers.
Cross-provider request and response transformation is handled by lightllm, a
surgical adapter and streaming-FSM layer inside ccproxy — no LiteLLM proxy
subprocess, no gateway server.
New in 2.0: Codex/OpenAI Responses support with packaged request shaping,
plus DeepSeek V4 routing for Anthropic-format requests through DeepSeek's
/anthropic/v1/messages endpoint. See Configuration for
the routing setup.
The hook pipeline is your extension point for building mods and taking control of your LLM usage while respecting terms of service:
/mcp endpoint, and experimental
tasks
support.Feedback and contributions welcome — open an issue or submit a PR.
| Platform | Reverse proxy (ccproxy start) | WireGuard namespace jail (ccproxy run --capture) |
|---|---|---|
| Linux | ✅ | ✅ |
| Windows (WSL2) | ✅ | ✅ |
| macOS | ✅ | ❌ — requires Linux namespaces |
WSL2 is fully supported because it is Linux. Native Windows is not — use WSL2.
On macOS, the reverse proxy listener (ccproxy start + SDK use) works fine, but
the namespace jail (ccproxy run --capture) requires Linux kernel features
(unprivileged user/net namespaces, slirp4netns, iptables NAT) that have no
macOS equivalent.
The recommended Windows install is the ccproxy.wsl distro artifact. It is
built on NixOS-WSL and includes ccproxy plus the Linux namespace tools required
by ccproxy run --capture.
# Requires Store WSL 2.4.4 or newer.
wsl --update
wsl --version
wsl --install --from-file ccproxy.wsl
wsl -d ccproxy
Inside the distro:
ccproxy init
ccproxy start
ccproxy namespace status --json
ccproxy namespace doctor --json
Tier 1 Windows support is Windows 11 22H2+ with Store-distributed WSL2, systemd enabled, and mirrored networking recommended. Windows 10 and older WSL networking are best-effort. WSL1 and native Windows without WSL are unsupported.
Advanced users can still use Ubuntu on WSL2 with systemd and Nix, but the release artifact is the primary out-of-box path.
The WireGuard namespace jail needs a small set of system tools on PATH:
slirp4netns, wireguard-tools (wg), iproute2 (ip), iptables,
util-linux (unshare, nsenter), and procps (sysctl).
# Debian / Ubuntu
sudo apt update
sudo apt install -y slirp4netns wireguard-tools iproute2 iptables procps
# Fedora
sudo dnf install -y slirp4netns wireguard-tools iproute iptables-nft procps-ng
# Arch
sudo pacman -S slirp4netns wireguard-tools iproute2 iptables procps-ng
# NixOS — provided via the project devShell (`nix develop`)
Then install ccproxy:
# Recommended: uv tool (isolated venv, console scripts on PATH)
uv tool install ai-ccproxy
# Alternative: pip
pip install ai-ccproxy
On Ubuntu 24.04+, unprivileged user namespaces are restricted by AppArmor by default. Either run once:
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
…or add a path-scoped AppArmor profile (see rootless-containers/rootlesskit).
Only the reverse proxy is supported. No system packages are required.
uv tool install ai-ccproxy
# or
pip install ai-ccproxy
ccproxy start and SDK use (ANTHROPIC_BASE_URL=http://localhost:4000) work
the same as on Linux. ccproxy run --capture will fail fast with a clear error
listing the missing Linux-only tools.
ccproxy --help
ccproxy init
ccproxy status --proxy --inspect # exit 3 = both down (expected, nothing running yet)
# Initialize ccproxy.yaml + LiteLLM-compatible config.yaml
ccproxy init
# Start the proxy and inspector stack (foreground)
ccproxy start
SDK use: point any OpenAI-compatible client at the reverse proxy listener:
export ANTHROPIC_BASE_URL=http://localhost:4000
claude -p "hello"
Transparent capture: run a command inside the WireGuard namespace jail (all traffic intercepted):
ccproxy run --capture -- claude -p "hello"
Traffic enters through one of two listeners, passes through a fixed three-stage addon chain, and exits directly to the provider API.
flowchart TD
subgraph Listeners
RP["Reverse Proxy :4000"]
WG["WireGuard CLI"]
end
RP --> Chain
WG --> Chain
subgraph Chain["Addon Chain"]
IN["inbound<br/>DAG hooks"] --> TX["transform<br/>lightllm"] --> OUT["outbound<br/>DAG hooks"]
end
Chain --> API["Provider API"]
Addon chain (fixed order):
ReadySignal → InspectorAddon → FingerprintCaptureAddon → MultiHARSaver → ShapeCaptureAddon → inbound DAG → transform → outbound DAG → TransportOverrideAddon → AuthAddon → GeminiAddon → PerplexityAddon → EgressSanitizerAddon
AuthAddon and GeminiAddon sit after the outbound pipeline so they see
ccproxy-finalized requests/responses. AuthAddon owns 401-detect → refresh →
replay. GeminiAddon owns Gemini capacity fallback (sticky retry + fallback
chain on 429/503) and cloudcode-pa envelope unwrapping.
lightllm converts request and response bodies through ccproxy's own
adapter layer and streaming FSMs. URL rewriting and auth injection are owned by
the inspector route and Provider config, while lightllm owns wire-format
conversion. LiteLLM itself is not a runtime dependency: sibling config.yaml
model declarations are compiled into ccproxy-native bindings before requests
enter this path.
SSE streaming: SSEPipeline handles cross-provider streaming by parsing
SSE events into ccproxy's response IR and rendering each chunk back to the
listener's wire format.
ccproxy init writes sibling ccproxy.yaml and config.yaml templates under
~/.config/ccproxy/. Both are also discovered beneath
$CCPROXY_CONFIG_DIR.
ccproxy.yaml owns native runtime services: providers, authentication,
hooks, inspection, shaping, and explicit transform overrides.config.yaml is a LiteLLM-compatible frontend for model definitions,
aliases, endpoints, credentials, metadata, and supported request defaults.The frontend compiles into the existing CCProxyConfig/Provider runtime; it
does not restore LiteLLM's proxy process or router. Routing precedence is
explicit lightllm.transforms, exact then wildcard compiled model bindings,
sentinel-selected providers, then no match. See
Configuration for the supported compatibility subset
and trust-boundary rules.
ccproxy.yaml:
ccproxy:
port: 4000
# Provider entries keyed by sentinel suffix. The sentinel key
# sk-ant-oat-ccproxy-{name} resolves to providers[name] for token
# injection and routing.
providers:
anthropic:
auth:
type: command
command: "jq -r '.claudeAiOauth.accessToken' ~/.claude/.credentials.json"
base_url: https://api.anthropic.com
path: /v1/messages
type: anthropic
deepseek:
auth:
type: command
command: "printenv DEEPSEEK_API_KEY"
header: x-api-key
base_url: https://api.deepseek.com
path: /anthropic/v1/messages
type: anthropic
hooks:
inbound:
- ccproxy.hooks.inject_auth
- ccproxy.hooks.extract_session_id
outbound:
- ccproxy.hooks.gemini_cli
- ccproxy.hooks.pplx_stamp_headers
- ccproxy.hooks.inject_mcp_notifications
- ccproxy.hooks.verbose_mode
- ccproxy.hooks.shape
- ccproxy.hooks.commitbee_compat
lightllm:
# Optional regex-matched override rules layered on top of the
# sentinel-driven providers map. Default is empty: most routing
# comes from `providers` via inject_auth's sentinel detection.
transforms:
- match_path: ^/v1/chat/completions
match_model: ^gpt-4o
action: transform
dest_provider: anthropic
dest_model: claude-haiku-4-5-20251001
Transform matching: match_host (optional regex, checked against
pretty_host + Host header + X-Forwarded-Host), match_path (regex,
default .*), match_model (regex, optional). First match wins.
Three actions: redirect (default — rewrite destination, preserve body),
transform (cross-format via lightllm), passthrough (forward unchanged).
Auth resolves through dest_provider → providers[name].
Provider.auth dispatches on type:. Two static loaders return whatever the
underlying source holds; OAuth loaders own the refresh lifecycle in-process.
type | What it is | When to use |
|---|---|---|
command | Run a shell command, return stdout | Static API keys, opnix/SOPS secret commands, env-var injection |
file | Read a file, return contents | Static API keys stored in a managed secret file |
anthropic_oauth | In-process Anthropic OAuth refresh | Share ~/.claude/.credentials.json with Claude Code CLI |
google_oauth | In-process Google/Gemini OAuth refresh | Share ~/.gemini/oauth_creds.json with gemini-cli |
codex_oauth | In-process Codex OAuth refresh | Share ~/.codex/auth.json with Codex CLI |
command and file are not OAuth — they have no expiry awareness and never
call out to a refresh endpoint. ccproxy reads them on every resolve; rotation
happens out-of-band through whichever secret manager produced the value.
anthropic_oauth and google_oauth extend the same form-encoded
AuthSource base. codex_oauth follows Codex's ChatGPT auth-file schema: it
reads ~/.codex/auth.json, refreshes JWT access tokens through OpenAI's OAuth
endpoint, atomically writes the updated token envelope, and stamps companion
ChatGPT-Account-ID / X-OpenAI-Fedramp headers derived from the same file.
A static API key for DeepSeek alongside an OAuth-refresh entry for Anthropic:
ccproxy is a Claude Code plugin with 2 hand-picked skills, indexed on Flowy in the Debugging category. Install it with the command on its page. It includes using-ccproxy-api, using-ccproxy-inspector. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it