Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Operates the ccproxy inspector MITM system for intercepting, inspecting, and transforming LLM API traffic. Covers running CLI tools through the reverse proxy or permissive WireGuard namespace capture path, checking namespace status and doctor output, inspecting flows with client-vs-forwarded request comparison, understanding the inbound/transform/outbound pipeline, capturing and auditing shape artifacts, applying the privacy guide, and diagnosing flow issues. Use when running CLI applications th
.claude/skills/starbaser-using-ccproxy-inspector/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 55% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 47% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 82% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 119% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 59% | 0% |
The inspector intercepts LLM API traffic through mitmproxy and routes accepted flows through the ccproxy addon chain:
InspectorAddon -> FingerprintCaptureAddon -> MultiHARSaver -> ShapeCaptureAddon
-> inbound DAG -> transform router -> outbound DAG
-> TransportOverrideAddon -> AuthAddon -> GeminiAddon
-> PerplexityAddon -> EgressSanitizerAddonUse the using-ccproxy-api skill for provider auth, sentinel keys, SDK base URL configuration, native ccproxy.yaml setup, and sibling config.yaml model routing when applicable.
The ccproxy plugin does not install or register the ccproxy FastMCP server for the user. If an MCP-aware client should use ccproxy's flow-inspection tools, the user must add their own MCP server config pointing at the running daemon's http://127.0.0.1:<mcp-port>/mcp endpoint and supply its bearer token when configured. Keep plugin installation separate from MCP server registration.
Before debugging a flow, establish which process and config directory are in play:
bashccproxy status ccproxy status --json ccproxy status --proxy --inspect --mcp
For namespace work, also inspect the transparent capture path:
bashccproxy namespace status ccproxy namespace status --json ccproxy namespace doctor ccproxy namespace doctor --json
Interpretation:
namespace status reports implementation facts: permissive mode, generatedWireGuard config presence, slirp4netns topology, and required tool paths.
privacy_claim: false is intentional. ccproxy reports observable runtimebehavior; it does not claim that the namespace is a restrictive privacy firewall.
namespace doctor runs a live probe through the same namespace execution pathused by ccproxy run --capture.
namespace doctor fails for DNS, public IPv4, or ccproxy-localhostreachability failures. IPv6 is reported but is not a failure.
ccproxy namespace wireguard-config prints raw WireGuard client config andcan expose private key material. Do not print or share it casually.
When the task concerns privacy, security language, namespace guarantees, keylogs, flow exports, or sharing diagnostics, read docs/privacy.md.
ccproxy runUse this when the client honors SDK base URL environment variables:
bashccproxy run -- claude ccproxy run -- aider ccproxy run -- python my_agent.py
This sets ANTHROPIC_BASE_URL, OPENAI_BASE_URL, and OPENAI_API_BASE to the configured ccproxy reverse proxy listener. Only traffic addressed to ccproxy is intercepted.
Use for lightweight SDK debugging and normal OpenAI/Anthropic-compatible clients.
ccproxy run --captureUse this when the tool hardcodes provider endpoints, when base URL injection is not enough, or when you need reference traffic from a real provider CLI:
bashccproxy start ccproxy run --capture -- claude -p "hello" ccproxy run --capture -- aider --model claude-sonnet-4-5-20250929 ccproxy run --capture -- python my_agent.py
The subprocess runs in a rootless Linux user+network namespace. ccproxy configures a WireGuard client inside that namespace, routes the namespace default route through mitmproxy, and injects a combined CA bundle via:
bashSSL_CERT_FILE NODE_EXTRA_CA_CERTS REQUESTS_CA_BUNDLE CURL_CA_BUNDLE
Important behavior:
tool.
hardcoded 127.0.0.1:4000 can still reach ccproxy.
listeners back to the host, which supports OAuth callback workflows.
| Scenario | Prefer | | --- | --- | | SDK client supports configurable base URL | ccproxy run | | CLI hardcodes provider endpoints | ccproxy run --capture | | Need native provider CLI reference traffic | ccproxy run --capture | | Need minimum moving parts | ccproxy run | | Need full local network capture for a tool | ccproxy run --capture | | Need to explain privacy behavior | docs/privacy.md + ccproxy namespace status --json |
Every accepted reverse-proxy or WireGuard flow is direction="inbound". The pipeline stage names inbound, transform, and outbound describe processing order, not traffic direction.
InspectorAddon stamps source metadata:
| Source | Meaning | | --- | --- | | reverse | Request entered through the reverse proxy listener | | wireguard | Request entered through mitmproxy's WireGuard listener | | unknown | Default before source is stamped |
Every flow has these useful views:
upstream.
when captured.
Use these views to distinguish client behavior from ccproxy behavior.
Client request snapshot
|
v
Inbound DAG
inject_auth: sentinel key -> configured provider credential
extract_session_id: body metadata -> ctx.metadata.session_id
provider-specific inbound hooks
|
v
Transform router
passthrough: keep destination/body
redirect: rewrite destination/auth, preserve wire format
transform: rewrite destination/auth and body via lightllm
|
v
Outbound DAG
gemini_cli: cloudcode-pa envelope/path/header handling
inject_mcp_notifications: buffered MCP events -> synthetic messages
verbose_mode: strip redact-thinking beta header
shape: replay packaged/local request shape and inner-DAG hooks
commitbee_compat: compatibility shim
|
v
TransportOverrideAddon
optional curl-cffi sidecar for configured fingerprint profiles
|
v
AuthAddon
401 detect -> credential re-resolve -> replay when token changed
|
v
GeminiAddon / PerplexityAddon / EgressSanitizerAddon
provider-specific response handling and ccproxy header cleanupAll ccproxy flows commands operate on a resolved flow set:
GET /flows -> config.flows.default_jq_filters -> CLI --jq filters -> final setUse repeatable --jq filters. Each filter must consume and produce a JSON array.
bashccproxy flows list ccproxy flows list --json ccproxy flows list --jq 'map(select(.request.pretty_host == "api.anthropic.com"))' ccproxy flows compare ccproxy flows compare --jq 'map(.[-1])' ccproxy flows diff ccproxy flows diff --jq 'map(select(.response.status_code >= 400))' ccproxy flows dump > all.har ccproxy flows dump --jq 'map(.[-1])' > latest.har ccproxy flows clear --all ccproxy flows clear --jq 'map(select(.response.status_code >= 400))'
Privacy note: HAR dumps, request/response bodies, flow JSON, and packet captures are sensitive. Prefer flows compare for local debugging and read docs/privacy.md before sharing artifacts.
Shape replay uses provider-specific .mflow or patch artifacts to reproduce known-good SDK request envelopes while injecting live request content.
Capture shape source traffic from a real CLI run:
bashccproxy start ccproxy run --capture -- claude -p "shape capture" ccproxy flows list ccproxy shapes save anthropic ccproxy shapes save anthropic --mflow
Audit packaged shape invariants:
bashuv run ccproxy shapes audit
Shape guidance:
.mflow files must be minimal request-only artifacts.responses, client snapshots, or captured TLS fingerprint metadata in packaged defaults.
users should not need to capture their own shapes unless a provider SDK behavior changed before a fixed release exists.
docs/shaping.md for canonical shape behavior.Problem?
|
+- ccproxy not capturing?
| -> ccproxy status --json
| -> For transparent capture: ccproxy namespace status --json
| -> For transparent capture: ccproxy namespace doctor --json
| -> Check same CCPROXY_CONFIG_DIR for start/run/status
|
+- Provider returns 401/403?
| -> ccproxy flows compare --jq 'map(.[-1])'
| -> Check sentinel key: sk-ant-oat-ccproxy-{provider}
| -> Check providers.{name}.auth resolves manually
| -> Check ctx.metadata.auth_provider / auth_injected
| -> Check ccproxy logs for AuthAddon refresh/replay
|
+- Request not transformed?
| -> ccproxy flows list --json
| -> Check lightllm.transforms match_host/match_path/match_model
| -> Check sentinel key resolved to a Provider
| -> ccproxy flows compare --jq 'map(.[-1])'
|
+- Shape not applied?
| -> Check hooks.outbound contains ccproxy.hooks.shape
| -> Check ccproxy shapes audit
| -> Check transform metadata exists for the flow
| -> Check flow source: reverse or auth-injected flows consume shapes
|
+- Gemini fails?
| -> Check gemini_cli outbound hook
| -> Check Google auth source refresh behavior
| -> Check GeminiAddon capacity fallback logs
| -> Inspect forwarded body for cloudcode-pa envelope fields
|
+- Privacy or artifact-sharing question?
-> Read docs/privacy.md
-> Prefer ccproxy namespace status --json over raw WireGuard config
-> Treat tls.keylog, wg.keylog, HAR files, and .mflow captures as sensitivedocs/privacy.md - privacy model, sensitive artifacts, sharing guidancedocs/inspect.md - inspector stack architecturedocs/shaping.md - request shaping systemdocs/lightllm.md - request/response transformation internalsskills/using-ccproxy-inspector/reference/flow-api-reference.md - mitmwebREST API endpoints, flow data model, content views, authentication
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-02 | fail→pass | 19,374 | 13,546 | -30% | 1 | 1 | 0% | 3,159 | 4,896 | +55% | 0 | 0 | — |
case-01 | fail→pass | 15,217 | 6,621 | -56% | 1 | 1 | 0% | 2,424 | 3,571 | +47% | 0 | 0 | — |
case-03 | fail→pass | 11,135 | 5,429 | -51% | 1 | 1 | 0% | 1,867 | 3,390 | +82% | 0 | 0 | — |
case-04 | fail→pass | 19,033 | 3,275 | -83% | 1 | 1 | 0% | 1,327 | 2,900 | +119% | 0 | 0 | — |
case-05 | fail→pass | 13,772 | 3,657 | -73% | 1 | 1 | 0% | 1,895 | 3,013 | +59% | 0 | 0 | — |
case-06 | pass→pass | 13,595 | 5,450 | -60% | 1 | 1 | 0% | 2,056 | 3,349 | +63% | 0 | 0 | — |
case-07 | fail→pass | 11,551 | 5,453 | -53% | 1 | 1 | 0% | 1,690 | 3,373 | +100% | 0 | 0 | — |
case-08 | pass→pass | 11,885 | 4,282 | -64% | 1 | 1 | 0% | 1,858 | 3,253 | +75% | 0 | 0 | — |
case-09 | fail→pass | 9,709 | 3,653 | -62% | 1 | 1 | 0% | 1,601 | 3,056 | +91% | 0 | 0 | — |
case-10 | fail→pass | 13,798 | 4,206 | -70% | 1 | 1 | 0% | 1,993 | 3,150 | +58% | 0 | 0 | — |
case-11 | pass→pass | 14,464 | 2,559 | -82% | 1 | 1 | 0% | 2,325 | 2,912 | +25% | 0 | 0 | — |
case-22 | pass→pass | 9,129 | 6,085 | -33% | 1 | 1 | 0% | 1,435 | 3,635 | +153% | 0 | 0 | — |
case-12 | fail→pass | 14,054 | 3,658 | -74% | 1 | 1 | 0% | 2,037 | 3,017 | +48% | 0 | 0 | — |
case-13 | fail→pass | 9,668 | 3,923 | -59% | 1 | 1 | 0% | 1,626 | 3,157 | +94% | 0 | 0 | — |
case-14 | fail→pass | 20,429 | 3,862 | -81% | 1 | 1 | 0% | 2,084 | 3,132 | +50% | 0 | 0 | — |
case-15 | fail→pass | 16,561 | 4,581 | -72% | 1 | 1 | 0% | 2,523 | 3,011 | +19% | 0 | 0 | — |
case-16 | pass→pass | 17,227 | 5,174 | -70% | 1 | 1 | 0% | 2,404 | 3,336 | +39% | 0 | 0 | — |
case-17 | fail→pass | 13,685 | 5,603 | -59% | 1 | 1 | 0% | 2,165 | 3,536 | +63% | 0 | 0 | — |
case-18 | fail→pass | 27,040 | 2,613 | -90% | 1 | 1 | 0% | 1,829 | 2,884 | +58% | 0 | 0 | — |
case-19 | fail→pass | 16,237 | 3,615 | -78% | 1 | 1 | 0% | 2,260 | 3,092 | +37% | 0 | 0 | — |
case-20 | pass→fail | 13,734 | 13,959 | +2% | 1 | 1 | 0% | 2,420 | 5,199 | +115% | 0 | 0 | — |
case-21 | pass→fail | 12,995 | 11,063 | -15% | 1 | 1 | 0% | 2,223 | 4,488 | +102% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 21 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +59 percentage points is the difference between those two pass rates over the 21 comparable cases. 2 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.