@polderlabs/bizar 10.0.7 → 10.1.0

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.
Files changed (32) hide show
  1. package/bizar-dash/src/server/api.mjs +2 -6
  2. package/bizar-dash/src/server/diagnostics-store.mjs +5 -35
  3. package/bizar-dash/src/server/mod-security.mjs +1 -2
  4. package/bizar-dash/src/server/providers-store.mjs +1 -1
  5. package/bizar-dash/src/server/routes/_shared.mjs +0 -17
  6. package/bizar-dash/src/server/routes/model-router.mjs +103 -0
  7. package/bizar-dash/src/server/routes/model-router.test.mjs +76 -0
  8. package/bizar-dash/src/server/server.mjs +1 -27
  9. package/bizar-dash/tests/cli-bugfixes.test.mjs +1 -1
  10. package/bizar-dash/tests/cli-error-visibility.test.mjs +1 -1
  11. package/bizar-dash/tests/cli-refactor.test.mjs +0 -1
  12. package/bizar-dash/tests/diagnostics-store.test.mjs +0 -1
  13. package/cli/bin.mjs +1 -15
  14. package/cli/cli-commands-validation.test.mjs +1 -1
  15. package/cli/commands/lightrag.mjs +1 -1
  16. package/cli/commands/util.mjs +1 -1
  17. package/cli/copy.mjs +1 -47
  18. package/cli/doctor.mjs +3 -3
  19. package/cli/install.mjs +3 -37
  20. package/cli/service-controller.mjs +0 -192
  21. package/cli/service-env.mjs +2 -9
  22. package/cli/utils.mjs +0 -7
  23. package/package.json +1 -1
  24. package/packages/sdk/package.json +1 -1
  25. package/scripts/check-deps.mjs +0 -24
  26. package/bizar-dash/skills/headroom/SKILL.md +0 -94
  27. package/bizar-dash/src/server/headroom.mjs +0 -649
  28. package/bizar-dash/src/server/routes/headroom.mjs +0 -126
  29. package/bizar-dash/tests/headroom-install.test.mjs +0 -173
  30. package/bizar-dash/tests/headroom-settings.test.mjs +0 -126
  31. package/bizar-dash/tests/headroom-status.test.mjs +0 -117
  32. package/cli/commands/headroom.mjs +0 -204
