squeezr-ai 1.10.4 → 1.10.6

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
@@ -103,6 +103,8 @@ localhost:8080 (Squeezr proxy)
103
103
  Your provider's API (Anthropic / OpenAI / Google / Ollama)
104
104
  ```
105
105
 
106
+ **MCP tool results are compressed automatically.** Any tool result that passes through the proxy — including results from MCP servers (Linear, GitHub, Slack, planning tools, custom MCPs) — goes through the same compression pipeline. No configuration needed; Squeezr treats MCP tool results identically to built-in tools. In practice MCP responses are often large JSON payloads that compress 70-94%.
107
+
106
108
  Recent content is always preserved untouched — by default the last 3 tool results are never compressed. Your CLI always has full context for what it's currently working on.
107
109
 
108
110
  ---
package/bin/squeezr.js CHANGED
@@ -24,6 +24,7 @@ Usage:
24
24
  squeezr start Start the proxy
25
25
  squeezr setup One-time setup: auto-start on login + configure all CLIs
26
26
  squeezr stop Stop the running proxy
27
+ squeezr logs Show last 50 lines of the log file
27
28
  squeezr gain Show token savings stats
28
29
  squeezr gain --reset Reset saved stats
29
30
  squeezr discover Show pattern coverage report (proxy must be running)
@@ -46,6 +47,23 @@ function runNode(script, extraArgs = []) {
46
47
  child.on('exit', code => process.exit(code ?? 0))
47
48
  }
48
49
 
50
+ function showLogs() {
51
+ const logFile = path.join(os.homedir(), '.squeezr', 'squeezr.log')
52
+ if (!fs.existsSync(logFile)) {
53
+ console.log('No log file yet. Run: squeezr setup')
54
+ return
55
+ }
56
+ // Show last 50 lines
57
+ const lines = fs.readFileSync(logFile, 'utf-8').split('\n').filter(Boolean)
58
+ const tail = lines.slice(-50)
59
+ if (tail.length === 0) {
60
+ console.log('Log file is empty — no requests yet.')
61
+ return
62
+ }
63
+ console.log(`=== ${logFile} (last ${tail.length} lines) ===\n`)
64
+ console.log(tail.join('\n'))
65
+ }
66
+
49
67
  function stopProxy() {
50
68
  const port = process.env.SQUEEZR_PORT || 8080
51
69
  try {
@@ -156,14 +174,21 @@ function setupWindows() {
156
174
  }
157
175
 
158
176
  // 3. Start Squeezr right now as a detached background process (no window)
177
+ // Logs go to ~/.squeezr/squeezr.log
178
+ const logDir = path.join(os.homedir(), '.squeezr')
179
+ const logFile = path.join(logDir, 'squeezr.log')
180
+ fs.mkdirSync(logDir, { recursive: true })
181
+ const logFd = fs.openSync(logFile, 'a')
159
182
  const child = spawn(nodeExe, [distIndex], {
160
183
  detached: true,
161
- stdio: 'ignore',
184
+ stdio: ['ignore', logFd, logFd],
162
185
  windowsHide: true,
163
186
  cwd: ROOT,
164
187
  })
165
188
  child.unref()
189
+ fs.closeSync(logFd)
166
190
  console.log(` [ok] Squeezr started in background (pid ${child.pid})`)
191
+ console.log(` [ok] Logs → ${logFile}`)
167
192
 
168
193
  console.log(`
169
194
  Done!
@@ -292,6 +317,10 @@ switch (command) {
292
317
  stopProxy()
293
318
  break
294
319
 
320
+ case 'logs':
321
+ showLogs()
322
+ break
323
+
295
324
  case 'gain':
296
325
  runNode('gain.js', args.slice(1))
297
326
  break
package/dist/gain.js CHANGED
@@ -27,21 +27,30 @@ const savedChars = data.total_saved_chars;
27
27
  const originalChars = data.total_original_chars;
28
28
  const CHARS_PER_TOKEN = 3.5;
29
29
  const savedTokens = Math.round(savedChars / CHARS_PER_TOKEN);
30
- const pct = originalChars > 0 ? Math.round((savedChars / originalChars) * 1000) / 10 : 0;
31
30
  const byTool = (data.by_tool ?? {});
31
+ // Savings % on tool results only (what Squeezr actually compresses).
32
+ // Using total context chars gives a misleadingly low number because the
33
+ // denominator includes user messages, Claude responses, and history
34
+ // re-sent on every request — none of which Squeezr touches.
35
+ const toolOriginal = Object.values(byTool).reduce((s, d) => s + d.originalChars, 0);
36
+ const toolSaved = Object.values(byTool).reduce((s, d) => s + d.savedChars, 0);
37
+ const toolPct = toolOriginal > 0 ? Math.round((toolSaved / toolOriginal) * 1000) / 10 : 0;
38
+ // Context reduction: how much smaller the overall payload became
39
+ const ctxPct = originalChars > 0 ? Math.round((savedChars / originalChars) * 1000) / 10 : 0;
32
40
  console.log('┌─────────────────────────────────────────┐');
33
41
  console.log('│ Squeezr — Token Savings │');
34
42
  console.log('├─────────────────────────────────────────┤');
35
- console.log(`│ Requests ${String(requests).padEnd(26)}│`);
36
- console.log(`│ Saved chars ${String(savedChars.toLocaleString()).padEnd(26)}│`);
37
- console.log(`│ Saved tokens ${String(savedTokens.toLocaleString()).padEnd(26)}│`);
38
- console.log(`│ Savings ${String(`${pct}%`).padEnd(26)}│`);
43
+ console.log(`│ Requests ${String(requests).padEnd(23)}│`);
44
+ console.log(`│ Saved chars ${String(savedChars.toLocaleString()).padEnd(23)}│`);
45
+ console.log(`│ Saved tokens ${String(savedTokens.toLocaleString()).padEnd(23)}│`);
46
+ console.log(`│ Tool savings ${String(`${toolPct}%`).padEnd(23)}│`);
47
+ console.log(`│ Context reduction ${String(`${ctxPct}%`).padEnd(22)}│`);
39
48
  if (Object.keys(byTool).length > 0) {
40
49
  console.log('├─────────────────────────────────────────┤');
41
50
  console.log('│ By Tool │');
42
- for (const [tool, d] of Object.entries(byTool)) {
43
- const toolPct = d.originalChars > 0 ? Math.round((d.savedChars / d.originalChars) * 1000) / 10 : 0;
44
- const line = ` ${tool} (${d.count}x): -${toolPct}%`;
51
+ for (const [tool, d] of Object.entries(byTool).sort((a, b) => b[1].savedChars - a[1].savedChars)) {
52
+ const pct = d.originalChars > 0 ? Math.round((d.savedChars / d.originalChars) * 1000) / 10 : 0;
53
+ const line = ` ${tool} (${d.count}x): -${pct}%`;
45
54
  console.log(`│${line.padEnd(41)}│`);
46
55
  }
47
56
  }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "1.10.4";
1
+ export declare const VERSION = "1.10.6";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = '1.10.4';
1
+ export const VERSION = '1.10.6';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "squeezr-ai",
3
- "version": "1.10.4",
3
+ "version": "1.10.6",
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",