Skip to content

About

Local request viewer for Claude Code, Codex and OpenCode. Inspect prompts, tools, messages and responses in real time.Claude Code、Codex 和 OpenCode 的本地请求查看器。

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

context-tracker

CI npm license

Language: English · 简体中文

Mirror the HTTP requests that AI coding CLIs (OpenCode / Claude Code / Codex) send to model providers into a local viewer, so you can inspect the full request context — headers, system prompt, tool definitions, messages — and (optionally) the model's response.

Architecture

Claude Code ──ANTHROPIC_BASE_URL──▶ ┐
Codex CLI  ──config.toml base_url─▶ ├─▶ proxy ──HTTPS──▶ AI API
OpenCode   ──opencode.json baseURL▶ ┘      │
                                            └──POST──▶ viewer (:39877)

The proxy forwards traffic untouched to the upstream API and mirrors a copy of each request to the viewer — a fire-and-forget side channel that never blocks or alters the main request/response path. One proxy port can route to multiple upstreams by path prefix; the viewer classifies entries by source and API protocol.

Install

Requires Node.js >= 18. Zero runtime dependencies.

Global install (recommended):

npm install -g context-tracker
# or from source: git clone https://github.com/conrad621/context-tracker.git && cd context-tracker && npm link

This provides a single context-tracker command:

context-tracker start           # start the viewer AND the proxy together (one process)
context-tracker help            # show usage

Without installing you can run the scripts directly: node src/start.js. The viewer and proxy still live at src/viewer.js / src/proxy.js for advanced use, but the CLI exposes only start.

Usage

Quick start — viewer + proxy together in one process:

context-tracker start           # global install
npm start                       # from the repo (local)

This starts the viewer (web UI + terminal) and the forwarding proxy as a single process — one Ctrl+C stops both.

Startup is quiet: only the listen URLs are printed. Pass --verbose (-v) to also see the hint lines — discovery source, route table, mirror URL, capture status, and the viewer's terminal-output note: context-tracker start --verbose (or npm start -- --verbose from the repo).

When Claude Code and Codex are both configured, start captures both (one port routes /v1/messages to Claude's upstream and /v1/responses to Codex's). To capture just one, pass --agent <claude|codex>: discovery then reads only that client's config and the proxy forwards only that agent's path prefix — other traffic gets a no route 404 instead of being forwarded to the wrong target:

context-tracker start --agent codex      # capture Codex only
context-tracker start --agent claude     # capture Claude Code only

1. How the upstream is chosen

start runs the viewer (web UI at http://localhost:39877, live terminal output) and the forwarding proxy in one process. The proxy picks its upstream in this order:

  1. Environment (highest freedom) — TARGET_URL / ROUTES always win over discovery; use them when you want a specific upstream, custom ports, or no config files at all:

    # single upstream
    TARGET_URL=https://api.deepseek.com context-tracker start
    
    # multi-upstream routing (capture Claude + Codex on one port)
    ROUTES='[
      {"prefix":"/v1/messages","target":"https://api.anthropic.com","source":"claude-code"},
      {"prefix":"/v1/responses","target":"https://api.openai.com","source":"codex"}
    ]' context-tracker start
  2. Auto-discovery (default, no config needed) — if you use Claude Code and/or Codex CLI, the proxy derives its upstreams from the clients' own config files, so you don't need to maintain profiles.json or set TARGET_URL at all:

    context-tracker start               # no env: auto-discover upstreams

Discovery reads, following each tool's official posture and merge order:

  • Claude Code — ~/.claude/settings.local.json then ~/.claude/settings.json (local overrides user) → env.ANTHROPIC_BASE_URL; falls back to the ANTHROPIC_BASE_URL environment variable. Claude traffic always lands on /v1/messages.
  • Codex CLI — ~/.codex/config.toml → the active [model_providers.*] base_url + wire_api; falls back to OPENAI_BASE_URL (wire via CODEX_WIRE_API || "chat"). Codex traffic lands on /responses (or /chat/completions for chat wire).

When both are found, the proxy routes one port to both upstreams by prefix (--verbose shows where it found them). To point discovery at a non-default path (or to override in CI/tests): CT_CLAUDE_SETTINGS, CT_CLAUDE_SETTINGS_LOCAL, CT_CODEX_CONFIG. Set AUTO_DISCOVER=0 to disable.

A discovered upstream that points back at the proxy itself (a loopback host on the proxy/mirror port) is ignored — so a stale ANTHROPIC_BASE_URL=http://localhost:39876 capture setting won't create a loop. Legitimate local upstreams on other ports (e.g. Ollama on :11434) pass through. If every candidate is filtered, the startup error lists which source pointed back at the proxy so the fix is obvious. Auto-discovery only covers Claude Code and Codex configs; other tools (OpenCode, DeepSeek, …) still need env vars.

profiles.json (schema: target, or routes with per-prefix target/source; plus port/mirrorPort/captureResponse/maxResponseBytes/redactAuth) is retained for programmatic consumers via loadProfiles() / resolveConfig() in src/config.js (PROFILES overrides its path); the CLI does not use it.

3. Point each tool at the proxy

Claude Code (calls POST /v1/messages):

