troxy-cli 1.30.5 → 1.30.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/bin/troxy.js CHANGED
@@ -284,13 +284,6 @@ switch (command) {
284
284
  break;
285
285
  }
286
286
 
287
- // usage-bar: Show live % savings in Claude UI
288
- case 'usage-bar': {
289
- const { showUsageBar } = await import('../src/usage-bar.js');
290
- await showUsageBar();
291
- break;
292
- }
293
-
294
287
  // ── Heartbeat daemon (background service) ─────────────────────
295
288
  case 'daemon': {
296
289
  const { runDaemon } = await import('../src/daemon.js');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "troxy-cli",
3
- "version": "1.30.5",
3
+ "version": "1.30.6",
4
4
  "description": "A secure control layer for AI agents: policies across payments, messages, logins, destructive actions, model usage, and secrets, all enforceable from the CLI",
5
5
  "homepage": "https://troxy.io",
6
6
  "bugs": {
package/src/init.js CHANGED
@@ -570,14 +570,6 @@ export async function runInit({ key, name, proxy, concise } = {}) {
570
570
  // Tool detection is a bonus, never a blocker for a successful init.
571
571
  }
572
572
 
573
- // Install Troxy usage bar MOD into Claude Code (CLI + desktop)
574
- try {
575
- const { installTroxySavingsModToClaudeCode } = await import('./install-mod.js');
576
- await installTroxySavingsModToClaudeCode();
577
- } catch {
578
- // MOD installation is optional - init succeeds even if it fails
579
- }
580
-
581
573
  console.log('\n Troxy is on. Restart Claude Code, then work as usual.');
582
574
  console.log(' Your savings → https://dash.troxy.io (Usage and Savings)');
583
575
  console.log('\n For more information, visit https://docs.troxy.io\n');
@@ -906,6 +898,19 @@ export function patchClaudeCodeHooks(
906
898
  if (postIdx >= 0) config.hooks.PostToolUse[postIdx] = postToolUseEntry;
907
899
  else config.hooks.PostToolUse.push(postToolUseEntry);
908
900
 
901
+ return stripLegacyUsageBarHooks(config);
902
+ }
903
+
904
+ // Older installs added Notification/MessageDisplay hooks that ran `troxy usage-bar`,
905
+ // which printed placeholder numbers. Remove them (and only them) on every patch and unpatch.
906
+ export function stripLegacyUsageBarHooks(config) {
907
+ for (const event of ['Notification', 'MessageDisplay']) {
908
+ if (!Array.isArray(config.hooks?.[event])) continue;
909
+ config.hooks[event] = config.hooks[event]
910
+ .map(e => ({ ...e, hooks: (e.hooks || []).filter(h => !/\btroxy usage-bar\s*$/.test(h.command || '')) }))
911
+ .filter(e => e.hooks.length);
912
+ if (!config.hooks[event].length) delete config.hooks[event];
913
+ }
909
914
  return config;
910
915
  }
911
916
 
@@ -922,7 +927,7 @@ export function unpatchClaudeCodeHooks(config) {
922
927
  if (Array.isArray(config.hooks?.PostToolUse)) {
923
928
  config.hooks.PostToolUse = config.hooks.PostToolUse.filter(e => !_isTroxyPostToolUseEntry(e));
924
929
  }
925
- return config;
930
+ return stripLegacyUsageBarHooks(config);
926
931
  }
927
932
 
928
933
  // File-based wrappers (for call sites that operate directly on file paths,
@@ -271,3 +271,15 @@ describe('unpatchClaudeCodeHooks', () => {
271
271
  assert.doesNotThrow(() => unpatchClaudeCodeHooks(cfg));
272
272
  });
273
273
  });
274
+
275
+ describe('stripLegacyUsageBarHooks', () => {
276
+ it('removes only the old placeholder usage-bar hooks, on patch and unpatch', () => {
277
+ const legacy = { matcher: '*', hooks: [{ type: 'command', command: '/opt/homebrew/bin/troxy usage-bar', timeout: 1 }] };
278
+ const mine = { matcher: '*', hooks: [{ type: 'command', command: 'echo mine' }] };
279
+ const cfg = () => ({ hooks: { Notification: [legacy, mine], MessageDisplay: [legacy] } });
280
+ for (const out of [patchClaudeCodeHooks(cfg(), {}, 'troxy hook-report'), unpatchClaudeCodeHooks(cfg())]) {
281
+ assert.deepEqual(out.hooks.Notification, [mine]);
282
+ assert.equal(out.hooks.MessageDisplay, undefined);
283
+ }
284
+ });
285
+ });
@@ -1,50 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import os from 'os';
4
-
5
- /**
6
- * Install Troxy policy MOD into Claude Code
7
- * Adds/updates hooks to show live usage bar with % context saved
8
- */
9
- export async function installTroxySavingsModToClaudeCode() {
10
- const claudeHome = path.join(os.homedir(), '.claude');
11
- const settingsPath = path.join(claudeHome, 'settings.json');
12
-
13
- if (!fs.existsSync(settingsPath)) {
14
- console.error(' Error: Claude Code not found. Install Claude Code first.\n');
15
- return false;
16
- }
17
-
18
- try {
19
- const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
20
-
21
- // Add Notification hook to show usage bar after each response
22
- if (!settings.hooks) settings.hooks = {};
23
- if (!settings.hooks.Notification) settings.hooks.Notification = [];
24
-
25
- // Check if already installed
26
- const alreadyInstalled = settings.hooks.Notification.some(h =>
27
- h.hooks?.[0]?.command?.includes('troxy usage-bar')
28
- );
29
-
30
- if (!alreadyInstalled) {
31
- settings.hooks.Notification.push({
32
- matcher: '*',
33
- hooks: [
34
- {
35
- type: 'command',
36
- command: '/opt/homebrew/bin/troxy usage-bar',
37
- timeout: 1
38
- }
39
- ]
40
- });
41
- }
42
-
43
- fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
44
- console.log(' ✓ Troxy usage bar MOD installed');
45
- return true;
46
- } catch (err) {
47
- console.error(` Error installing MOD: ${err.message}`);
48
- return false;
49
- }
50
- }
package/src/usage-bar.js DELETED
@@ -1,25 +0,0 @@
1
- /**
2
- * Show live usage bar with % context saved
3
- * Displays in Claude UI as AbovePrompt band
4
- */
5
-
6
- export async function showUsageBar() {
7
- // Read current session usage from Claude's session context
8
- // Format for AbovePrompt hook output: simple text that Claude displays
9
-
10
- // Placeholder data - would be fetched from real session in production
11
- const contextUsed = 45; // %
12
- const saved = 15; // % saved by Troxy routing/trimming
13
-
14
- const barLength = 20;
15
- const filledLength = Math.round((contextUsed / 100) * barLength);
16
- const emptyLength = barLength - filledLength;
17
-
18
- const bar = '█'.repeat(filledLength) + '░'.repeat(emptyLength);
19
-
20
- // Output format for Claude's hook system
21
- // This gets displayed in the AbovePrompt area
22
- const output = `[${bar}] ${contextUsed}% used · ${saved}% saved by Troxy`;
23
-
24
- console.log(output);
25
- }