Coding Agent Tracking
Track prompts, token usage, costs, and conversations from Claude Code, Cursor, Aider, Cline, and any other LLM-powered coding agent.
Managing the gateway from an agent?
How it works
Ingate sits between your coding agent and the LLM provider. Every request passes through, gets logged with full request/response capture, and is forwarded to the real API: logs, costs, usage, and sessions are all captured. The agent sees no difference: same API, same responses, same streaming.
Provider auth modes
Add provider configs to ingate.yaml. There are two modes depending on how your tools authenticate.
Mode A: API key (Ingate manages keys)
Ingate holds the real API keys. Tools authenticate to Ingate, and Ingate injects the real provider key when forwarding upstream.
providers:
anthropic:
base_url: https://api.anthropic.com
api_key: sk-ant-your-real-key # Ingate injects this
enabled: true
openai:
base_url: https://api.openai.com
api_key: sk-your-real-key
enabled: trueMode B: Auth passthrough (for subscriptions)
For tools that authenticate with their own credentials (e.g., Claude Code with a Pro/Max subscription, or Cursor with its own API key), use auth_passthrough: true. Ingate forwards the client's auth headers to the provider as-is, no key injection, just observation and logging.
providers:
anthropic:
base_url: https://api.anthropic.com
auth_passthrough: true # Don't inject auth, forward client's OAuth token
enabled: true
default: true
openai:
base_url: https://api.openai.com
auth_passthrough: true
enabled: trueWhen to use which
| Scenario | Mode |
|---|---|
| Team sharing a single Anthropic API key | API key, one key on the server, devs get Ingate keys |
| Individual developer with Claude Pro/Max | Auth passthrough, Claude Code's OAuth token passes through |
| Individual developer with their own API key | Either mode works |
| Cursor with built-in subscription | Auth passthrough |
Every request through the proxy authenticates with X-Ingate-Key (your Ingate API key). When a tool only exposes a base URL and API key setting, the Ingate key goes in the API key field, as in the per-tool setups below.
Claude Code
Claude Code uses the Anthropic SDK, which respects ANTHROPIC_BASE_URL.
With a subscription (Pro/Max)
If you're using Claude Code with a Claude subscription (not an API key), use auth passthrough mode. Claude Code authenticates via OAuth. Ingate just forwards the token and logs everything.
providers:
anthropic:
base_url: https://api.anthropic.com
auth_passthrough: true # Forward Claude Code's OAuth token
enabled: true
default: trueexport ANTHROPIC_BASE_URL=http://localhost:7100
# No ANTHROPIC_API_KEY needed, Claude Code uses its own OAuth tokenClaude Code authenticates normally (browser OAuth), sends POST /v1/messages to Ingate, Ingate auto-detects "anthropic", forwards the request with the OAuth token intact, logs everything, and returns the response.
With an API key
If you have an Anthropic API key (not a subscription), Ingate holds the key and injects it:
providers:
anthropic:
base_url: https://api.anthropic.com
api_key: sk-ant-your-real-key
enabled: true
default: trueexport ANTHROPIC_BASE_URL=http://localhost:7100
export ANTHROPIC_API_KEY=igt_your_ingate_key # Ingate key, not Anthropic keyCursor
Cursor supports custom API endpoints in its settings:
- Open Cursor Settings → Models
- Set API Base URL to
http://localhost:7100 - Set the API key to your Ingate key
Or via environment:
export OPENAI_BASE_URL=http://localhost:7100 # For OpenAI models
export ANTHROPIC_BASE_URL=http://localhost:7100 # For Claude modelsAider
Aider supports custom base URLs via environment variables:
# For Anthropic models
export ANTHROPIC_BASE_URL=http://localhost:7100
export ANTHROPIC_API_KEY=igt_your_ingate_key
# For OpenAI models
export OPENAI_API_BASE=http://localhost:7100
export OPENAI_API_KEY=igt_your_ingate_keyCline (VS Code)
In Cline's settings, configure:
- API Provider: Anthropic (or OpenAI)
- Base URL:
http://localhost:7100 - API Key: your Ingate key
How routing works
Ingate automatically detects the provider from the request path, no X-Ingate-Provider header needed:
| Path pattern | Auto-detected provider |
|---|---|
/v1/messages | anthropic |
/v1/chat/completions | openai |
/v1/completions | openai |
/v1/embeddings | openai |
/v1/models | openai |
/v1/responses | openai |
/api/generate | ollama |
/api/chat | ollama |
For any path not in this table, you can configure a fallback by marking a provider default: true.
Priority chain
X-Ingate-Provider header → path auto-detection → the provider marked default: true in config.What gets tracked
Once routed through Ingate, every request is captured:
| Data | Where to see |
|---|---|
| Full request/response bodies | Dashboard → Logs (/ui/#/logs) |
| Token counts (input/output) | Dashboard → Usage (/ui/#/usage) |
| Latency per request | Log detail view |
| Cost estimates | Dashboard → Usage breakdown |
| Model used | Logs filter by model |
| Provider | Logs filter by provider |
| Session timelines | Dashboard → Sessions (/ui/#/sessions) |
| User breakdown | Dashboard → User Analytics (/ui/#/user-analytics) |
Session tracking
To group requests into conversations, add the optional tracking headers X-Ingate-User-Id (who is making the request) and X-Ingate-Session-Id (which conversation/session this belongs to). Then view conversation timelines at /ui/#/sessions.
Usage analytics
Query usage by user or session:
# Who's using the most tokens?
curl http://localhost:7100/api/v1/usage/breakdown?group_by=user \
-H "Authorization: Bearer $TOKEN"
# What sessions are active?
curl http://localhost:7100/api/v1/sessions \
-H "Authorization: Bearer $TOKEN"
# Timeline of a specific session
curl http://localhost:7100/api/v1/sessions/SESSION_ID/timeline \
-H "Authorization: Bearer $TOKEN"Team setup
For a team of developers, each developer gets their own Ingate API key:
# Admin creates keys for each developer
# Each developer sets their personal key in their shell profile
# Developer 1
export ANTHROPIC_BASE_URL=http://ingate.internal:7100
export ANTHROPIC_API_KEY=igt_dev1_key
# Developer 2
export ANTHROPIC_BASE_URL=http://ingate.internal:7100
export ANTHROPIC_API_KEY=igt_dev2_keyBenefits:
- Centralized API key management (real keys never leave the server)
- Per-developer usage tracking and cost attribution
- Budget enforcement per org/user
- Audit trail of all LLM interactions
- No need to distribute provider API keys to individual machines
Alternative: post-hoc ingestion
If you can't proxy (e.g., the tool doesn't support custom base URLs), use the Ingestion API to send logs after the fact:
curl -X POST http://localhost:7100/api/v1/ingest \
-H "X-Ingate-Key: igt_your_key" \
-H "Content-Type: application/json" \
-d '{
"provider": "anthropic",
"model": "claude-sonnet-4-20250514",
"request": {
"body": "{\"model\":\"claude-sonnet-4-20250514\",\"messages\":[{\"role\":\"user\",\"content\":\"explain this code\"}]}"
},
"response": {
"status_code": 200,
"body": "{\"content\":[{\"text\":\"This code...\"}],\"usage\":{\"input_tokens\":50,\"output_tokens\":200}}"
},
"latency_ms": 1500,
"tags": {
"user_id": "dev@company.com",
"session_id": "coding-session-42",
"tool": "claude-code"
}
}'Alternative: OpenTelemetry
If your tool emits OpenTelemetry traces (or you instrument it), send traces to Ingate's OTLP receiver: Ingate accepts OTLP/HTTP at POST /v1/traces:
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:7100Ingate extracts gen_ai.* span attributes (model, tokens, provider) and maps them to log entries automatically. See OpenTelemetry for details.