export ANTHROPIC_BASE_URL=http://localhost:39876
export ANTHROPIC_API_KEY=sk-ant-...        # or ANTHROPIC_AUTH_TOKEN
claude

Codex CLI (calls POST /v1/responses) — edit ~/.codex/config.toml:

model_provider = "capture"

[model_providers.capture]
name = "Capture Proxy"
base_url = "http://localhost:39876/v1"      # client sends /v1/responses
env_key = "OPENAI_API_KEY"
wire_api = "responses"
export OPENAI_API_KEY=sk-...
codex

Codex defaults to ChatGPT subscription login; to capture traffic you must use API-key auth (the env_key above).

OpenCode — set the provider's baseURL to http://localhost:39876 in opencode.json.

⚠️ The /v1 path prefix: Claude Code and Codex send the full path including /v1 themselves, so TARGET_URL / route target must be the host root (e.g. https://api.anthropic.com, without /v1) — otherwise you get a doubled /v1/v1/... prefix. If OpenCode only sends /messages, then TARGET_URL needs to include /v1.

4. Start chatting

Request context appears live in both the viewer terminal and the web UI. Each entry offers structured / raw / headers / (optional) response views.

Web UI features:

  • Search — the top search box filters by path / model / content in real time, with match highlighting (/ to focus, Esc to clear)
  • Filter — source / api chips, multi-select and stackable
  • Live metrics — total requests, currently shown, requests per minute
  • Pause / follow / clear — pause freezes live updates, follow auto-scrolls to newest, clear empties the view
  • Text selection — hover any content box for select-all / copy; double-click selects the whole block
  • Incremental sync — the client only fetches new/updated entries (/__history?since=), so poll cost stays flat regardless of history size
  • Virtual scrolling — only viewport rows are rendered; thousands of requests still mean only a few dozen DOM nodes
  • Stable expansion — an expanded entry stays open and keeps its active tab across live refreshes
  • Response usage — when response capture is on, the response pane parses the SSE stream into a token-usage / stop-reason / tool-call summary
  • Request diff — a "diff" view compares each request against the previous one from the same source: system-prompt changes, added/removed/changed tools, added/removed message turns
  • Token accounting & composition — each request shows a token count (real usage when captured, else estimated) and a stacked bar breaking it into system / tools / history / current, with per-tool cost
  • Cost stats — a Stats panel aggregates captured traffic by model and source (requests, tokens, estimated USD cost); prices are configurable in config/pricing.json
  • Waste detection — requests are flagged for oversized system prompts, large/duplicated tool schemas, over-long history, and repeated messages, with a suggestions list
  • Session filter — requests carrying a session id (from headers or body) can be isolated to view one agent task's turns as a timeline
  • Export — export the current view, a single request, or a session to JSON / Markdown / HAR (via export links or the /__export endpoint)

Environment variables

Variable Default Description
PROFILES ./config/profiles.json path to the profile config file
AUTO_DISCOVER 1 when 1 (default), proxy with no profile/env derives upstreams from Claude Code / Codex config files; set 0 to disable
CT_CLAUDE_SETTINGS ~/.claude/settings.json auto-discovery: Claude Code settings file path
CT_CLAUDE_SETTINGS_LOCAL ~/.claude/settings.local.json auto-discovery: Claude Code local settings file path (overrides user settings)
CT_CODEX_CONFIG ~/.codex/config.toml auto-discovery: Codex CLI config file path
PROXY_PORT 39876 proxy listen port
MIRROR_PORT 39877 viewer listen port
TARGET_URL - single upstream base URL; used with or as the fallback for ROUTES
ROUTES - JSON array routing by prefix to different targets, with an optional source label
SOURCE - manual source label in single-upstream mode
CAPTURE_RESPONSE - when 1, tee and aggregate the SSE response and associate it with its request
MAX_RESPONSE_BYTES 2097152 response aggregation cap (truncated beyond this)
MAX_HISTORY 2000 max number of requests the viewer retains
REDACT_AUTH - when 1, redact API keys (applied at viewer render time)

Testing

npm test        # runs: node --test

Includes protocol-extraction unit tests (Anthropic Messages / OpenAI Chat / OpenAI Responses), config/profile-loading and auto-discovery unit tests, and end-to-end tests (mock SSE upstream + proxy + viewer) verifying routing, streaming passthrough, mirror classification, redaction, response aggregation, profile startup, and auto-discovery from injected client configs.

Supported protocols

API Path Source tool
Anthropic Messages /v1/messages Claude Code
OpenAI Responses /v1/responses Codex
OpenAI Chat Completions /v1/chat/completions OpenCode / DeepSeek / etc.

Limitations

  • Only works with header-authenticated providers (Anthropic, OpenAI, DeepSeek, OpenRouter, etc.). Signature-based auth such as AWS Bedrock (SigV4) or Google Vertex is not supported.
  • Codex subscription login (ChatGPT) cannot be captured; switch to API-key auth.
  • Response capture has a memory cost, bounded by MAX_RESPONSE_BYTES; oversized responses keep only a truncated copy.

Roadmap

Where the project is headed — see ROADMAP.md.

License

MIT

About

Local request viewer for Claude Code, Codex and OpenCode. Inspect prompts, tools, messages and responses in real time.Claude Code、Codex 和 OpenCode 的本地请求查看器。

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages