troxy-cli 1.29.11 → 1.29.12

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/init.js +35 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "troxy-cli",
3
- "version": "1.29.11",
3
+ "version": "1.29.12",
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
@@ -12,6 +12,34 @@ import { probePort } from './proxy.js';
12
12
  import { launchdUserDomain } from './launchd.js';
13
13
  import { reclaimOwnership } from './sudo-ownership.js';
14
14
 
15
+ // `npx troxy-cli@latest <cmd>` puts a `troxy` shim on PATH only for that one
16
+ // child process (npx's own temp-PATH trick) - it never installs a persistent
17
+ // binary. installService()'s `which troxy` lookup succeeds during that npx
18
+ // run and wires the background service to the real (but ephemeral) npx-cache
19
+ // path, so "Background service installed ✓" is honest in the moment - but
20
+ // the user is left with no actual `troxy` command afterward, so every
21
+ // follow-up instruction we print (`troxy uninstall`, `troxy daemon &`, ...)
22
+ // 404s with "command not found". Detect that case so we can tell the truth
23
+ // about how to run follow-up commands instead of implying one that doesn't exist.
24
+ function ranViaEphemeralNpx() {
25
+ if (process.env.npm_execpath && /npx|_npx/.test(process.env.npm_execpath)) return true;
26
+ try {
27
+ const resolved = execSync('which troxy', { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
28
+ return /\/_npx\//.test(resolved);
29
+ } catch {
30
+ return true; // no `troxy` resolvable at all outside this process either
31
+ }
32
+ }
33
+
34
+ function printPersistentInstallHint() {
35
+ console.log('\n ⚠ troxy isn\'t on your PATH as a permanent command - this run was');
36
+ console.log(' via npx, which only makes it available for this one command.');
37
+ console.log(' For uninstall, status, or anything else later, either:');
38
+ console.log(' npm install -g troxy-cli (then use `troxy <command>` directly)');
39
+ console.log(' or:');
40
+ console.log(' npx troxy-cli@latest <command> (repeat the npx prefix each time)\n');
41
+ }
42
+
15
43
  // Re-point every consumer of the API key (MCP client configs, the background service /
16
44
  // systemd env file / launchd plist, OpenClaw) at `key`. Shared by runInit and rotate-key
17
45
  // (H6): rotate-key used to write the new key only to config.json and then revoke the old
@@ -136,12 +164,18 @@ export async function reprovisionKeyConsumers(key, agentName, proxyOptIn = null)
136
164
  }
137
165
 
138
166
  console.log('\n Setting up background service...');
167
+ const viaEphemeralNpx = ranViaEphemeralNpx();
139
168
  try {
140
169
  installService(key, agentName);
141
170
  console.log(' Background service installed ✓');
171
+ if (viaEphemeralNpx) printPersistentInstallHint();
142
172
  } catch (err) {
143
173
  console.log(` Background service ✗ (${err.message})`);
144
- console.log(' You can start it manually with: troxy daemon &');
174
+ if (viaEphemeralNpx) {
175
+ printPersistentInstallHint();
176
+ } else {
177
+ console.log(' You can start it manually with: troxy daemon &');
178
+ }
145
179
  }
146
180
 
147
181
  // Sudo safety net, not part of the normal (unprivileged) flow's own