CodeAgentLens is a local model-endpoint gateway and observability workbench for code agents. It gives Claude Code, Codex, and other OpenAI/Anthropic-compatible clients one local gateway while keeping traces, prompts, request artifacts, usage, endpoint decisions, and logs inspectable on the same machine.
This project is an independently maintained derivative of ccNexus.
Upstream: https://github.com/lich0821/ccNexus
- A loopback Gateway/API at
http://127.0.0.1:3010for code-agent model traffic. - A separate Debug Portal at
http://127.0.0.1:3011/debug/obsfor observability and local artifact inspection. - OpenTelemetry traces and metrics exported to a bundled local stack.
- Local request dumps with prompt extraction, headers, request/response bodies, transformed bodies, stream events, and usage files.
- Endpoint routing, retry, credential rotation, and token usage accounting across Claude, OpenAI Chat, and OpenAI Responses style clients.
- Source-controlled local validation commands for native and Docker runtime modes.
Figure 1: How code-agent traffic moves through the Gateway and becomes traces, dump artifacts, and Debug Portal links.
Figure 2: How the local Gateway, Debug Portal, dump root, SQLite store, and observability stack connect on a developer machine.
Default local entry points:
| Component | URL | Purpose |
|---|---|---|
| Gateway/API | http://127.0.0.1:3010 |
Local code-agent model endpoint. |
| Debug Portal | http://127.0.0.1:3011/debug/obs |
Main UI for traces, prompts, artifacts, and tool links. |
| Jaeger | http://127.0.0.1:16686 |
Trace search and span timing. |
| Grafana | http://127.0.0.1:13000 |
Dashboards and Tempo/Prometheus queries. |
| Prometheus | http://127.0.0.1:9090/graph |
Metrics query UI. |
| Tempo | http://127.0.0.1:3200/status |
Trace storage status. |
| OTel Collector | http://127.0.0.1:8888/metrics |
Collector diagnostics. |
CodeAgentLens separates traffic handling from observability access. The Gateway/API listens on 3010 and agent clients only need that URL. The Debug Portal listens on 3011 and is the place to inspect what happened after a request flows through the gateway.
CodeAgentLens local runtime data is canonicalized at D:\DevTools\code-agent-lens\data. The SQLite database is D:\DevTools\code-agent-lens\data\code-agent-lens.db, and Docker maps this host directory to /data. The legacy D:\DevTools\shared\ccnexus tree is a ccNexus migration source only, not a CodeAgentLens runtime directory. See Runtime Paths.
| Setting | Purpose |
|---|---|
CODE_AGENT_LENS_DATA_DIR=D:\DevTools\code-agent-lens\data |
Canonical native data directory. Docker maps the same host directory to /data. |
CODE_AGENT_LENS_DB_PATH=D:\DevTools\code-agent-lens\data\code-agent-lens.db |
Canonical native SQLite database path. Inside Docker this is /data/code-agent-lens.db. |
CODE_AGENT_LENS_OBS_LOCAL_DEBUG=true |
Enables the local debug policy. |
CODE_AGENT_LENS_OBS_DUMP_ENABLED=true |
Enables local request artifact dumps. |
CODE_AGENT_LENS_OBS_DUMP_DIR=D:\DevTools\code-agent-lens\data\observability |
Canonical native dump root. Inside Docker this is /data/observability. |
CODE_AGENT_LENS_OBS_VIEWER_ENABLED=true |
Enables the Debug Portal. |
CODE_AGENT_LENS_OBS_VIEWER_PUBLIC_URL=http://127.0.0.1:3011/debug/obs |
Writes the local viewer URL into trace attributes and artifact links. |
CODE_AGENT_LENS_OBS_CAPTURE_HEADERS=all |
Captures request and upstream headers; secret headers are redacted by default. |
CODE_AGENT_LENS_OBS_CAPTURE_BODIES=all |
Captures ingress, transform, and upstream body artifacts. |
CODE_AGENT_LENS_OBS_CAPTURE_STREAM_EVENTS=all |
Captures raw and transformed streaming event JSONL. |
CODE_AGENT_LENS_OBS_PROMPT_EXTRACT=true |
Extracts prompt role artifacts from supported API bodies. |
| Module | What it does | Where to look |
|---|---|---|
| Gateway listener | Receives Claude, OpenAI Chat, and OpenAI Responses style requests from code agents. | http://127.0.0.1:3010/health and gateway logs. |
| Endpoint resolver | Chooses the active enabled endpoint, supports manual switching, and protects in-flight endpoint requests during rotation. | Web UI and request logs. |
| Protocol transformers | Converts between supported client and upstream formats, including Claude, OpenAI Chat, and OpenAI Responses paths. | Request artifacts named transform.request.* and transformed response artifacts. |
| Proxy and retry engine | Sends upstream requests with connection pooling, retries transient failures, tracks active requests, and records endpoint failures. | Debug Portal request detail, logs, and usage artifacts. |
| Token and usage extractor | Normalizes input/output token usage from non-streaming and streaming responses. | usage.json inside each request artifact directory. |
| Request recorder | Creates request IDs, trace IDs, span IDs, obs references, viewer URLs, and OTel attributes. | /debug/obs/trace/{trace_id} and Jaeger span attributes. |
| Local dump writer | Writes manifest-bound request artifacts under runs/{run_id}/traces/{trace_id}/{request_id}. |
/debug/obs/request/{request_id}. |
| Prompt extractor | Extracts system, developer, user, and other prompt roles from supported API bodies. | /debug/obs/prompts and /debug/obs/request/{request_id}/prompts. |
| Stream event capture | Records raw and transformed SSE events when stream capture is enabled. | Stream artifacts and /debug/obs/request/{request_id}. |
| Debug Portal | Provides the local UI for recent requests, prompt sessions, errors, trace links, raw artifacts, and integrated tools. | http://127.0.0.1:3011/debug/obs. |
| Jaeger integration | Shows distributed trace timing and links back to CodeAgentLens artifacts through code-agent-lens_obs_ref. |
/debug/obs/tool/jaeger or native Jaeger. |
| Grafana integration | Opens local dashboards and Tempo/Prometheus views while preserving Portal navigation. | /debug/obs/tool/grafana or native Grafana. |
| Prometheus metrics | Exposes counters and histograms for requests, errors, retries, endpoint rotations, stream events, credential refreshes, and token totals. | Prometheus or Grafana. |
| Validation CLI | Produces evidence for stack profiles, local debug policy, synthetic traces, auth simulations, and port checks. | go run ./cmd/code-agent-lens obs .... |
For each observable request, CodeAgentLens can write a manifest-bound directory containing:
prompt.index.json: request metadata, prompt role manifest, file manifest, trace ID, span ID, request ID, and run ID.ingress.request.headers.jsonandingress.request.body.raw: client-side request data, with secret headers redacted unless explicitly enabled for local debugging.prompt.system.txt,prompt.developer.txt,prompt.user.txt, and numbered variants: extracted prompt text by role.transform.request.input.rawandtransform.request.output.raw: transformer input and output snapshots.upstream.request.*andupstream.response.*: upstream URL, headers, body, and transformed response data.stream.raw.events.jsonlandstream.transformed.events.jsonl: streaming event evidence when enabled.usage.json: normalized input and output token counts plus the source of the usage data.
The Debug Portal serves artifacts through manifest-bound routes, not arbitrary filesystem paths.
Run static source validation:
go run ./cmd/code-agent-lens obs validate --deployment-profile local_debug --profile deploy/observability/stack.local.yaml --evidence-dir .tmp/release-gate/observability/nativeUse this mode when you want the native CodeAgentLens process on 3010 and 3011, with Docker providing Jaeger, Grafana, Prometheus, Tempo, and the OTel Collector.
Start the observability-only Docker stack first:
docker compose -p observability -f deploy/observability/docker-compose.observability.yaml up -dThen start the native local debug runtime when ports 3010 and 3011 are free:
go run ./cmd/code-agent-lens obs up --mode native --deployment-profile local_debug --profile deploy/observability/stack.local.yaml --evidence-dir .tmp/release-gate/observability/nativeThe native Go command does not start Docker containers. It starts only the CodeAgentLens runtime and Debug Portal, uses the canonical local database at D:\DevTools\code-agent-lens\data\code-agent-lens.db, writes artifacts under D:\DevTools\code-agent-lens\data\observability, and exports OTEL data to http://127.0.0.1:4318.
Run full-chain synthetic trace validation after the runtime is up:
go run ./cmd/code-agent-lens obs validate --mode native --deployment-profile local_debug --profile deploy/observability/stack.local.yaml --synthetic --trace --evidence-dir .tmp/release-gate/observability/nativeStop the native runtime:
go run ./cmd/code-agent-lens obs stop --mode native --profile deploy/observability/stack.local.yaml --evidence-dir .tmp/release-gate/observability/native-stopCheck that the official ports are free:
go run ./cmd/code-agent-lens obs ports --expect-free 3010,3011 --evidence-dir .tmp/release-gate/observability/native-stopUse this mode instead of native when you want both CodeAgentLens and the observability stack inside Docker. Do not run it alongside the native runtime on 3010 and 3011.
Start the full stack through the CLI:
go run ./cmd/code-agent-lens obs up --mode docker --deployment-profile local_debug --profile deploy/observability/stack.local.yaml --evidence-dir .tmp/release-gate/observability/dockerEquivalent direct compose command:
docker compose -p observability -f deploy/observability/docker-compose.full.yaml up -d --build --remove-orphansOpen http://127.0.0.1:3011/debug/obs/prompts. Use the search, role, and run filters to find the request. Open the request's prompt details to see extracted system, developer, user, and other prompt roles.
Open http://127.0.0.1:3011/debug/obs/trace/{trace_id}. The trace page lists the request IDs found under that trace and links to request details, prompt details, raw bodies, and artifact views.
Open http://127.0.0.1:3011/debug/obs/ref/{trace_id}/{request_id}. Jaeger can also use docs/observability/jaeger-ui-config.json to make code-agent-lens_obs_ref clickable.
Open the request detail page and inspect the ingress body plus transformer artifacts. The Gateway detects client format from paths such as /v1/messages, /v1/chat/completions, and /v1/responses.
Start from /debug/obs, open the request, then inspect upstream request artifacts and logs. Endpoint state is also represented in the Web UI and persisted in the local SQLite-backed configuration and stats store.
Open /debug/obs/request/{request_id}. Use the artifact links for ingress request body, transform input, transform output, upstream request body, upstream response body, and upstream response transformed body.
Open /debug/obs/request/{request_id} and inspect usage.json. It records normalized input and output tokens plus whether usage came from upstream data or fallback extraction.
Open the request detail page and inspect stream artifacts. When stream capture is enabled, CodeAgentLens writes raw and transformed stream event JSONL files so you can compare upstream SSE shape with client-facing SSE shape.
Open /debug/obs/tool/jaeger or native Jaeger at http://127.0.0.1:16686. Search for the CodeAgentLens service and follow spans such as gateway request handling, ingress capture, upstream request, usage extraction, and stream processing.
Open /debug/obs/tool/grafana or native Grafana at http://127.0.0.1:13000. Prometheus metrics include request totals, error totals, request duration, upstream duration, retries, endpoint rotations, token counters, stream events, and credential refresh/failure counters.
Gateway traffic uses 127.0.0.1:3010. Debug Portal traffic uses 127.0.0.1:3011/debug/obs. The gateway deliberately returns not found for /debug/obs so agent tokens and model-call traffic do not open the Portal listener.
The Debug Portal reads local dump files from the configured dump root. Full prompt/body artifacts are local debug artifacts. OpenTelemetry exports traces and metrics to the configured local collector in the bundled local stack.
Stop the process that owns the official port, or run a separate diagnostic environment that does not count as formal release evidence. The official local debug profile uses 3010 for the Gateway/API and 3011 for the Debug Portal.
Run obs up, then obs validate --synthetic --trace. The validation sends a fixture-driven OpenAI Responses request through the local gateway, verifies the response, checks local dump artifacts, verifies prompt roles and usage, and writes evidence under the chosen evidence directory.
Point the agent's base URL at http://127.0.0.1:3010 or http://127.0.0.1:3010/v1 according to the client. Use obs configure-agents --backup first as a dry run to preview agent configuration without modifying user config files.
The default local_debug profile is for loopback-only development. It can use full local capture so a developer can inspect prompts and model payloads on the same machine. Non-loopback profiles must fail closed unless auth, RBAC, capture policy, and tool exposure rules pass validation.
Important boundaries:
local_debugis the only profile that permits disabled Portal auth, and only for loopback bind.lan_teamandpublic_serveruse metadata-first capture defaults and require auth/RBAC simulation to pass.- Secret headers such as
AuthorizationandX-API-Keyare redacted unless explicit local debug capture is enabled. - Raw artifact routes are manifest-bound and reject path traversal.
- Agent Gateway traffic and Portal traffic use separate listeners.
Maintainer: milome
Security reports: GitHub private vulnerability reporting: https://github.com/milome/code-agent-lens/security/advisories/new