troxy-cli 1.30.12 → 1.30.14

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
@@ -1,6 +1,6 @@
1
1
  # troxy-cli
2
2
 
3
- The official Troxy CLI — onboard AI agents, manage MCPs and policies from the terminal.
3
+ The official Troxy CLI. Connect Claude Code and make your usage go further.
4
4
 
5
5
  ## Prerequisites
6
6
 
package/bin/troxy.js CHANGED
@@ -570,14 +570,13 @@ switch (command) {
570
570
  const { account } = data;
571
571
  console.log(`
572
572
  Account
573
- Active policies: ${account.active_policies}
574
573
  MCPs total: ${account.total_mcps} (${account.connected_mcps} connected)
575
574
  Requests 24h: ${account.requests_24h}
576
575
  Default action: ${account.default_action}
577
576
  `);
578
577
  } catch { console.log(); }
579
578
  } else {
580
- console.log(' Account: not signed in. Run `troxy login` to manage policies and view activity from the CLI.\n');
579
+ console.log(' Account: not signed in. Run `troxy login` to view usage and activity from the CLI.\n');
581
580
  }
582
581
 
583
582
  // Version check
@@ -771,106 +770,23 @@ switch (command) {
771
770
  default:
772
771
  if (command) console.error(` Unknown command: ${command}\n`);
773
772
  console.log(`
774
- Troxy: a secure control layer for AI agents
775
-
776
- This CLI has two parts:
777
- - Commands below (policies, mcps, activity, ...) are for YOU to run and manage your account.
778
- - "troxy mcp" starts the MCP server an AI agent connects to. You don't run it by hand;
779
- MCP clients (Claude Desktop, etc.) launch it after "troxy init" configures them.
780
-
781
- First time? Run these two commands in order:
782
- 1) npx troxy-cli init --key txy-... (get key from https://dash.troxy.io)
783
- 2) troxy login (start a 12h CLI session)
784
-
785
- MCP setup (once per machine): troxy init --key <api-key>
786
- Login for CLI commands (12h): troxy login
787
-
788
- Setup (one time, API key required)
789
- troxy init --key <api-key> Connect this machine as an MCP + save key
790
- troxy init --key <api-key> --name "My Agent" Same, no interactive prompt
791
- (for cloud/scripted agents that can't answer stdin)
792
- troxy tools Scan for AI tools + report them to the dashboard
793
- troxy restart Restart the MCP background service
794
- troxy uninstall Remove Troxy from this machine
795
- troxy status API health + MCP status (no login needed)
796
- troxy update Update to the latest version
773
+ Troxy: make your Claude usage go further
797
774
 
798
- Proxy (experimental - routes Claude's own model calls through Troxy for
799
- real-time policy enforcement and cost optimization, separate from the MCP
800
- connection above)
801
- troxy proxy status Show whether it's on, and cert/interceptor health
802
- troxy proxy enable --experimental Turn it on (installs a local CA cert)
803
- troxy proxy disable Turn it off - removes the settings.json patch
804
-
805
- Everything else requires: troxy login
806
-
807
- MCP
808
- troxy pause Pause this MCP (blocks all checkpoints)
809
- troxy resume Resume this MCP
810
- troxy mcps list All MCPs in your account
811
- troxy mcps rename --name "x" Rename this machine's MCP
812
- troxy mcps create --name "x" Create a key for another agent/machine
813
- troxy mcps revoke --mcp "x" Revoke an MCP's key
814
- troxy mcps pause/resume --mcp "x" Pause/resume any MCP (not just this one)
815
- troxy mcps budget --mcp "x" --currency USD --limit 500
816
- troxy mcps set-default-action --mcp "x" --action BLOCK
817
-
818
- Keys
819
- troxy rotate-key Rotate MCP key (revokes old, saves new locally)
820
-
821
- Policies (all six checkpoints: payment, comms, access, destructive, model, secrets)
822
- Admin-only: every write below requires --org. Personal and per-MCP policies
823
- no longer exist - a policy is always org-wide or space-wide, and org acts as
824
- a ceiling a space policy can never be looser than. list/describe/test need
825
- no --org and show every org + space policy that applies to you.
826
- troxy policies list / list --org
827
- troxy policies describe --name "Block Amazon"
828
- troxy policies templates (browse the built-in library)
829
- troxy policies fields --domain secrets (see what each checkpoint supports)
830
- troxy policies create --describe "block Amazon purchases over $200" --org (AI builder, payment/comms only)
831
- troxy policies create --name "X" --template "Block a secret going somewhere public" --org
832
- troxy policies create --name "X" --action BLOCK --domain payment --field amount --operator gte --value 500 --org
833
- troxy policies create --name "X" --action BLOCK --domain access --field login_action --operator eq --value signup --org
834
- troxy policies create --name "X" --action BLOCK --domain comms --or "field=recipient_domain,operator=contains,value=gmail.com" --org
835
- troxy policies create --name "X" --action BLOCK --domain secrets --field has_api_key --operator eq --value true --org
836
- troxy policies test --domain payment --field amount --operator gt --value 100 --example '{"amount": 150}'
837
- troxy policies set-priority --name "X" --priority 10 --org
838
- troxy policies pause --name "X" --org
839
- troxy policies resume --name "X" --org
840
- troxy policies delete --name "X" --org
841
- (--org needs admin access; run 'troxy policies create --help' for the full condition syntax)
842
-
843
- Approvals (ESCALATE holds)
844
- troxy approvals list
845
- troxy approvals approve --id <id>
846
- troxy approvals decline --id <id>
847
-
848
- Settings
849
- troxy settings show
850
- troxy settings set --default-action BLOCK --approval-timeout 4
851
-
852
- LLM provider keys
853
- troxy secrets list
854
- troxy secrets set --name "OpenAI"
855
- troxy secrets delete --name "OpenAI"
856
-
857
- Account
858
- troxy account clear-data Wipe activity/policies, keep account + keys
859
- troxy account delete Permanently delete your account (irreversible)
775
+ First time? Create a key at https://dash.troxy.io, then run:
776
+ npx troxy-cli init --key txy-...
860
777
 
861
- Activity & insights
862
- troxy activity [--limit 50] [--mine]
863
- troxy insights [--period 7]
864
- troxy usage-bar [--period 7]
778
+ Commands
779
+ troxy init --key <api-key> Connect this machine (add --name "My Mac" to skip the prompt)
780
+ troxy status Health and connection status
781
+ troxy update Update to the latest version
782
+ troxy uninstall Remove Troxy from this machine
783
+ troxy login Start a 12h CLI session for the commands below
784
+ troxy usage-bar [--period 7] Your usage and what Troxy saved
785
+ troxy activity [--limit 50] Recent requests
786
+ troxy insights [--period 7] Trends
865
787
 
866
- Simulate (test your policies against every checkpoint, not just payment)
867
- troxy pay --merchant "Amazon" --amount 50
868
- troxy pay --merchant "Google" --amount 300 --category software
869
- troxy send --recipient jane@gmail.com --body "the password is hunter2"
870
- troxy signin --site coinbase.com --type signup
871
- troxy action --verb delete --resource "prod users table" --items 500
872
- troxy model-call --model claude-opus-5 --provider anthropic --cost 4.50
873
- troxy scan --content "AWS_SECRET_ACCESS_KEY=..." --destination public --do push
788
+ In Claude Code: /troxy status, /troxy off, /troxy on
789
+ Help: https://docs.troxy.io or support@troxy.io
874
790
  `);
875
791
  process.exit(command ? 1 : 0);
876
792
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "troxy-cli",
3
- "version": "1.30.12",
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",
3
+ "version": "1.30.14",
4
+ "description": "Make your Claude Code usage go further: lighter requests, less usage, less money",
5
5
  "homepage": "https://troxy.io",
6
6
  "bugs": {
7
7
  "email": "support@troxy.io"
@@ -107,6 +107,23 @@ function rebuildWithText(toolResponse, text) {
107
107
  return { ...toolResponse, content: text };
108
108
  }
109
109
 
110
+ // Only outputs Claude rarely fetches back get shortened. Measured 2026-10-23 on 1,435 shortened
111
+ // outputs: Grep 0% recalled; wc, ls, head, tail, test runs and logs 0-15%; Read of .js/.html
112
+ // 17-20%. Targeted reads (sed, cat, Bash grep, Read of .py/.md/.txt) came back 30-86%, so
113
+ // shortening them only adds a recall step.
114
+ const SHORTEN_COMMANDS = new Set(['wc', 'ls', 'head', 'tail', 'ps', 'gh', 'aws', 'pytest']);
115
+ const SHORTEN_READ_EXT = /\.(js|html)$/i;
116
+
117
+ export function isShortenable(toolName, toolInput) {
118
+ if (toolName === undefined) return true; // ponytail: payloads without tool_name (old tests); Claude Code always sends it
119
+ if (toolName === 'Grep') return true;
120
+ if (toolName === 'Read') return SHORTEN_READ_EXT.test(String(toolInput?.file_path || ''));
121
+ if (toolName !== 'Bash') return false;
122
+ const cmd = String(toolInput?.command || '').trim().replace(/^(cd\s+\S+\s*(&&|;)\s*)+/, '');
123
+ if (/^python3?\s+-m\s+pytest\b/.test(cmd)) return true;
124
+ return SHORTEN_COMMANDS.has(path.basename(cmd.split(/\s+/)[0] || ''));
125
+ }
126
+
110
127
  export async function buildHookResponse(toolUseBlock, {
111
128
  sandboxFraction = 1,
112
129
  holdoutFraction = 0.2,
@@ -124,7 +141,7 @@ export async function buildHookResponse(toolUseBlock, {
124
141
  return undefined;
125
142
  }
126
143
  const output = extractText(toolResponse);
127
- if (output === null || !shouldSandbox(output)) {
144
+ if (output === null || !shouldSandbox(output) || !isShortenable(toolUseBlock?.tool_name, toolUseBlock?.tool_input)) {
128
145
  writeState(storeDir, 'skipped');
129
146
  return undefined;
130
147
  }
@@ -271,3 +271,25 @@ test('posttooluse-hook is a no-op unless TROXY_COMPRESS=1', () => {
271
271
  fs.rmSync(tmpHome, { recursive: true, force: true });
272
272
  }
273
273
  });
274
+
275
+ test('isShortenable: only output kinds Claude rarely fetches back', async () => {
276
+ const { isShortenable } = await import('../sandbox/posttooluse-hook.js');
277
+ assert.equal(isShortenable('Grep', {}), true);
278
+ assert.equal(isShortenable('Read', { file_path: '/a/b/app.js' }), true);
279
+ assert.equal(isShortenable('Read', { file_path: '/a/b/notes.md' }), false);
280
+ assert.equal(isShortenable('Read', { file_path: '/a/b/x.py' }), false);
281
+ assert.equal(isShortenable('Bash', { command: 'cd /repo && ls -la src' }), true);
282
+ assert.equal(isShortenable('Bash', { command: 'python3 -m pytest -q' }), true);
283
+ assert.equal(isShortenable('Bash', { command: 'sed -n 1,200p file.js' }), false);
284
+ assert.equal(isShortenable('Bash', { command: 'cat big.log' }), false);
285
+ assert.equal(isShortenable('mcp__claude_ai_Gmail__get_thread', {}), false);
286
+ });
287
+
288
+ test('a large sed output passes through unshortened', async () => {
289
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'troxy-sandbox-'));
290
+ const response = await buildHookResponse(
291
+ { tool_name: 'Bash', tool_input: { command: 'sed -n 1,400p a.js' }, tool_response: bashResult('x'.repeat(5000)) },
292
+ { sandboxFraction: 1, holdoutFraction: 0, randomFn: () => 0.5, storeDir: dir });
293
+ assert.equal(response, undefined);
294
+ assert.equal(readState(dir).state, 'skipped');
295
+ });
@@ -89,12 +89,6 @@ describe('bin/troxy.js: proxy subcommand wiring', () => {
89
89
  assert.match(proxyBlock, /runProxyDisable/);
90
90
  assert.match(proxyBlock, /runProxyStatus/);
91
91
  });
92
-
93
- it('is listed in the default help banner - init already enables it for real users', () => {
94
- const helpBannerStart = binSrc.indexOf("Troxy: a secure control layer for AI agents");
95
- const helpBanner = binSrc.slice(helpBannerStart);
96
- assert.ok(helpBanner.includes('troxy proxy '), 'troxy proxy should appear in the printed help banner');
97
- });
98
92
  });
99
93
 
100
94
  describe('uninstall.js: settings.json symmetry (fail-open layer 6)', () => {