squeezr-ai 1.16.0 → 1.16.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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Token compression proxy for AI coding CLIs.** Sits between your CLI and the API, compresses context on the fly, saves thousands of tokens per session.
4
4
 
5
- [![npm](https://img.shields.io/npm/v/squeezr-ai)](https://www.npmjs.com/package/squeezr-ai) [![license](https://img.shields.io/npm/l/squeezr-ai)](LICENSE) [![tests](https://img.shields.io/badge/tests-190%20passing-brightgreen)]()
5
+ [![npm](https://img.shields.io/npm/v/squeezr-ai)](https://www.npmjs.com/package/squeezr-ai) [![license](https://img.shields.io/npm/l/squeezr-ai)](LICENSE) [![tests](https://img.shields.io/badge/tests-219%20passing-brightgreen)]()
6
6
 
7
7
  ## Supported CLIs
8
8
 
@@ -24,7 +24,7 @@ squeezr start
24
24
  ```
25
25
 
26
26
  `squeezr setup` handles everything automatically:
27
- - Sets `ANTHROPIC_BASE_URL`, `GEMINI_API_BASE_URL`, `HTTPS_PROXY`, `NODE_EXTRA_CA_CERTS`, `NO_PROXY`
27
+ - Sets `ANTHROPIC_BASE_URL`, `GEMINI_API_BASE_URL`, `HTTPS_PROXY`, `NODE_EXTRA_CA_CERTS`
28
28
  - Registers auto-start (launchd on macOS, systemd on Linux, Task Scheduler/NSSM on Windows)
29
29
  - **Windows:** imports the MITM CA into the Windows Certificate Store (user-level, no admin required) so Rust-based CLIs like Codex trust the proxy's TLS certificates
30
30
  - **macOS/Linux:** generates a CA bundle at `~/.squeezr/mitm-ca/bundle.crt` for `SSL_CERT_FILE`
@@ -92,6 +92,8 @@ Compression aggressiveness scales with context window usage:
92
92
 
93
93
  Codex uses WebSocket over TLS to `chatgpt.com` with OAuth authentication — it cannot be proxied via `OPENAI_BASE_URL`. Squeezr runs a TLS-terminating MITM proxy on port 8081 that intercepts and compresses WebSocket frames. See [CODEX.md](CODEX.md) for the full technical breakdown.
94
94
 
95
+ The MITM proxy **only intercepts `chatgpt.com`** traffic. All other HTTPS requests (npm, git, curl, etc.) pass through as a transparent TCP tunnel — no certificate needed, no interference.
96
+
95
97
  ## Configuration
96
98
 
97
99
  ### Global config: `squeezr.toml` (next to the binary)
@@ -169,7 +171,7 @@ Squeezr uses cheap/free models for AI compression (the deterministic layer is pu
169
171
 
170
172
  ```bash
171
173
  squeezr setup # configure env vars, auto-start, CA trust
172
- squeezr start # start the proxy (foreground)
174
+ squeezr start # start the proxy (auto-restarts if version mismatch after update)
173
175
  squeezr stop # stop the proxy
174
176
  squeezr status # check if proxy is running
175
177
  squeezr logs # show last 50 log lines
package/bin/squeezr.js CHANGED
@@ -16,6 +16,15 @@ const pkg = require(path.join(ROOT, 'package.json'))
16
16
  const args = process.argv.slice(2)
17
17
  const command = args[0]
18
18
 
19
+ function getPortFromToml() {
20
+ try {
21
+ const toml = fs.readFileSync(path.join(ROOT, 'squeezr.toml'), 'utf-8')
22
+ const m = toml.match(/^port\s*=\s*(\d+)/m)
23
+ if (m) return parseInt(m[1])
24
+ } catch {}
25
+ return null
26
+ }
27
+
19
28
  function getMitmPort(port) {
20
29
  const envMitm = process.env.SQUEEZR_MITM_PORT
21
30
  if (envMitm) return parseInt(envMitm)
@@ -27,6 +36,10 @@ function getMitmPort(port) {
27
36
  return Number(port) + 1
28
37
  }
29
38
 
39
+ function getPort() {
40
+ return process.env.SQUEEZR_PORT || getPortFromToml() || 8080
41
+ }
42
+
30
43
  const HELP = `
31
44
  Squeezr v${pkg.version} — AI context compressor for Claude Code, Codex, Aider, Gemini CLI and Ollama
32
45
 
@@ -68,7 +81,7 @@ async function startDaemon() {
68
81
  }
69
82
 
70
83
  // Check if already running — and if the version matches
71
- const port = process.env.SQUEEZR_PORT || 8080
84
+ const port = getPort()
72
85
  const runningVersion = await new Promise(resolve => {
73
86
  const req = http.get(`http://localhost:${port}/squeezr/health`, res => {
74
87
  let data = ''
@@ -134,7 +147,7 @@ function showLogs() {
134
147
  }
135
148
 
136
149
  function stopProxy() {
137
- const port = process.env.SQUEEZR_PORT || 8080
150
+ const port = getPort()
138
151
  const mitmPort = getMitmPort(port)
139
152
  const ports = [port, mitmPort]
140
153
  let killed = false
@@ -164,19 +177,22 @@ function stopProxy() {
164
177
  } else {
165
178
  execSync(`kill -9 ${pid}`, { stdio: 'pipe' })
166
179
  }
167
- console.log(`Squeezr stopped (pid ${pid} on port ${p})`)
168
180
  killed = true
169
181
  } catch {}
170
182
  }
171
183
  } catch {}
172
184
  }
173
- if (!killed) {
174
- console.log(`Squeezr is not running on port ${port}`)
185
+ if (killed) {
186
+ console.log(`Squeezr stopped`)
187
+ console.log(` HTTP proxy (Claude/Aider/Gemini): http://localhost:${port}`)
188
+ console.log(` MITM proxy (Codex): http://localhost:${mitmPort}`)
189
+ } else {
190
+ console.log(`Squeezr is not running`)
175
191
  }
176
192
  }
177
193
 
178
194
  async function checkStatus() {
179
- const port = process.env.SQUEEZR_PORT || 8080
195
+ const port = getPort()
180
196
  const mitmPort = getMitmPort(port)
181
197
  return new Promise(resolve => {
182
198
  const req = http.get(`http://localhost:${port}/squeezr/health`, res => {
@@ -281,15 +297,59 @@ async function configurePorts() {
281
297
  try { execSync(`setx HTTPS_PROXY "http://localhost:${finalMitm}"`, { stdio: 'pipe' }) } catch {}
282
298
  console.log('Environment variables updated. Restart your terminal for changes to take effect.')
283
299
  } else {
284
- console.log(`\nUpdate your shell profile:`)
285
- console.log(` export SQUEEZR_PORT=${finalPort}`)
286
- console.log(` export SQUEEZR_MITM_PORT=${finalMitm}`)
287
- console.log(` export ANTHROPIC_BASE_URL=http://localhost:${finalPort}`)
288
- console.log(` export HTTPS_PROXY=http://localhost:${finalMitm}`)
300
+ // Update shell profiles directly
301
+ const profiles = [
302
+ path.join(os.homedir(), '.zshrc'),
303
+ path.join(os.homedir(), '.bashrc'),
304
+ path.join(os.homedir(), '.bash_profile'),
305
+ ]
306
+ const envBlock = [
307
+ `export SQUEEZR_PORT=${finalPort}`,
308
+ `export SQUEEZR_MITM_PORT=${finalMitm}`,
309
+ `export ANTHROPIC_BASE_URL=http://localhost:${finalPort}`,
310
+ `export GEMINI_API_BASE_URL=http://localhost:${finalPort}`,
311
+ `export HTTPS_PROXY=http://localhost:${finalMitm}`,
312
+ ].join('\n')
313
+ for (const p of profiles) {
314
+ try {
315
+ let content = fs.readFileSync(p, 'utf-8')
316
+ if (content.includes('# squeezr env vars')) {
317
+ // Replace existing block (from marker to the closing fi)
318
+ content = content.replace(
319
+ /# squeezr env vars[\s\S]*?fi/,
320
+ `# squeezr env vars\n${envBlock}\n# squeezr auto-heal\nif ! curl -sf http://localhost:${finalPort}/squeezr/health > /dev/null 2>&1; then squeezr start > /dev/null 2>&1; fi`
321
+ )
322
+ fs.writeFileSync(p, content)
323
+ console.log(` [ok] Updated ${p}`)
324
+ }
325
+ } catch {}
326
+ }
327
+ // Also update env for WSL setx if on WSL
328
+ try {
329
+ const procVersion = fs.readFileSync('/proc/version', 'utf-8')
330
+ if (/microsoft|wsl/i.test(procVersion)) {
331
+ const setx = '/mnt/c/Windows/System32/setx.exe'
332
+ try { execSync(`"${setx}" SQUEEZR_PORT "${finalPort}"`, { stdio: 'pipe' }) } catch {}
333
+ try { execSync(`"${setx}" SQUEEZR_MITM_PORT "${finalMitm}"`, { stdio: 'pipe' }) } catch {}
334
+ try { execSync(`"${setx}" ANTHROPIC_BASE_URL "http://localhost:${finalPort}"`, { stdio: 'pipe' }) } catch {}
335
+ try { execSync(`"${setx}" GEMINI_API_BASE_URL "http://localhost:${finalPort}"`, { stdio: 'pipe' }) } catch {}
336
+ try { execSync(`"${setx}" HTTPS_PROXY "http://localhost:${finalMitm}"`, { stdio: 'pipe' }) } catch {}
337
+ }
338
+ } catch {}
289
339
  }
290
340
 
291
- console.log(`\nRestart squeezr for changes to take effect:`)
292
- console.log(` squeezr stop && squeezr start`)
341
+ // Apply to current process so stop/start works immediately
342
+ process.env.SQUEEZR_PORT = String(finalPort)
343
+ process.env.SQUEEZR_MITM_PORT = String(finalMitm)
344
+ process.env.ANTHROPIC_BASE_URL = `http://localhost:${finalPort}`
345
+ process.env.HTTPS_PROXY = `http://localhost:${finalMitm}`
346
+
347
+ // Auto stop + start
348
+ console.log('')
349
+ stopProxy()
350
+ await new Promise(r => setTimeout(r, 1500))
351
+ await startDaemon()
352
+ console.log(`\nOpen a new terminal for env vars to apply to other tools.`)
293
353
  }
294
354
 
295
355
  // ── squeezr uninstall ─────────────────────────────────────────────────────────
@@ -390,7 +450,7 @@ function setupWindows() {
390
450
  console.log('Setting up Squeezr for Windows...\n')
391
451
 
392
452
  // 1. Set env vars permanently via setx (user scope, no admin needed)
393
- const port = process.env.SQUEEZR_PORT || 8080
453
+ const port = getPort()
394
454
  const mitmPort = getMitmPort(port)
395
455
  const caPath = path.join(os.homedir(), '.squeezr', 'mitm-ca', 'ca.crt')
396
456
  const vars = {
@@ -545,7 +605,7 @@ function setupUnix() {
545
605
 
546
606
  // 1. Set env vars + auto-heal guard in shell profile
547
607
  const distIndex = path.join(ROOT, 'dist', 'index.js')
548
- const port = process.env.SQUEEZR_PORT || 8080
608
+ const port = getPort()
549
609
  const mitmPort = getMitmPort(port)
550
610
  const bundlePath = path.join(os.homedir(), '.squeezr', 'mitm-ca', 'bundle.crt')
551
611
  const shellBlock = [
@@ -678,7 +738,7 @@ function setupWSL() {
678
738
  // The guard checks if the proxy is alive on terminal open. If not, it starts
679
739
  // it in the background. This is the safety net for WSL2 where systemd and
680
740
  // Task Scheduler may both fail.
681
- const port = process.env.SQUEEZR_PORT || 8080
741
+ const port = getPort()
682
742
  const mitmPort = getMitmPort(port)
683
743
  const bundlePath = path.join(os.homedir(), '.squeezr', 'mitm-ca', 'bundle.crt')
684
744
  const shellBlock = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "squeezr-ai",
3
- "version": "1.16.0",
3
+ "version": "1.16.2",
4
4
  "description": "AI proxy that compresses Claude Code, Codex, Aider, Gemini CLI and Ollama context windows to save thousands of tokens per session",
5
5
  "keywords": [
6
6
  "claude",