troxy-cli 1.29.10 → 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.
- package/package.json +1 -1
- package/src/init.js +35 -1
- package/src/uninstall.js +16 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "troxy-cli",
|
|
3
|
-
"version": "1.29.
|
|
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
|
-
|
|
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
|
package/src/uninstall.js
CHANGED
|
@@ -129,6 +129,15 @@ export async function runUninstall() {
|
|
|
129
129
|
// is listening" outage this plan's fail-open design exists to prevent.
|
|
130
130
|
// Each is independently best-effort: a missing/corrupt config file must
|
|
131
131
|
// never stop the rest of uninstall from proceeding.
|
|
132
|
+
let wasIntercepting = false;
|
|
133
|
+
try {
|
|
134
|
+
const settingsPath = claudeCodeSettingsPath();
|
|
135
|
+
if (fs.existsSync(settingsPath)) {
|
|
136
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
137
|
+
wasIntercepting = !!(settings.env?.HTTPS_PROXY || settings.env?.NODE_EXTRA_CA_CERTS);
|
|
138
|
+
}
|
|
139
|
+
} catch {}
|
|
140
|
+
|
|
132
141
|
process.stdout.write(' Reverting Claude Code settings... ');
|
|
133
142
|
try {
|
|
134
143
|
unpatchClaudeCodeConfig(claudeCodeConfigPath());
|
|
@@ -200,4 +209,11 @@ export async function runUninstall() {
|
|
|
200
209
|
}
|
|
201
210
|
|
|
202
211
|
console.log('\n Troxy removed. All agent keys revoked. Your AI agents are no longer protected by Troxy.\n');
|
|
212
|
+
|
|
213
|
+
if (wasIntercepting) {
|
|
214
|
+
console.log(' ⚠ IMPORTANT: fully quit and restart Claude Code / Claude Desktop now.');
|
|
215
|
+
console.log(' Your current session was launched with Troxy\'s proxy settings still');
|
|
216
|
+
console.log(' loaded in memory, and the certificate they point to has just been');
|
|
217
|
+
console.log(' deleted — it will fail to reach Anthropic until you restart.\n');
|
|
218
|
+
}
|
|
203
219
|
}
|