troxy-cli 1.30.15 → 1.30.17

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
@@ -762,7 +762,8 @@ switch (command) {
762
762
 
763
763
  // ── Help / default ────────────────────────────────────────────
764
764
  default:
765
- if (command) console.error(` Unknown command: ${command}\n`);
765
+ const asksHelp = ['help', '--help', '-h'].includes(command);
766
+ if (command && !asksHelp) console.error(` Unknown command: ${command}\n`);
766
767
  console.log(`
767
768
  Troxy: make your Claude usage go further
768
769
 
@@ -782,6 +783,6 @@ switch (command) {
782
783
  In Claude Code: /troxy status, /troxy off, /troxy on
783
784
  Help: https://docs.troxy.io or support@troxy.io
784
785
  `);
785
- process.exit(command ? 1 : 0);
786
+ process.exit(command && !asksHelp ? 1 : 0);
786
787
  }
787
788
  } // end _run
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "troxy-cli",
3
- "version": "1.30.15",
3
+ "version": "1.30.17",
4
4
  "description": "Make your Claude Code usage go further: lighter requests, less usage, less money",
5
5
  "homepage": "https://troxy.io",
6
6
  "bugs": {
package/src/init.js CHANGED
@@ -195,7 +195,7 @@ export async function reprovisionKeyConsumers(key, agentName, proxyOptIn = null,
195
195
  const installed = await installTroxyGuardMod();
196
196
  console.log(installed
197
197
  ? ` • Troxy model routing (terminal + Desktop) ✓`
198
- : ` • Troxy model routing - (needs Claude Code 2.1.287+, skipped)`);
198
+ : ` • Troxy model routing ✗ NOT installed: needs Claude Code 2.1.287+ (run claude --version). Usage and Savings stays empty until it is.`);
199
199
  } catch (err) {
200
200
  console.log(` • Troxy model routing ✗ (${err.message})`);
201
201
  }
@@ -486,6 +486,11 @@ const MCP_CLIENTS = [
486
486
  ];
487
487
 
488
488
  export async function runInit({ key, name, proxy, concise } = {}) {
489
+ // Under sudo, os.homedir() can be root's, so the mod would land where Claude Code never looks.
490
+ if (process.env.SUDO_USER) {
491
+ console.error('\n Run this without sudo: troxy init --key ...\n (sudo is only for the install command.)\n');
492
+ process.exit(1);
493
+ }
489
494
  // undefined (flag never passed) -> null, so reprovisionKeyConsumers can
490
495
  // tell "not decided, ask interactively" apart from an explicit --proxy.
491
496
  const proxyOptIn = proxy === undefined ? null : Boolean(proxy);
@@ -1,3 +1,5 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { fileURLToPath } from 'node:url';
1
3
  import { test } from 'node:test';
2
4
  import assert from 'node:assert/strict';
3
5
  import os from 'node:os';
@@ -94,3 +96,10 @@ test('refreshTroxyGuardMod: re-copies a stale mod, leaves a current or missing o
94
96
  fs.rmSync(tmpHome, { recursive: true, force: true });
95
97
  }
96
98
  });
99
+
100
+ test('init refuses to run under sudo, so the mod is not installed in root\'s home', () => {
101
+ const r = spawnSync(process.execPath, [fileURLToPath(new URL('../../bin/troxy.js', import.meta.url)), 'init', '--key', 'x'],
102
+ { env: { ...process.env, SUDO_USER: 'someone' }, encoding: 'utf8' });
103
+ assert.equal(r.status, 1);
104
+ assert.match(r.stderr, /without sudo/);
105
+ });