@@ -102,9 +102,6 @@ function linuxUnitPath() {
102
102
  function linuxEnvPath() {
103
103
  return join(bizarConfigDir(), 'service.env');
104
104
  }
105
- function linuxHeadroomUnitPath() {
106
- return join(userUnitDir(), 'bizar-headroom.service');
107
- }
108
105
  function darwinPlistPath() {
109
106
  return join(launchAgentsDir(), 'com.bizar.dashboard.plist');
110
107
  }
@@ -178,161 +175,6 @@ function linuxEnvFileContent({ projectRoot }) {
178
175
  return buildServiceEnvFile({ bizarHome: bizarConfigDir(), repoPath: projectRoot });
179
176
  }
180
177
 
181
- // ── Headroom companion service (Linux) ─────────────────────────────────────────
182
-
183
- function linuxHeadroomUnitContent() {
184
- const envPath = join(bizarConfigDir(), 'service.env');
185
- return [
186
- '[Unit]',
187
- 'Description=Bizar Headroom context-compression proxy',
188
- 'After=bizar.service',
189
- 'Wants=bizar.service',
190
- '',
191
- '[Service]',
192
- 'Type=simple',
193
- `EnvironmentFile=${envPath}`,
194
- 'ExecStart=/bin/sh -c "command -v headroom >/dev/null 2>&1 && headroom proxy cline || exit 0"',
195
- 'Restart=on-failure',
196
- 'RestartSec=10',
197
- 'TimeoutStopSec=15',
198
- '',
199
- '[Install]',
200
- 'WantedBy=default.target',
201
- '',
202
- ].join('\n');
203
- }
204
-
205
- function darwinHeadroomPlistPath() {
206
- return join(launchAgentsDir(), 'com.bizar.headroom.plist');
207
- }
208
-
209
- function darwinHeadroomPlistContent({ nodePath, projectRoot }) {
210
- const envContent = buildServiceEnvFile({ bizarHome: bizarConfigDir(), repoPath: projectRoot });
211
- const envVars = parseEnvFile(envContent);
212
- const envXml = envVars
213
- .map(([k, v]) => ` <key>${xmlEscape(k)}</key>\n <string>${xmlEscape(v)}</string>`)
214
- .join('\n');
215
- return [
216
- '<?xml version="1.0" encoding="UTF-8"?>',
217
- '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
218
- '<plist version="1.0">',
219
- '<dict>',
220
- ' <key>Label</key>',
221
- ' <string>com.bizar.headroom</string>',
222
- ' <key>ProgramArguments</key>',
223
- ' <array>',
224
- ` <string>${xmlEscape(nodePath)}</string>`,
225
- ' <string>-c</string>',
226
- ' <string>command -v headroom >/dev/null 2>&1 && headroom proxy cline || exit 0</string>',
227
- ' </array>',
228
- ' <key>EnvironmentVariables</key>',
229
- ' <dict>',
230
- envXml,
231
- ' </dict>',
232
- ' <key>KeepAlive</key>',
233
- ' <true/>',
234
- ' <key>RunAtLoad</key>',
235
- ' <true/>',
236
- ' <key>StandardOutPath</key>',
237
- ` <string>${xmlEscape(join(bizarConfigDir(), 'headroom.log'))}</string>`,
238
- ' <key>StandardErrorPath</key>',
239
- ` <string>${xmlEscape(join(bizarConfigDir(), 'headroom.log'))}</string>`,
240
- ' <key>WorkingDirectory</key>',
241
- ` <string>${xmlEscape(projectRoot)}</string>`,
242
- '</dict>',
243
- '</plist>',
244
- '',
245
- ].join('\n');
246
- }
247
-
248
- function installHeadroomServiceLinux({ force = false }) {
249
- // Honour BIZAR_HEADROOM_AUTOSTART from process.env (already merged by buildServiceEnvFile)
250
- const headroomAutoStart = process.env.BIZAR_HEADROOM_AUTOSTART !== '0';
251
- if (!headroomAutoStart) {
252
- return ok({ note: 'headroom autostart disabled via BIZAR_HEADROOM_AUTOSTART=0' });
253
- }
254
- if (!existsSync(userUnitDir())) {
255
- try { mkdirSync(userUnitDir(), { recursive: true }); } catch (err) {
256
- return fail(`cannot create ${userUnitDir()}: ${err.message}`);
257
- }
258
- }
259
- const unitPath = linuxHeadroomUnitPath();
260
- const want = linuxHeadroomUnitContent();
261
- if (!force && existsSync(unitPath)) {
262
- const have = readFileSync(unitPath, 'utf8').trim() + '\n';
263
- if (have === want.trim() + '\n') {
264
- return ok({ alreadyInstalled: true, unitPath, note: 'headroom unit already matches' });
265
- }
266
- }
267
- try {
268
- writeFileSync(unitPath, want, { encoding: 'utf8', mode: 0o644 });
269
- } catch (err) {
270
- return fail(`write ${unitPath}: ${err.message}`);
271
- }
272
- runCmd('systemctl', ['--user', 'daemon-reload']);
273
- const r = runCmd('systemctl', ['--user', 'enable', '--now', 'bizar-headroom.service']);
274
- if (r.error || (r.status !== 0 && r.status !== null)) {
275
- return fail(`headroom service enable failed: ${r.stderr || r.error?.message || `exit ${r.status}`}`, { unitPath });
276
- }
277
- return ok({ unitPath, note: 'headroom companion service installed and started' });
278
- }
279
-
280
- function uninstallHeadroomServiceLinux() {
281
- const unitPath = linuxHeadroomUnitPath();
282
- if (!existsSync(unitPath)) {
283
- return ok({ unitPath: null, note: 'no headroom systemd unit installed' });
284
- }
285
- runCmd('systemctl', ['--user', 'disable', '--now', 'bizar-headroom.service']);
286
- try { unlinkSync(unitPath); } catch { /* ignore */ }
287
- runCmd('systemctl', ['--user', 'daemon-reload']);
288
- return ok({ unitPath: null, note: 'headroom systemd unit removed' });
289
- }
290
-
291
- function installHeadroomServiceDarwin({ nodePath, projectRoot, force = false }) {
292
- const headroomAutoStart = process.env.BIZAR_HEADROOM_AUTOSTART !== '0';
293
- if (!headroomAutoStart) {
294
- return ok({ note: 'headroom autostart disabled via BIZAR_HEADROOM_AUTOSTART=0' });
295
- }
296
- const dir = launchAgentsDir();
297
- if (!existsSync(dir)) {
298
- try { mkdirSync(dir, { recursive: true }); } catch (err) {
299
- return fail(`cannot create ${dir}: ${err.message}`);
300
- }
301
- }
302
- const plistPath = darwinHeadroomPlistPath();
303
- const want = darwinHeadroomPlistContent({ nodePath, projectRoot });
304
- if (!force && existsSync(plistPath)) {
305
- const have = readFileSync(plistPath, 'utf8').trim() + '\n';
306
- if (have === want.trim() + '\n') {
307
- const lst = runCmd('launchctl', ['list']);
308
- if (lst.status === 0 && /com\.bizar\.headroom/.test(lst.stdout)) {
309
- return ok({ alreadyInstalled: true, unitPath: plistPath, note: 'headroom plist matches and is loaded' });
310
- }
311
- }
312
- }
313
- try {
314
- writeFileSync(plistPath, want, { encoding: 'utf8', mode: 0o644 });
315
- try { chmodSync(plistPath, 0o644); } catch { /* best-effort */ }
316
- } catch (err) {
317
- return fail(`write ${plistPath}: ${err.message}`);
318
- }
319
- runCmd('launchctl', ['unload', plistPath]);
320
- const load = runCmd('launchctl', ['load', '-w', plistPath]);
321
- if (load.error || (load.status !== 0 && load.status !== null)) {
322
- return fail(`launchctl load failed for headroom: ${load.stderr || load.error?.message || `exit ${load.status}`}`, { unitPath: plistPath });
323
- }
324
- return ok({ unitPath: plistPath, note: 'headroom companion plist installed and loaded' });
325
- }
326
-
327
- function uninstallHeadroomServiceDarwin() {
328
- const plistPath = darwinHeadroomPlistPath();
329
- if (!existsSync(plistPath)) {
330
- return ok({ unitPath: null, note: 'no headroom launchd plist installed' });
331
- }
332
- runCmd('launchctl', ['unload', plistPath]);
333
- try { unlinkSync(plistPath); } catch { /* ignore */ }
334
- return ok({ unitPath: null, note: 'headroom launchd plist removed' });
335
- }
336
178
 
337
179
  function installServiceLinux({ nodePath, projectRoot, force = false }) {
338
180
  if (!existsSync(userUnitDir())) {
@@ -393,13 +235,6 @@ function installServiceLinux({ nodePath, projectRoot, force = false }) {
393
235
  return fail(`systemctl --user enable --now failed: ${r.stderr || r.error?.message || `exit ${r.status}`}`, { unitPath });
394
236
  }
395
237
 
396
- // Also install headroom companion service (non-fatal if it fails)
397
- const hr = installHeadroomServiceLinux({ force });
398
- if (!hr.ok) {
399
- // Non-fatal: headroom is optional
400
- console.log(` ${hr.error || 'headroom companion install failed'}`);
401
- }
402
-
403
238
  return ok({
404
239
  unitPath,
405
240
  note: 'systemd user unit installed and started (or already running)',
@@ -562,12 +397,6 @@ function installServiceDarwin({ nodePath, projectRoot, force = false }) {
562
397
  return fail(`launchctl load failed: ${load.stderr || load.error?.message || `exit ${load.status}`}`, { unitPath: plistPath });
563
398
  }
564
399
 
565
- // Also install headroom companion service (non-fatal if it fails)
566
- const hr = installHeadroomServiceDarwin({ nodePath, projectRoot, force });
567
- if (!hr.ok) {
568
- console.log(` ${hr.error || 'headroom companion install failed'}`);
569
- }
570
-
571
400
  return ok({ unitPath: plistPath, note: 'plist installed and loaded' });
572
401
  }
573
402
 
@@ -755,30 +584,9 @@ export function uninstallService() {
755
584
  else if (PLATFORM === 'darwin') result = uninstallServiceDarwin();
756
585
  else if (PLATFORM === 'win32') result = uninstallServiceWindows();
757
586
  else return fail(`unsupported platform: ${PLATFORM}`);
758
- // Also uninstall headroom companion
759
- if (PLATFORM === 'linux') uninstallHeadroomServiceLinux();
760
- if (PLATFORM === 'darwin') uninstallHeadroomServiceDarwin();
761
587
  return result;
762
588
  }
763
589
 
764
- /**
765
- * Install the headroom companion service only (does NOT install the
766
- * main dashboard service). Idempotent. Safe to re-run.
767
- */
768
- export function installHeadroomService(opts = {}) {
769
- const nodePath = resolveNodePath(opts.nodePath);
770
- const projectRoot = resolveRepoRoot(opts.projectRoot);
771
- if (PLATFORM === 'linux') return installHeadroomServiceLinux({ force: !!opts.force });
772
- if (PLATFORM === 'darwin') return installHeadroomServiceDarwin({ nodePath, projectRoot, force: !!opts.force });
773
- return ok({ note: `headroom companion not supported on ${PLATFORM}` });
774
- }
775
-
776
- export function uninstallHeadroomService() {
777
- if (PLATFORM === 'linux') return uninstallHeadroomServiceLinux();
778
- if (PLATFORM === 'darwin') return uninstallHeadroomServiceDarwin();
779
- return ok({ note: `headroom companion not supported on ${PLATFORM}` });
780
- }
781
-
782
590
  /**
783
591
  * v5.x — Restart the service (issue #7).
784
592
  *
@@ -4,7 +4,7 @@
4
4
  * v5.x — Central env file builder for the Bizar service.
5
5
  *
6
6
  * Produces the content for `~/.config/bizar/service.env` (mode 0600),
7
- * which is sourced by the systemd/launchd service and the headroom companion.
7
+ * which is sourced by the systemd/launchd service.
8
8
  *
9
9
  * All BIZAR_* vars are written here so the service has a consistent view
10
10
  * of the environment. Values already present in `process.env` are honoured
@@ -31,7 +31,6 @@ export function defaultBizarEnv() {
31
31
  BIZAR_DASHBOARD_PORT: '4097',
32
32
  BIZAR_DASHBOARD_HOST: '127.0.0.1',
33
33
  BIZAR_LOG_LEVEL: 'info',
34
- BIZAR_HEADROOM_AUTOSTART: '1',
35
34
  BIZAR_LIGHTRAG_AUTOSTART: '1',
36
35
  BIZAR_MEMORY_VAULT: join(home, '.bizar_memory'),
37
36
  CLINE_SERVER_PASSWORD: '',
@@ -77,11 +76,10 @@ function generatePassword() {
77
76
  * @param {object} opts
78
77
  * @param {string} [opts.bizarHome] – default: ~/.config/bizar
79
78
  * @param {string} [opts.repoPath] – absolute path to the repo root
80
- * @param {boolean} [opts.headroomAutoStart] – default: true
81
79
  * @param {boolean} [opts.lightragAutoStart] – default: true
82
80
  * @returns {string} env file content (does NOT write to disk)
83
81
  */
84
- export function buildServiceEnvFile({ bizarHome, repoPath, headroomAutoStart = true, lightragAutoStart = true } = {}) {
82
+ export function buildServiceEnvFile({ bizarHome, repoPath, lightragAutoStart = true } = {}) {
85
83
  const home = homedir();
86
84
  const defaults = defaultBizarEnv();
87
85
 
@@ -91,11 +89,6 @@ export function buildServiceEnvFile({ bizarHome, repoPath, headroomAutoStart = t
91
89
  BIZAR_DASHBOARD_PORT: process.env.BIZAR_DASHBOARD_PORT || defaults.BIZAR_DASHBOARD_PORT,
92
90
  BIZAR_DASHBOARD_HOST: process.env.BIZAR_DASHBOARD_HOST || defaults.BIZAR_DASHBOARD_HOST,
93
91
  BIZAR_LOG_LEVEL: process.env.BIZAR_LOG_LEVEL || defaults.BIZAR_LOG_LEVEL,
94
- BIZAR_HEADROOM_AUTOSTART: String(
95
- process.env.BIZAR_HEADROOM_AUTOSTART !== undefined
96
- ? (process.env.BIZAR_HEADROOM_AUTOSTART === '1' || process.env.BIZAR_HEADROOM_AUTOSTART === 'true' ? '1' : '0')
97
- : (headroomAutoStart ? '1' : '0')
98
- ),
99
92
  BIZAR_LIGHTRAG_AUTOSTART: String(
100
93
  process.env.BIZAR_LIGHTRAG_AUTOSTART !== undefined
101
94
  ? (process.env.BIZAR_LIGHTRAG_AUTOSTART === '1' || process.env.BIZAR_LIGHTRAG_AUTOSTART === 'true' ? '1' : '0')
package/cli/utils.mjs CHANGED
@@ -121,13 +121,6 @@ export async function detectClaude() {
121
121
  return { exists, version, configDir: claudeConfigDir(), agentsDir: claudeAgentsDir() };
122
122
  }
123
123
 
124
- export async function detectHeadroom() {
125
- return commandExists('headroom');
126
- }
127
-
128
- // Alias for backward-compat during migration
129
- export const detectRtk = detectHeadroom;
130
-
131
124
  export async function detectSemble() {
132
125
  if (commandExists('semble')) {
133
126
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polderlabs/bizar",
3
- "version": "10.0.7",
3
+ "version": "10.1.0",
4
4
  "description": "Norse-pantheon multi-agent system for Claude Code — 14 agents across 4 cost tiers with cost-aware routing, plans, and a configurable agent harness. Ships as a single npm package with the dashboard server, Claude Code MCP server, and typed SDK.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polderlabs/bizar-sdk",
3
- "version": "10.0.7",
3
+ "version": "10.1.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -152,13 +152,6 @@ function readGhVersion() {
152
152
  return m ? m[1] : raw.split(' ')[0];
153
153
  }
154
154
 
155
- function readHeadroomVersion() {
156
- const raw = safeExec('headroom', ['--version']);
157
- if (!raw) return null;
158
- const m = raw.match(/(\d+\.\d+\.\d+)/);
159
- return m ? m[1] : raw.split(' ')[0];
160
- }
161
-
162
155
  function readSembleVersion() {
163
156
  const raw = safeExec('semble', ['--version']);
164
157
  if (!raw) return null;
@@ -187,7 +180,6 @@ function windowsInstallCmd(name) {
187
180
  case 'pip': return 'python -m pip install --upgrade pip 2>nul || pip install --upgrade pip 2>nul';
188
181
  case 'jq': return 'winget install jqlang.jq 2>nul || choco install jq -y 2>nul';
189
182
  case 'gh': return 'winget install GitHub.cli 2>nul || choco install gh -y 2>nul';
190
- case 'headroom':
191
183
  case 'semble': return 'npm install -g ' + name + ' 2>nul';
192
184
  default: return null;
193
185
  }
@@ -204,7 +196,6 @@ function macInstallCmd(name) {
204
196
  case 'pip': return 'python3 -m pip install --upgrade pip';
205
197
  case 'jq': return 'brew install jq';
206
198
  case 'gh': return 'brew install gh';
207
- case 'headroom':
208
199
  case 'semble': return 'npm install -g ' + name;
209
200
  default: return null;
210
201
  }
@@ -219,7 +210,6 @@ function linuxInstallCmd(name) {
219
210
  case 'jq': return 'nix-shell -p jq';
220
211
  case 'git': return 'nix-shell -p git';
221
212
  case 'gh': return 'nix-shell -p gh';
222
- case 'headroom':
223
213
  case 'semble': return `nix-env -iA nixpkgs.${name}`;
224
214
  default: return null;
225
215
  }
@@ -264,7 +254,6 @@ function linuxInstallCmd(name) {
264
254
  if (LINUX_DISTRO === 'alpine') return `${sudo}apk add --no-cache gh`;
265
255
  if (LINUX_DISTRO === 'void') return `${sudo}xbps-install -S gh`;
266
256
  return `${sudo}${pm} install -y gh`;
267
- case 'headroom':
268
257
  case 'semble':
269
258
  return `npm install -g ${name}`;
270
259
  default:
@@ -425,19 +414,6 @@ export async function checkDeps({ strict = false } = {}) {
425
414
  }
426
415
  }
427
416
 
428
- // --- headroom ---
429
- {
430
- const current = readHeadroomVersion();
431
- const entry = { name: 'headroom', status: 'missing', current, required: 'recommended' };
432
- if (which('headroom')) {
433
- entry.status = 'present';
434
- present.push(entry);
435
- } else {
436
- entry.installCmd = installCmdFor('headroom');
437
- missing.push(entry);
438
- }
439
- }
440
-
441
417
  // --- semble ---
442
418
  {
443
419
  const current = readSembleVersion();
@@ -1,94 +0,0 @@
1
- ---
2
- name: headroom
3
- description: Headroom — context compression layer for AI agents. Routes cline and other LLM clients through a local proxy that compresses tool outputs, logs, RAG chunks, and conversation history by 60–95%.
4
- ---
5
-
6
- # Headroom
7
-
8
- Headroom is a context compression layer that sits between cline (or any LLM client) and the upstream provider. It intercepts tool call outputs, conversation history, and RAG chunks and compresses them before they reach the model — typically reducing token usage by 60–95% with no loss in answer quality.
9
-
10
- ## When to Use
11
-
12
- - **Token budget is tight**: If a task is approaching the context window limit, Headroom can reclaim 60–90% of the tokens spent on tool outputs.
13
- - **Long conversations**: The compression is cumulative — the longer the session, the more Headroom saves.
14
- - **Verbose tool output**: RAG retrieval, file globbing, grep results, and diagnostic output are the highest-value compression targets.
15
- - **Multi-step implementation**: Large features with many tool calls benefit most.
16
-
17
- ## Architecture
18
-
19
- ```
20
- cline → headroom proxy (localhost:8787) → LLM provider
21
-
22
- compresses tool outputs, logs, RAG chunks
23
- caches responses
24
- measures savings
25
- ```
26
-
27
- ## Key Concepts
28
-
29
- ### Compression ratio
30
- The fraction of tokens Headroom eliminates. A 0.85 compression ratio means 85% of the tokens were removed before reaching the provider.
31
-
32
- ### Wrapped vs unwrapped
33
- `headroom wrap cline` modifies `~/.config/cline/cline.json` to route traffic through the proxy. `headroom unwrap cline` restores the original configuration.
34
-
35
- ### Proxy vs wrap
36
- - **Proxy** (`headroom proxy`): The actual HTTP proxy server running on port 8787.
37
- - **Wrap** (`headroom wrap cline`): The act of configuring cline to use the proxy.
38
-
39
- You can run the proxy standalone (`headroom proxy`) and point any OpenAI-compatible client at it. The wrap command is just a convenience for cline.
40
-
41
- ## Dashboard Integration
42
-
43
- The Bizar dashboard manages Headroom through Settings → Headroom:
44
-
45
- - **Status widget**: Shows live proxy status, compression ratio, tokens saved
46
- - **Controls**: Install, wrap/unwrap, start/stop proxy, open dashboard
47
- - **Settings**: Auto-install, auto-start, auto-wrap, route-all-providers, port, host, backend, output shaper, telemetry, budget
48
-
49
- API endpoints:
50
- - `GET /api/headroom/status` — live status
51
- - `GET /api/headroom/stats?hours=24` — compression statistics
52
- - `POST /api/headroom/install` — install headroom
53
- - `POST /api/headroom/wrap` — wrap cline
54
- - `POST /api/headroom/unwrap` — unwrap cline
55
- - `POST /api/headroom/proxy/start` — start proxy
56
- - `POST /api/headroom/proxy/stop` — stop proxy
57
- - `POST /api/headroom/auto-route` — configure all providers to route through the proxy
58
-
59
- CLI:
60
- ```bash
61
- bizar headroom status # live status
62
- bizar headroom stats # compression stats
63
- bizar headroom install # install headroom
64
- bizar headroom wrap # wrap cline
65
- bizar headroom unwrap # unwrap
66
- bizar headroom start # start proxy
67
- bizar headroom stop # stop proxy
68
- bizar headroom doctor # health check
69
- ```
70
-
71
- ## Environment Variables
72
-
73
- | Variable | Default | Description |
74
- |---|---|---|
75
- | `HEADROOM_HOST` | `127.0.0.1` | Proxy bind host |
76
- | `HEADROOM_PORT` | `8787` | Proxy port |
77
- | `HEADROOM_OUTPUT_SHAPER` | `0` | Set to `1` to enable output shaping |
78
- | `HEADROOM_TELEMETRY` | (on) | Set to `off` to disable |
79
- | `HEADROOM_BUDGET` | `0` | Monthly USD cap (0 = unlimited) |
80
- | `HEADROOM_CONTEXT_TOOL` | `rtk` | Context tool: `rtk` or `lean-ctx` |
81
-
82
- ## Common Gotchas
83
-
84
- 1. **Proxy must be running before cline starts**: If the proxy is down when cline launches, cline will fail to make LLM calls. Start the proxy first, or enable `autoStart` in Headroom settings.
85
-
86
- 2. **`headroom wrap` edits cline.json**: The wrap command modifies `~/.config/cline/cline.json`. If you use version control for this file, you'll see a diff on every wrap. Use `headroom unwrap` before committing, or ignore the changes.
87
-
88
- 3. **Headroom 0.30.0 doesn't have `headroom plan --tokens`**: This command was removed. Use `headroom perf --hours 24` for actual token savings data.
89
-
90
- 4. **Token savings are cumulative**: The compression ratio compounds over a session. A 15-step implementation that saves 80% at each step uses roughly the same tokens as a 3-step implementation without Headroom.
91
-
92
- 5. **Cache hits**: Headroom caches semantically similar tool calls. Repeated operations (file reads, API probes) can be served from cache entirely, bypassing the LLM.
93
-
94
- 6. **Provider baseURL**: When `routeAllProviders` is enabled, the dashboard rewrites provider baseURLs to point at the proxy. If you configure a new provider manually, you may need to update its baseURL to go through the proxy.