context-lens 0.6.2 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -19
- package/dist/analysis/server.js +2 -2
- package/dist/analysis/server.js.map +1 -1
- package/dist/cli-utils.d.ts.map +1 -1
- package/dist/cli-utils.js +18 -1
- package/dist/cli-utils.js.map +1 -1
- package/dist/cli.js +140 -30
- package/dist/cli.js.map +1 -1
- package/dist/core/security.d.ts.map +1 -1
- package/dist/core/security.js +23 -0
- package/dist/core/security.js.map +1 -1
- package/dist/core/tool-patterns.d.ts +52 -0
- package/dist/core/tool-patterns.d.ts.map +1 -0
- package/dist/core/tool-patterns.js +260 -0
- package/dist/core/tool-patterns.js.map +1 -0
- package/dist/core/waste.d.ts +73 -0
- package/dist/core/waste.d.ts.map +1 -0
- package/dist/core/waste.js +283 -0
- package/dist/core/waste.js.map +1 -0
- package/dist/core.d.ts +4 -0
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +2 -0
- package/dist/core.js.map +1 -1
- package/dist/proxy/prune.d.ts +15 -0
- package/dist/proxy/prune.d.ts.map +1 -0
- package/dist/proxy/prune.js +112 -0
- package/dist/proxy/prune.js.map +1 -0
- package/dist/proxy/server.js +9 -0
- package/dist/proxy/server.js.map +1 -1
- package/dist/schemas.d.ts +4 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +2 -0
- package/dist/schemas.js.map +1 -1
- package/dist/server/api.d.ts.map +1 -1
- package/dist/server/api.js +86 -1
- package/dist/server/api.js.map +1 -1
- package/dist/server/projection.d.ts.map +1 -1
- package/dist/server/projection.js +1 -0
- package/dist/server/projection.js.map +1 -1
- package/dist/server/store.d.ts +4 -0
- package/dist/server/store.d.ts.map +1 -1
- package/dist/server/store.js +73 -4
- package/dist/server/store.js.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/mitm_addon.py +1 -0
- package/package.json +5 -5
- package/ui/dist/assets/index-CZq91bC_.js +52 -0
- package/ui/dist/assets/index-DSyD9xgM.css +1 -0
- package/ui/dist/index.html +2 -2
- package/ui/dist/assets/index-C2HhFk_P.js +0 -52
- package/ui/dist/assets/index-xYrXQJL_.css +0 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ See what's actually filling your context window. Context Lens is a local proxy t
|
|
|
8
8
|
|
|
9
9
|
Works with Claude Code, Codex, Gemini CLI, Cline, Aider, Pi, and anything else that talks to OpenAI/Anthropic/Google APIs. No code changes needed.
|
|
10
10
|
|
|
11
|
-
**Using AI coding tools across a team?** Token costs compound fast when every developer runs agents all day. Context Lens gives you per-session visibility into where the budget goes
|
|
11
|
+
**Using AI coding tools across a team?** Token costs compound fast when every developer runs agents all day. Context Lens gives you per-session visibility into where the budget goes: which tools, which patterns, which sessions are outliers. Export sessions as [LHAR](docs/LHAR.md) to share and compare. Team dashboards are on the roadmap; if that's relevant for you, [open an issue](https://github.com/larsderidder/context-lens/issues) or watch this repo.
|
|
12
12
|
|
|
13
13
|

|
|
14
14
|
|
|
@@ -101,14 +101,38 @@ ANTHROPIC_BASE_URL=http://localhost:4040/claude claude
|
|
|
101
101
|
OPENAI_BASE_URL=http://localhost:4040 codex
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
+
### OpenAI-compatible providers
|
|
105
|
+
|
|
106
|
+
If your tool talks to an OpenAI-compatible endpoint (Ollama, OpenRouter, Together, vLLM, etc.), set `UPSTREAM_OPENAI_URL` so the proxy knows where to forward:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
docker run -d \
|
|
110
|
+
-p 4040:4040 -p 4041:4041 \
|
|
111
|
+
-e CONTEXT_LENS_BIND_HOST=0.0.0.0 \
|
|
112
|
+
-e UPSTREAM_OPENAI_URL=https://openrouter.ai/api/v1 \
|
|
113
|
+
-v ~/.context-lens:/root/.context-lens \
|
|
114
|
+
ghcr.io/larsderidder/context-lens:latest
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Then point your tool at the proxy (e.g. `"baseURL": "http://localhost:4040/opencode"`).
|
|
118
|
+
|
|
119
|
+
For services running on the Docker host (like Ollama), use `host.docker.internal` as the hostname:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
UPSTREAM_OPENAI_URL=http://host.docker.internal:11434/v1
|
|
123
|
+
```
|
|
124
|
+
|
|
104
125
|
### Environment variables
|
|
105
126
|
|
|
106
127
|
| Variable | Default | Description |
|
|
107
128
|
| :--- | :--- | :--- |
|
|
108
129
|
| `CONTEXT_LENS_BIND_HOST` | `127.0.0.1` | Set to `0.0.0.0` to accept connections from outside the container |
|
|
130
|
+
| `UPSTREAM_OPENAI_URL` | _(auto-detect)_ | Forward OpenAI-format requests to this URL (for Ollama, vLLM, OpenRouter, etc.) |
|
|
109
131
|
| `CONTEXT_LENS_INGEST_URL` | _(file-based)_ | POST captures to a remote URL instead of writing to disk |
|
|
110
132
|
| `CONTEXT_LENS_PRIVACY` | `standard` | Privacy level: `minimal`, `standard`, or `full` |
|
|
111
133
|
| `CONTEXT_LENS_NO_UPDATE_CHECK` | `0` | Set to `1` to skip the npm update check |
|
|
134
|
+
| `CONTEXT_LENS_MAX_SESSIONS` | `200` | Maximum number of conversations to keep in memory |
|
|
135
|
+
| `CONTEXT_LENS_MAX_COMPACT_MESSAGES` | `60` | Maximum messages per entry when compacting for storage |
|
|
112
136
|
|
|
113
137
|
### Split-container setup
|
|
114
138
|
|
|
@@ -151,18 +175,18 @@ services:
|
|
|
151
175
|
|
|
152
176
|
## What You Get
|
|
153
177
|
|
|
154
|
-
-
|
|
155
|
-
-
|
|
156
|
-
-
|
|
157
|
-
-
|
|
158
|
-
-
|
|
159
|
-
-
|
|
160
|
-
-
|
|
161
|
-
-
|
|
162
|
-
-
|
|
163
|
-
-
|
|
164
|
-
-
|
|
165
|
-
-
|
|
178
|
+
- Composition treemap: visual breakdown of what's filling your context (system prompts, tool definitions, tool results, messages, thinking, images)
|
|
179
|
+
- Cost tracking: per-turn and per-session cost estimates across models
|
|
180
|
+
- Conversation threading: groups API calls by session, shows main agent vs subagent turns
|
|
181
|
+
- Agent breakdown: token usage and cost per agent within a session
|
|
182
|
+
- Timeline: bar chart of context size over time, filterable by main/all/cost
|
|
183
|
+
- Context diff: turn-to-turn delta showing what grew, shrank, or appeared
|
|
184
|
+
- Findings: flags large tool results, unused tool definitions, context overflow risk, compaction events
|
|
185
|
+
- Auto-detection: recognizes Claude Code, Codex, aider, Pi, and others by source tag or system prompt
|
|
186
|
+
- Session tagging: label sessions with custom tags, filter the session list by tag
|
|
187
|
+
- LHAR export: download session data as LHAR (LLM HTTP Archive) format ([doc](docs/LHAR.md))
|
|
188
|
+
- State persistence: data survives restarts; delete individual sessions or reset all from the UI
|
|
189
|
+
- Streaming support: passes through SSE chunks in real-time
|
|
166
190
|
|
|
167
191
|
### Screenshots
|
|
168
192
|
|
|
@@ -238,7 +262,7 @@ redact = "secrets"
|
|
|
238
262
|
|
|
239
263
|
### OpenCode
|
|
240
264
|
|
|
241
|
-
OpenCode connects to multiple providers simultaneously over HTTPS. Use `context-lens opencode
|
|
265
|
+
OpenCode connects to multiple providers simultaneously over HTTPS. Use `context-lens opencode`; it routes all traffic through mitmproxy so every provider call is captured regardless of which model is active:
|
|
242
266
|
|
|
243
267
|
```bash
|
|
244
268
|
pipx install mitmproxy
|
|
@@ -260,7 +284,7 @@ pipx install mitmproxy
|
|
|
260
284
|
context-lens cline
|
|
261
285
|
```
|
|
262
286
|
|
|
263
|
-
Cline is a Node.js process, so it uses `NODE_EXTRA_CA_CERTS` (not `SSL_CERT_FILE`) to trust the mitmproxy CA certificate
|
|
287
|
+
Cline is a Node.js process, so it uses `NODE_EXTRA_CA_CERTS` (not `SSL_CERT_FILE`) to trust the mitmproxy CA certificate; the CLI handles this automatically.
|
|
264
288
|
|
|
265
289
|
### OpenAI-Compatible Endpoints
|
|
266
290
|
|
|
@@ -274,7 +298,7 @@ UPSTREAM_OPENAI_URL=https://my-provider.com/v1 context-lens -- my-tool "prompt"
|
|
|
274
298
|
|
|
275
299
|
### Codex Subscription Mode
|
|
276
300
|
|
|
277
|
-
Codex with a ChatGPT subscription needs mitmproxy for HTTPS interception (Cloudflare blocks reverse proxies)
|
|
301
|
+
Codex with a ChatGPT subscription needs mitmproxy for HTTPS interception (Cloudflare blocks reverse proxies); the CLI handles this automatically. Just make sure `mitmdump` is installed:
|
|
278
302
|
|
|
279
303
|
```bash
|
|
280
304
|
pipx install mitmproxy
|
|
@@ -316,11 +340,11 @@ The CLI sets env vars like `ANTHROPIC_BASE_URL=http://localhost:4040` so the too
|
|
|
316
340
|
|
|
317
341
|
Tools like [Langfuse](https://langfuse.com/) and [Braintrust](https://braintrust.dev/) are great for observability when you control the code: you add their SDK, instrument your calls, and get traces in a dashboard. Context Lens solves a different problem.
|
|
318
342
|
|
|
319
|
-
|
|
343
|
+
Claude Code, Codex, Gemini CLI, and Aider are closed-source binaries; you can't add an SDK to them. Context Lens works as a transparent proxy, capturing everything without touching the tool's code.
|
|
320
344
|
|
|
321
|
-
|
|
345
|
+
Most observability tools show input/output token totals. Context Lens breaks down *what's inside* the context window: how much is system prompts, tool definitions, conversation history, tool results, thinking blocks. That breakdown is what you need to understand why sessions get expensive.
|
|
322
346
|
|
|
323
|
-
|
|
347
|
+
Everything runs on your machine. No accounts, no cloud, no data leaving your network.
|
|
324
348
|
|
|
325
349
|
| | Context Lens | Langfuse / Braintrust |
|
|
326
350
|
|:---|:---|:---|
|
package/dist/analysis/server.js
CHANGED
|
@@ -40,8 +40,8 @@ function resolveDataDir() {
|
|
|
40
40
|
return path.join(homedir(), ".context-lens", "data");
|
|
41
41
|
}
|
|
42
42
|
const dataDir = resolveDataDir();
|
|
43
|
-
const maxSessions = 200;
|
|
44
|
-
const maxCompactMessages = 60;
|
|
43
|
+
const maxSessions = parseInt(process.env.CONTEXT_LENS_MAX_SESSIONS || "200", 10);
|
|
44
|
+
const maxCompactMessages = parseInt(process.env.CONTEXT_LENS_MAX_COMPACT_MESSAGES || "60", 10);
|
|
45
45
|
// --- Setup ---
|
|
46
46
|
const store = new Store({
|
|
47
47
|
dataDir,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/analysis/server.ts"],"names":[],"mappings":";AAEA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,iBAAiB;AAEjB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,WAAW,CAAC;AACnE,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,0BAA0B,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AAE5E,MAAM,UAAU,GACd,OAAO,CAAC,GAAG,CAAC,wBAAwB;IACpC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;AAEpD,MAAM,UAAU,GAAG,CACjB,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,UAAU,CAC/C,CAAC,WAAW,EAAE,CAAC;AAChB,MAAM,OAAO,GACX,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;AAE9E,kFAAkF;AAClF,mEAAmE;AACnE,SAAS,cAAc;IACrB,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB;QACnC,OAAO,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IAE3C,sDAAsD;IACtD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACxD,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,8CAA8C,SAAS,EAAE,CAAC,CAAC;QACvE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;AAEjC,MAAM,WAAW,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/analysis/server.ts"],"names":[],"mappings":"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"}
|
package/dist/cli-utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-utils.d.ts","sourceRoot":"","sources":["../src/cli-utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAqB7C,QAAA,MAAM,oBAAoB,uCAAwC,CAAC;AACnE,KAAK,YAAY,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAM1D,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"cli-utils.d.ts","sourceRoot":"","sources":["../src/cli-utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAqB7C,QAAA,MAAM,oBAAoB,uCAAwC,CAAC;AACnE,KAAK,YAAY,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAM1D,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAqHD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAY1D;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CA0J1D;AAED,wBAAgB,cAAc,IAAI,MAAM,CAyEvC;AAGD,eAAO,MAAM,aAAa;;;;;;;;;CAUhB,CAAC"}
|
package/dist/cli-utils.js
CHANGED
|
@@ -63,6 +63,19 @@ const TOOL_CONFIG = {
|
|
|
63
63
|
serverEnv: {},
|
|
64
64
|
needsMitm: true,
|
|
65
65
|
},
|
|
66
|
+
copilot: {
|
|
67
|
+
// GitHub Copilot CLI (@github/copilot) supports COPILOT_API_URL to
|
|
68
|
+
// redirect all API traffic to a custom endpoint. We point it at the
|
|
69
|
+
// reverse proxy so captures work without mitmproxy.
|
|
70
|
+
//
|
|
71
|
+
// The proxy needs to forward openai-classified traffic to
|
|
72
|
+
// api.githubcopilot.com instead of api.openai.com, so we override
|
|
73
|
+
// UPSTREAM_OPENAI_URL in the server (proxy) environment.
|
|
74
|
+
childEnv: { COPILOT_API_URL: `${PROXY_URL}/copilot` },
|
|
75
|
+
extraArgs: [],
|
|
76
|
+
serverEnv: { UPSTREAM_OPENAI_URL: "https://api.githubcopilot.com" },
|
|
77
|
+
needsMitm: false,
|
|
78
|
+
},
|
|
66
79
|
aider: {
|
|
67
80
|
childEnv: {
|
|
68
81
|
ANTHROPIC_BASE_URL: `${PROXY_URL}/aider`,
|
|
@@ -102,7 +115,9 @@ const TOOL_CONFIG = {
|
|
|
102
115
|
PI_CODING_AGENT_DIR: PI_AGENT_DIR_PREFIX,
|
|
103
116
|
},
|
|
104
117
|
extraArgs: [],
|
|
105
|
-
|
|
118
|
+
// Allow x-target-url header so providers with non-standard upstreams
|
|
119
|
+
// (e.g. opencode, kilo) can tell the proxy their real destination URL.
|
|
120
|
+
serverEnv: { CONTEXT_LENS_ALLOW_TARGET_OVERRIDE: "1" },
|
|
106
121
|
needsMitm: false,
|
|
107
122
|
},
|
|
108
123
|
bryti: {
|
|
@@ -297,6 +312,7 @@ export function formatHelpText() {
|
|
|
297
312
|
" context-lens claude",
|
|
298
313
|
" context-lens codex",
|
|
299
314
|
" context-lens cline",
|
|
315
|
+
" context-lens copilot",
|
|
300
316
|
" context-lens opencode",
|
|
301
317
|
" context-lens gm",
|
|
302
318
|
" context-lens bryti",
|
|
@@ -338,6 +354,7 @@ export function formatHelpText() {
|
|
|
338
354
|
" - No command starts standalone mode (proxy + analysis/web UI by default).",
|
|
339
355
|
" - 'codex', 'cline', and 'opencode' use mitmproxy for HTTPS interception (requires mitmproxy; install: pipx install mitmproxy).",
|
|
340
356
|
" - 'cline' with Anthropic OAuth routes through api.cline.bot; mitmproxy intercepts that traffic.",
|
|
357
|
+
" - 'copilot' (GitHub Copilot CLI, @github/copilot) uses COPILOT_API_URL to redirect traffic through the proxy; no mitmproxy needed.",
|
|
341
358
|
" - 'pi --mitm' uses mitmproxy for full interception, useful for subscription-based models (openai-codex provider).",
|
|
342
359
|
" - 'doctor' is a local diagnostics command.",
|
|
343
360
|
" - 'background' manages detached proxy/web-ui processes.",
|
package/dist/cli-utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-utils.js","sourceRoot":"","sources":["../src/cli-utils.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"cli-utils.js","sourceRoot":"","sources":["../src/cli-utils.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
2
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
3
3
|
import { randomBytes } from "node:crypto";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import http from "node:http";
|
|
@@ -84,7 +84,10 @@ else if (!parsedArgs.commandName) {
|
|
|
84
84
|
const analysisPath = join(__dirname, "analysis", "server.js");
|
|
85
85
|
const proxy = spawn("node", [proxyPath], {
|
|
86
86
|
stdio: "inherit",
|
|
87
|
-
env: {
|
|
87
|
+
env: {
|
|
88
|
+
...process.env,
|
|
89
|
+
CONTEXT_LENS_ANALYSIS_URL: "http://localhost:4041",
|
|
90
|
+
},
|
|
88
91
|
});
|
|
89
92
|
const analysis = spawn("node", [analysisPath], {
|
|
90
93
|
stdio: "inherit",
|
|
@@ -244,6 +247,7 @@ else {
|
|
|
244
247
|
...toolConfig.serverEnv,
|
|
245
248
|
...process.env,
|
|
246
249
|
CONTEXT_LENS_CLI: "1",
|
|
250
|
+
CONTEXT_LENS_ANALYSIS_URL: "http://localhost:4041",
|
|
247
251
|
};
|
|
248
252
|
// Start proxy
|
|
249
253
|
if (proxyAlreadyRunning) {
|
|
@@ -404,8 +408,8 @@ else {
|
|
|
404
408
|
// Codex uses mitmproxy and has its own chaining via previous_response_id.
|
|
405
409
|
// Claude Code and Pi embed their own session IDs in request metadata.
|
|
406
410
|
// Tools without built-in session IDs (Gemini, Aider, custom) rely on this.
|
|
411
|
+
const sessionTag = randomBytes(4).toString("hex"); // 8 hex chars
|
|
407
412
|
if (!toolConfig.needsMitm) {
|
|
408
|
-
const sessionTag = randomBytes(4).toString("hex"); // 8 hex chars
|
|
409
413
|
// For bryti, the proxy URL is baked into config.yml (not an env var),
|
|
410
414
|
// so the session tag loop below won't reach it. Pass it to prepareBrytiDataDir
|
|
411
415
|
// so it can embed the tag directly into the patched config.yml base_url.
|
|
@@ -439,13 +443,19 @@ else {
|
|
|
439
443
|
childEnv.SSL_CERT_FILE = certPath;
|
|
440
444
|
if (childEnv.NODE_EXTRA_CA_CERTS === "")
|
|
441
445
|
childEnv.NODE_EXTRA_CA_CERTS = certPath;
|
|
446
|
+
// On macOS, Codex is compiled with rustls + native-roots, which reads
|
|
447
|
+
// the system Keychain and ignores SSL_CERT_FILE entirely. If the cert
|
|
448
|
+
// is not trusted in the Keychain, Codex cannot connect through mitmproxy.
|
|
449
|
+
if (platform() === "darwin" && commandName === "codex") {
|
|
450
|
+
warnIfMitmCertNotTrustedMacOs(certPath);
|
|
451
|
+
}
|
|
442
452
|
}
|
|
443
453
|
else {
|
|
444
454
|
console.error(`Warning: mitmproxy CA cert not found at ${certPath}. Run 'mitmdump' once to generate it.`);
|
|
445
455
|
}
|
|
446
456
|
}
|
|
447
457
|
if (commandName === "pi" && !useMitm) {
|
|
448
|
-
childEnv.PI_CODING_AGENT_DIR = preparePiAgentDir(childEnv.PI_CODING_AGENT_DIR);
|
|
458
|
+
childEnv.PI_CODING_AGENT_DIR = preparePiAgentDir(childEnv.PI_CODING_AGENT_DIR, sessionTag);
|
|
449
459
|
}
|
|
450
460
|
// For bryti: if dist/cli.js exists in cwd, use it directly (dev mode).
|
|
451
461
|
// Otherwise fall back to the globally installed bryti binary.
|
|
@@ -495,7 +505,12 @@ else {
|
|
|
495
505
|
if (Array.isArray(data.conversations) &&
|
|
496
506
|
data.conversations.length === 0) {
|
|
497
507
|
console.error("\n⚠️ No API traffic captured yet. If the tool is running, it may not be routing through the proxy.");
|
|
498
|
-
|
|
508
|
+
if (toolConfig.needsMitm) {
|
|
509
|
+
console.error(` Check that ${commandName} is routing through mitmproxy (https_proxy=http://localhost:8080).\n`);
|
|
510
|
+
}
|
|
511
|
+
else {
|
|
512
|
+
console.error(` Check that ${commandName} is using the proxy URL (http://localhost:4040).\n`);
|
|
513
|
+
}
|
|
499
514
|
}
|
|
500
515
|
}
|
|
501
516
|
catch { }
|
|
@@ -563,7 +578,7 @@ else {
|
|
|
563
578
|
// Relative path: resolve against the original agent dir
|
|
564
579
|
return resolve(baseDir, pkg);
|
|
565
580
|
}
|
|
566
|
-
function preparePiAgentDir(targetDirEnv) {
|
|
581
|
+
function preparePiAgentDir(targetDirEnv, sessionTag) {
|
|
567
582
|
const dirPrefix = targetDirEnv && targetDirEnv.length > 0
|
|
568
583
|
? targetDirEnv
|
|
569
584
|
: join(tmpdir(), "context-lens-pi-agent-");
|
|
@@ -610,22 +625,66 @@ else {
|
|
|
610
625
|
!Array.isArray(modelsConfig.providers)
|
|
611
626
|
? { ...modelsConfig.providers }
|
|
612
627
|
: {};
|
|
613
|
-
const proxyBaseUrl =
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
"
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
628
|
+
const proxyBaseUrl = sessionTag
|
|
629
|
+
? `${CLI_CONSTANTS.PROXY_URL}/pi/${sessionTag}`
|
|
630
|
+
: `${CLI_CONSTANTS.PROXY_URL}/pi`;
|
|
631
|
+
// These upstreams are natively understood by the proxy — no target
|
|
632
|
+
// override needed, the proxy routes them correctly by path/format.
|
|
633
|
+
const nativeUpstreams = new Set([
|
|
634
|
+
"https://api.anthropic.com",
|
|
635
|
+
"https://api.openai.com",
|
|
636
|
+
"https://generativelanguage.googleapis.com",
|
|
637
|
+
"https://cloudcode-pa.googleapis.com",
|
|
638
|
+
"https://us-central1-aiplatform.googleapis.com",
|
|
639
|
+
]);
|
|
640
|
+
// Rewrite every provider that has an external baseUrl, regardless of its
|
|
641
|
+
// key name. For providers whose upstream isn't natively known to the proxy,
|
|
642
|
+
// stash the real URL as x-target-url so the proxy forwards correctly.
|
|
643
|
+
for (const [key, value] of Object.entries(providers)) {
|
|
644
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
645
|
+
continue;
|
|
646
|
+
const provider = value;
|
|
647
|
+
const originalBaseUrl = typeof provider.baseUrl === "string" ? provider.baseUrl : null;
|
|
648
|
+
// Skip providers with no baseUrl or a local/relative URL
|
|
649
|
+
if (!originalBaseUrl || !originalBaseUrl.startsWith("http"))
|
|
650
|
+
continue;
|
|
651
|
+
// Skip providers already pointing at the proxy
|
|
652
|
+
if (originalBaseUrl.startsWith("http://localhost"))
|
|
653
|
+
continue;
|
|
654
|
+
const needsTargetOverride = !nativeUpstreams.has(originalBaseUrl.replace(/\/$/, ""));
|
|
655
|
+
const existingHeaders = provider.headers &&
|
|
656
|
+
typeof provider.headers === "object" &&
|
|
657
|
+
!Array.isArray(provider.headers)
|
|
658
|
+
? provider.headers
|
|
659
|
+
: {};
|
|
660
|
+
providers[key] = {
|
|
661
|
+
...provider,
|
|
662
|
+
baseUrl: proxyBaseUrl,
|
|
663
|
+
...(needsTargetOverride
|
|
624
664
|
? {
|
|
625
|
-
|
|
626
|
-
|
|
665
|
+
headers: {
|
|
666
|
+
...existingHeaders,
|
|
667
|
+
"x-target-url": originalBaseUrl,
|
|
668
|
+
},
|
|
627
669
|
}
|
|
628
|
-
: {
|
|
670
|
+
: {}),
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
// The old code explicitly wrote "anthropic" unconditionally; the rewrite
|
|
674
|
+
// in 83225d2 switched to iterating existing providers, which dropped this.
|
|
675
|
+
// Pi uses the built-in anthropic provider by default and it may not appear
|
|
676
|
+
// in models.json at all, so we must always inject it.
|
|
677
|
+
if (!providers.anthropic) {
|
|
678
|
+
providers.anthropic = {
|
|
679
|
+
baseUrl: proxyBaseUrl,
|
|
680
|
+
api: "anthropic-messages",
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
else {
|
|
684
|
+
const ap = providers.anthropic;
|
|
685
|
+
if (!String(ap.baseUrl ?? "").startsWith("http://localhost")) {
|
|
686
|
+
providers.anthropic = { ...ap, baseUrl: proxyBaseUrl };
|
|
687
|
+
}
|
|
629
688
|
}
|
|
630
689
|
fs.writeFileSync(targetModelsPath, `${JSON.stringify({ ...modelsConfig, providers }, null, 2)}\n`);
|
|
631
690
|
return targetDir;
|
|
@@ -762,17 +821,51 @@ else {
|
|
|
762
821
|
return targetDir;
|
|
763
822
|
}
|
|
764
823
|
}
|
|
824
|
+
// On macOS, Codex uses rustls with native-roots (the system Keychain) and
|
|
825
|
+
// completely ignores SSL_CERT_FILE. If the mitmproxy CA cert is not trusted
|
|
826
|
+
// in the Keychain, Codex will fail to connect through mitmproxy with a
|
|
827
|
+
// "stream disconnected before completion" error. Check and warn.
|
|
828
|
+
function warnIfMitmCertNotTrustedMacOs(certPath) {
|
|
829
|
+
try {
|
|
830
|
+
// `security verify-cert` exits 0 when the cert chain is trusted by macOS.
|
|
831
|
+
const result = spawnSync("security", ["verify-cert", "-c", certPath], {
|
|
832
|
+
stdio: "pipe",
|
|
833
|
+
});
|
|
834
|
+
if (result.status !== 0) {
|
|
835
|
+
console.error("\n⚠️ mitmproxy CA cert is not trusted in the macOS Keychain.");
|
|
836
|
+
console.error(" Codex uses the system certificate store (not SSL_CERT_FILE).");
|
|
837
|
+
console.error(" Run this once to trust it, then retry:");
|
|
838
|
+
console.error(` sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${certPath}\n`);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
catch {
|
|
842
|
+
// Non-fatal: if 'security' isn't available, skip the check.
|
|
843
|
+
}
|
|
844
|
+
}
|
|
765
845
|
// Open browser (cross-platform)
|
|
766
846
|
function openBrowser(url) {
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
847
|
+
let cmd;
|
|
848
|
+
let args;
|
|
849
|
+
if (platform() === "darwin") {
|
|
850
|
+
cmd = "open";
|
|
851
|
+
args = [url];
|
|
852
|
+
}
|
|
853
|
+
else if (platform() === "win32") {
|
|
854
|
+
// `start` is a cmd.exe built-in, not a standalone executable.
|
|
855
|
+
// Using `cmd /c start` works in all Windows shells including MSYS2/Git Bash.
|
|
856
|
+
cmd = "cmd";
|
|
857
|
+
args = ["/c", "start", url];
|
|
858
|
+
}
|
|
859
|
+
else {
|
|
860
|
+
cmd = "xdg-open";
|
|
861
|
+
args = [url];
|
|
862
|
+
}
|
|
863
|
+
const browserProcess = spawn(cmd, args, {
|
|
773
864
|
stdio: "ignore",
|
|
774
865
|
detached: true,
|
|
775
866
|
});
|
|
867
|
+
// Non-fatal: if the browser can't be opened, just continue.
|
|
868
|
+
browserProcess.on("error", () => { });
|
|
776
869
|
browserProcess.unref(); // Don't wait for browser to close
|
|
777
870
|
}
|
|
778
871
|
// Cleanup on exit
|
|
@@ -940,10 +1033,15 @@ async function backgroundStart(noUi) {
|
|
|
940
1033
|
if (existing)
|
|
941
1034
|
clearBackgroundState();
|
|
942
1035
|
const proxyPath = join(__dirname, "proxy", "server.js");
|
|
1036
|
+
const proxyEnv = {
|
|
1037
|
+
...process.env,
|
|
1038
|
+
CONTEXT_LENS_CLI: "1",
|
|
1039
|
+
...(noUi ? {} : { CONTEXT_LENS_ANALYSIS_URL: "http://localhost:4041" }),
|
|
1040
|
+
};
|
|
943
1041
|
const proxy = spawn("node", [proxyPath], {
|
|
944
1042
|
stdio: "ignore",
|
|
945
1043
|
detached: true,
|
|
946
|
-
env:
|
|
1044
|
+
env: proxyEnv,
|
|
947
1045
|
});
|
|
948
1046
|
proxy.unref();
|
|
949
1047
|
let analysis = null;
|
|
@@ -1133,9 +1231,21 @@ async function runDoctor() {
|
|
|
1133
1231
|
const mitmdumpPath = findBinaryOnPath("mitmdump");
|
|
1134
1232
|
info("mitmdump (Codex, pi --mitm)", mitmdumpPath ?? "not found (install: pipx install mitmproxy)");
|
|
1135
1233
|
const certPath = join(homedir(), ".mitmproxy", "mitmproxy-ca-cert.pem");
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1234
|
+
const certExists = fs.existsSync(certPath);
|
|
1235
|
+
info("mitm CA cert (Codex, pi --mitm)", certExists ? certPath : "not present (run 'mitmdump' once to generate)");
|
|
1236
|
+
if (certExists && platform() === "darwin") {
|
|
1237
|
+
try {
|
|
1238
|
+
const result = spawnSync("security", ["verify-cert", "-c", certPath], {
|
|
1239
|
+
stdio: "pipe",
|
|
1240
|
+
});
|
|
1241
|
+
info("mitm CA cert trusted in macOS Keychain", result.status === 0
|
|
1242
|
+
? "yes"
|
|
1243
|
+
: `NO — Codex will fail. Fix: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${certPath}`);
|
|
1244
|
+
}
|
|
1245
|
+
catch {
|
|
1246
|
+
// Non-fatal.
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1139
1249
|
const contextDir = join(homedir(), ".context-lens");
|
|
1140
1250
|
const dataDir = join(contextDir, "data");
|
|
1141
1251
|
report("context dir writable", checkWritableDir(contextDir), contextDir);
|