@claudexor/cli 1.0.1 → 2.1.3
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/dist/acp-surface-runner.d.ts +17 -0
- package/dist/acp-surface-runner.d.ts.map +1 -0
- package/dist/acp-surface-runner.js +187 -0
- package/dist/acp-surface-runner.js.map +1 -0
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js.map +1 -1
- package/dist/bridge-serve.d.ts +3 -0
- package/dist/bridge-serve.d.ts.map +1 -0
- package/dist/bridge-serve.js +39 -0
- package/dist/bridge-serve.js.map +1 -0
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +12 -3
- package/dist/capabilities.js.map +1 -1
- package/dist/claude-oauth-usage.d.ts +33 -0
- package/dist/claude-oauth-usage.d.ts.map +1 -0
- package/dist/claude-oauth-usage.js +190 -0
- package/dist/claude-oauth-usage.js.map +1 -0
- package/dist/claude-statusline.d.ts +25 -0
- package/dist/claude-statusline.d.ts.map +1 -0
- package/dist/claude-statusline.js +259 -0
- package/dist/claude-statusline.js.map +1 -0
- package/dist/claudexord.js +346 -543
- package/dist/claudexord.js.map +1 -1
- package/dist/cli-io.d.ts +8 -9
- package/dist/cli-io.d.ts.map +1 -1
- package/dist/cli-io.js +11 -7
- package/dist/cli-io.js.map +1 -1
- package/dist/cli.js +475 -516
- package/dist/cli.js.map +1 -1
- package/dist/codex-quota-source.d.ts +11 -0
- package/dist/codex-quota-source.d.ts.map +1 -0
- package/dist/codex-quota-source.js +181 -0
- package/dist/codex-quota-source.js.map +1 -0
- package/dist/command-flags.d.ts +18 -0
- package/dist/command-flags.d.ts.map +1 -0
- package/dist/command-flags.js +124 -0
- package/dist/command-flags.js.map +1 -0
- package/dist/command-registry.d.ts +2 -40
- package/dist/command-registry.d.ts.map +1 -1
- package/dist/command-registry.js +74 -164
- package/dist/command-registry.js.map +1 -1
- package/dist/control-services.d.ts +2490 -0
- package/dist/control-services.d.ts.map +1 -0
- package/dist/control-services.js +453 -0
- package/dist/control-services.js.map +1 -0
- package/dist/credential-commands.d.ts +9 -0
- package/dist/credential-commands.d.ts.map +1 -0
- package/dist/credential-commands.js +224 -0
- package/dist/credential-commands.js.map +1 -0
- package/dist/daemon-lifecycle.d.ts +7 -3
- package/dist/daemon-lifecycle.d.ts.map +1 -1
- package/dist/daemon-lifecycle.js +40 -12
- package/dist/daemon-lifecycle.js.map +1 -1
- package/dist/daemon-run.d.ts +2 -0
- package/dist/daemon-run.d.ts.map +1 -1
- package/dist/daemon-run.js +62 -14
- package/dist/daemon-run.js.map +1 -1
- package/dist/daemon-runtime-shutdown.d.ts +58 -0
- package/dist/daemon-runtime-shutdown.d.ts.map +1 -0
- package/dist/daemon-runtime-shutdown.js +142 -0
- package/dist/daemon-runtime-shutdown.js.map +1 -0
- package/dist/decision.d.ts.map +1 -1
- package/dist/decision.js +12 -3
- package/dist/decision.js.map +1 -1
- package/dist/live.d.ts +29 -0
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +117 -6
- package/dist/live.js.map +1 -1
- package/dist/local-attachment.d.ts +14 -0
- package/dist/local-attachment.d.ts.map +1 -0
- package/dist/local-attachment.js +67 -0
- package/dist/local-attachment.js.map +1 -0
- package/dist/mcp-runner.d.ts +4 -15
- package/dist/mcp-runner.d.ts.map +1 -1
- package/dist/mcp-runner.js +276 -145
- package/dist/mcp-runner.js.map +1 -1
- package/dist/native-login.d.ts +21 -0
- package/dist/native-login.d.ts.map +1 -0
- package/dist/native-login.js +110 -0
- package/dist/native-login.js.map +1 -0
- package/dist/ops-commands.d.ts +8 -6
- package/dist/ops-commands.d.ts.map +1 -1
- package/dist/ops-commands.js +250 -168
- package/dist/ops-commands.js.map +1 -1
- package/dist/orchestrate-options.d.ts.map +1 -1
- package/dist/orchestrate-options.js +1 -1
- package/dist/orchestrate-options.js.map +1 -1
- package/dist/orphan-reaper.d.ts +4 -5
- package/dist/orphan-reaper.d.ts.map +1 -1
- package/dist/orphan-reaper.js +29 -56
- package/dist/orphan-reaper.js.map +1 -1
- package/dist/orphan-sweeper.d.ts +1 -2
- package/dist/orphan-sweeper.d.ts.map +1 -1
- package/dist/orphan-sweeper.js +29 -48
- package/dist/orphan-sweeper.js.map +1 -1
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +196 -64
- package/dist/plugins.js.map +1 -1
- package/dist/primary-output.d.ts.map +1 -1
- package/dist/primary-output.js.map +1 -1
- package/dist/profile-compatibility.d.ts +6 -0
- package/dist/profile-compatibility.d.ts.map +1 -0
- package/dist/profile-compatibility.js +21 -0
- package/dist/profile-compatibility.js.map +1 -0
- package/dist/profile-registration.d.ts +15 -0
- package/dist/profile-registration.d.ts.map +1 -0
- package/dist/profile-registration.js +68 -0
- package/dist/profile-registration.js.map +1 -0
- package/dist/project-command.d.ts +3 -0
- package/dist/project-command.d.ts.map +1 -0
- package/dist/project-command.js +87 -0
- package/dist/project-command.js.map +1 -0
- package/dist/quota-command.d.ts +3 -0
- package/dist/quota-command.d.ts.map +1 -0
- package/dist/quota-command.js +59 -0
- package/dist/quota-command.js.map +1 -0
- package/dist/registry.d.ts +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +16 -4
- package/dist/registry.js.map +1 -1
- package/dist/release.d.ts.map +1 -1
- package/dist/release.js +15 -3
- package/dist/release.js.map +1 -1
- package/dist/repl.d.ts +3 -8
- package/dist/repl.d.ts.map +1 -1
- package/dist/repl.js +23 -122
- package/dist/repl.js.map +1 -1
- package/dist/request-preflight.d.ts +13 -0
- package/dist/request-preflight.d.ts.map +1 -0
- package/dist/request-preflight.js +81 -0
- package/dist/request-preflight.js.map +1 -0
- package/dist/retention-service.d.ts +24 -0
- package/dist/retention-service.d.ts.map +1 -0
- package/dist/retention-service.js +100 -0
- package/dist/retention-service.js.map +1 -0
- package/dist/retry-command-specs.d.ts +3 -0
- package/dist/retry-command-specs.d.ts.map +1 -0
- package/dist/retry-command-specs.js +21 -0
- package/dist/retry-command-specs.js.map +1 -0
- package/dist/retry-command.d.ts +4 -0
- package/dist/retry-command.d.ts.map +1 -0
- package/dist/retry-command.js +57 -0
- package/dist/retry-command.js.map +1 -0
- package/dist/review-command.d.ts.map +1 -1
- package/dist/review-command.js +47 -12
- package/dist/review-command.js.map +1 -1
- package/dist/run-options.d.ts +2 -2
- package/dist/run-options.d.ts.map +1 -1
- package/dist/run-options.js +27 -5
- package/dist/run-options.js.map +1 -1
- package/dist/settings-command.d.ts.map +1 -1
- package/dist/settings-command.js +143 -188
- package/dist/settings-command.js.map +1 -1
- package/dist/settings-service.d.ts +50 -0
- package/dist/settings-service.d.ts.map +1 -1
- package/dist/settings-service.js +67 -1
- package/dist/settings-service.js.map +1 -1
- package/dist/setup-job-reducer.d.ts +9 -0
- package/dist/setup-job-reducer.d.ts.map +1 -0
- package/dist/setup-job-reducer.js +290 -0
- package/dist/setup-job-reducer.js.map +1 -0
- package/dist/setup-job-store.d.ts +250 -0
- package/dist/setup-job-store.d.ts.map +1 -0
- package/dist/setup-job-store.js +359 -0
- package/dist/setup-job-store.js.map +1 -0
- package/dist/setup-job-support.d.ts +27 -0
- package/dist/setup-job-support.d.ts.map +1 -0
- package/dist/setup-job-support.js +141 -0
- package/dist/setup-job-support.js.map +1 -0
- package/dist/setup-jobs.d.ts +437 -22
- package/dist/setup-jobs.d.ts.map +1 -1
- package/dist/setup-jobs.js +813 -423
- package/dist/setup-jobs.js.map +1 -1
- package/dist/setup-lifecycle-binding.d.ts +40 -0
- package/dist/setup-lifecycle-binding.d.ts.map +1 -0
- package/dist/setup-lifecycle-binding.js +159 -0
- package/dist/setup-lifecycle-binding.js.map +1 -0
- package/dist/setup-login-protocol.d.ts +13 -0
- package/dist/setup-login-protocol.d.ts.map +1 -0
- package/dist/setup-login-protocol.js +179 -0
- package/dist/setup-login-protocol.js.map +1 -0
- package/dist/setup-login-runner.d.ts +20 -0
- package/dist/setup-login-runner.d.ts.map +1 -0
- package/dist/setup-login-runner.js +225 -0
- package/dist/setup-login-runner.js.map +1 -0
- package/dist/setup-supervisor.d.ts +53 -0
- package/dist/setup-supervisor.d.ts.map +1 -0
- package/dist/setup-supervisor.js +177 -0
- package/dist/setup-supervisor.js.map +1 -0
- package/dist/spec-thread-scope.d.ts +3 -0
- package/dist/spec-thread-scope.d.ts.map +1 -0
- package/dist/spec-thread-scope.js +9 -0
- package/dist/spec-thread-scope.js.map +1 -0
- package/dist/spec.d.ts +9 -20
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js +49 -21
- package/dist/spec.js.map +1 -1
- package/dist/thread-delivery.d.ts +18 -0
- package/dist/thread-delivery.d.ts.map +1 -0
- package/dist/thread-delivery.js +67 -0
- package/dist/thread-delivery.js.map +1 -0
- package/dist/thread-select.d.ts +9 -0
- package/dist/thread-select.d.ts.map +1 -0
- package/dist/thread-select.js +12 -0
- package/dist/thread-select.js.map +1 -0
- package/dist/trust-command.d.ts.map +1 -1
- package/dist/trust-command.js +69 -61
- package/dist/trust-command.js.map +1 -1
- package/dist/trust-services.d.ts +5 -6
- package/dist/trust-services.d.ts.map +1 -1
- package/dist/trust-services.js +42 -13
- package/dist/trust-services.js.map +1 -1
- package/package.json +24 -22
- package/dist/attachment-resolver.d.ts +0 -11
- package/dist/attachment-resolver.d.ts.map +0 -1
- package/dist/attachment-resolver.js +0 -61
- package/dist/attachment-resolver.js.map +0 -1
- package/dist/settings-display.d.ts +0 -3
- package/dist/settings-display.d.ts.map +0 -1
- package/dist/settings-display.js +0 -33
- package/dist/settings-display.js.map +0 -1
package/dist/plugins.js
CHANGED
|
@@ -3,6 +3,7 @@ import { copyFileSync, existsSync, lstatSync, readFileSync, readdirSync, realpat
|
|
|
3
3
|
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { hostFallbackExamples, recoveryVerbs } from "./command-registry.js";
|
|
6
|
+
import { manageClaudeStatusline } from "./claude-statusline.js";
|
|
6
7
|
import { CLAUDEXOR_VERSION, ensureDir, sha256, userConfigDir, userHomeDir, writeJson, } from "@claudexor/util";
|
|
7
8
|
export const PLUGIN_HOSTS = ["cursor", "claude", "codex", "opencode"];
|
|
8
9
|
export const PLUGIN_TARGETS = [...PLUGIN_HOSTS, "all"];
|
|
@@ -21,10 +22,6 @@ function jsonText(value) {
|
|
|
21
22
|
function generatedMcpEnv(runtime) {
|
|
22
23
|
return {
|
|
23
24
|
CLAUDEXOR_CONFIG_DIR: runtime.configDir,
|
|
24
|
-
// MANAGED is drift-detection CONTENT (versions the generated artifact
|
|
25
|
-
// text for status/doctor). PLUGIN_VERSION is ALSO read at runtime:
|
|
26
|
-
// `mcp serve` compares it with the CLI version and warns on stderr when
|
|
27
|
-
// the installed artifacts are stale (repair + host reload fixes it).
|
|
28
25
|
CLAUDEXOR_MANAGED: MARKER,
|
|
29
26
|
CLAUDEXOR_PLUGIN_VERSION: CLAUDEXOR_VERSION,
|
|
30
27
|
};
|
|
@@ -46,19 +43,16 @@ function opencodeMcpEntry(runtime) {
|
|
|
46
43
|
command: [runtime.nodePath, runtime.cliPath, "mcp", "serve"],
|
|
47
44
|
environment: generatedMcpEnv(runtime),
|
|
48
45
|
enabled: true,
|
|
49
|
-
// Tool-DISCOVERY timeout only (OpenCode semantics). Tool EXECUTION time
|
|
50
|
-
// is governed by OpenCode's global MCP execution timeout — long verbs
|
|
51
|
-
// (agent/best-of) can exceed it; the generated README and INTEGRATIONS.md
|
|
52
|
-
// carry the guidance (raise experimental.mcp_timeout, or prefer the CLI
|
|
53
|
-
// for long runs). The runId trailer keeps abandoned calls recoverable.
|
|
54
46
|
timeout: 5000,
|
|
55
47
|
};
|
|
56
48
|
}
|
|
57
49
|
/** `claudexor inspect <runId>`, `follow <runId>`, ... — from the registry's recovery verbs. */
|
|
58
50
|
function recoveryVerbLine() {
|
|
59
51
|
const verbs = recoveryVerbs();
|
|
60
|
-
const parts = verbs.map((verb, i) =>
|
|
61
|
-
return parts.length > 1
|
|
52
|
+
const parts = verbs.map((verb, i) => i === 0 ? `\`claudexor ${verb} <runId>\`` : `\`${verb} <runId>\``);
|
|
53
|
+
return parts.length > 1
|
|
54
|
+
? `${parts.slice(0, -1).join(", ")}, or ${parts[parts.length - 1]}`
|
|
55
|
+
: (parts[0] ?? "");
|
|
62
56
|
}
|
|
63
57
|
function skillText(host) {
|
|
64
58
|
const namespace = host === "claude" ? "claudexor@skills-dir" : "claudexor";
|
|
@@ -110,9 +104,9 @@ function skillText(host) {
|
|
|
110
104
|
].join("\n");
|
|
111
105
|
}
|
|
112
106
|
function commandText(host) {
|
|
113
|
-
const frontmatter =
|
|
107
|
+
const frontmatter = host === "claude" || host === "cursor" || host === "opencode"
|
|
114
108
|
? ["---", "description: Use Claudexor CLI/MCP for harness-agnostic coding workflows", "---"]
|
|
115
|
-
: []
|
|
109
|
+
: [];
|
|
116
110
|
return [
|
|
117
111
|
...frontmatter,
|
|
118
112
|
managedComment().trimEnd(),
|
|
@@ -124,7 +118,9 @@ function commandText(host) {
|
|
|
124
118
|
"",
|
|
125
119
|
"Do not claim live thread parity through MCP. Ask for an explicit repo path if the target project is ambiguous.",
|
|
126
120
|
"",
|
|
127
|
-
]
|
|
121
|
+
]
|
|
122
|
+
.filter((line, i, all) => line !== "" || all[i - 1] !== "")
|
|
123
|
+
.join("\n");
|
|
128
124
|
}
|
|
129
125
|
function readmeText(host) {
|
|
130
126
|
return [
|
|
@@ -210,11 +206,31 @@ const HOST_DEFINITIONS = {
|
|
|
210
206
|
artifacts: (home, runtime) => {
|
|
211
207
|
const root = join(home, ".claude", "skills", "claudexor");
|
|
212
208
|
return [
|
|
213
|
-
{
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
209
|
+
{
|
|
210
|
+
path: join(root, ".claude-plugin", "plugin.json"),
|
|
211
|
+
content: manifest("claude"),
|
|
212
|
+
description: "Claude plugin manifest",
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
path: join(root, "skills", "claudexor", "SKILL.md"),
|
|
216
|
+
content: skillText("claude"),
|
|
217
|
+
description: "Claude skill",
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
path: join(root, "commands", "claudexor.md"),
|
|
221
|
+
content: commandText("claude"),
|
|
222
|
+
description: "Claude command",
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
path: join(root, ".mcp.json"),
|
|
226
|
+
content: jsonText(mcpServers(runtime)),
|
|
227
|
+
description: "Claude MCP config",
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
path: join(root, "README.md"),
|
|
231
|
+
content: readmeText("claude"),
|
|
232
|
+
description: "Claude integration README",
|
|
233
|
+
},
|
|
218
234
|
];
|
|
219
235
|
},
|
|
220
236
|
legacy: (home) => [
|
|
@@ -235,10 +251,26 @@ const HOST_DEFINITIONS = {
|
|
|
235
251
|
artifacts: (home, runtime) => {
|
|
236
252
|
const root = join(home, ".codex", "plugins", "claudexor");
|
|
237
253
|
return [
|
|
238
|
-
{
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
254
|
+
{
|
|
255
|
+
path: join(root, ".codex-plugin", "plugin.json"),
|
|
256
|
+
content: manifest("codex"),
|
|
257
|
+
description: "Codex plugin manifest",
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
path: join(root, "skills", "claudexor", "SKILL.md"),
|
|
261
|
+
content: skillText("codex"),
|
|
262
|
+
description: "Codex skill",
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
path: join(root, ".mcp.json"),
|
|
266
|
+
content: jsonText(mcpServers(runtime)),
|
|
267
|
+
description: "Codex MCP config",
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
path: join(root, "README.md"),
|
|
271
|
+
content: readmeText("codex"),
|
|
272
|
+
description: "Codex integration README",
|
|
273
|
+
},
|
|
242
274
|
];
|
|
243
275
|
},
|
|
244
276
|
config: "codex-marketplace",
|
|
@@ -260,11 +292,31 @@ const HOST_DEFINITIONS = {
|
|
|
260
292
|
artifacts: (home, runtime) => {
|
|
261
293
|
const root = join(home, ".cursor", "plugins", "local", "claudexor");
|
|
262
294
|
return [
|
|
263
|
-
{
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
295
|
+
{
|
|
296
|
+
path: join(root, ".cursor-plugin", "plugin.json"),
|
|
297
|
+
content: manifest("cursor"),
|
|
298
|
+
description: "Cursor plugin manifest",
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
path: join(root, "skills", "claudexor", "SKILL.md"),
|
|
302
|
+
content: skillText("cursor"),
|
|
303
|
+
description: "Cursor skill",
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
path: join(root, "commands", "claudexor.md"),
|
|
307
|
+
content: commandText("cursor"),
|
|
308
|
+
description: "Cursor command",
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
path: join(root, "mcp.json"),
|
|
312
|
+
content: jsonText(mcpServers(runtime)),
|
|
313
|
+
description: "Cursor MCP config",
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
path: join(root, "README.md"),
|
|
317
|
+
content: readmeText("cursor"),
|
|
318
|
+
description: "Cursor integration README",
|
|
319
|
+
},
|
|
268
320
|
];
|
|
269
321
|
},
|
|
270
322
|
legacy: (home) => [
|
|
@@ -285,9 +337,21 @@ const HOST_DEFINITIONS = {
|
|
|
285
337
|
artifacts: (home, runtime) => {
|
|
286
338
|
const root = join(home, ".config", "opencode");
|
|
287
339
|
return [
|
|
288
|
-
{
|
|
289
|
-
|
|
290
|
-
|
|
340
|
+
{
|
|
341
|
+
path: join(root, "skills", "claudexor", "SKILL.md"),
|
|
342
|
+
content: skillText("opencode"),
|
|
343
|
+
description: "OpenCode skill",
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
path: join(root, "commands", "claudexor.md"),
|
|
347
|
+
content: commandText("opencode"),
|
|
348
|
+
description: "OpenCode command",
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
path: join(root, "plugins", "claudexor.js"),
|
|
352
|
+
content: opencodePluginText(runtime),
|
|
353
|
+
description: "OpenCode JS plugin",
|
|
354
|
+
},
|
|
291
355
|
];
|
|
292
356
|
},
|
|
293
357
|
config: "opencode-mcp",
|
|
@@ -346,7 +410,9 @@ function loadState(configDir = userConfigDir()) {
|
|
|
346
410
|
catch (err) {
|
|
347
411
|
throw new Error(`plugin state is not valid JSON: ${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
348
412
|
}
|
|
349
|
-
if (!parsed ||
|
|
413
|
+
if (!parsed ||
|
|
414
|
+
typeof parsed !== "object" ||
|
|
415
|
+
parsed.version !== STATE_VERSION) {
|
|
350
416
|
throw new Error(`plugin state has unsupported shape: ${path}`);
|
|
351
417
|
}
|
|
352
418
|
const state = parsed;
|
|
@@ -376,7 +442,10 @@ function readText(path) {
|
|
|
376
442
|
return readFileSync(path, "utf8");
|
|
377
443
|
}
|
|
378
444
|
catch (err) {
|
|
379
|
-
if (err &&
|
|
445
|
+
if (err &&
|
|
446
|
+
typeof err === "object" &&
|
|
447
|
+
"code" in err &&
|
|
448
|
+
err.code === "ENOENT")
|
|
380
449
|
return null;
|
|
381
450
|
throw new Error(`unable to read ${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
382
451
|
}
|
|
@@ -451,7 +520,10 @@ function assertReadableLeaf(path) {
|
|
|
451
520
|
lstatSync(path);
|
|
452
521
|
}
|
|
453
522
|
catch (err) {
|
|
454
|
-
if (err &&
|
|
523
|
+
if (err &&
|
|
524
|
+
typeof err === "object" &&
|
|
525
|
+
"code" in err &&
|
|
526
|
+
err.code === "ENOENT")
|
|
455
527
|
return;
|
|
456
528
|
throw err;
|
|
457
529
|
}
|
|
@@ -475,7 +547,10 @@ function rejectSymlinkPath(path) {
|
|
|
475
547
|
st = lstatSync(path);
|
|
476
548
|
}
|
|
477
549
|
catch (err) {
|
|
478
|
-
if (err &&
|
|
550
|
+
if (err &&
|
|
551
|
+
typeof err === "object" &&
|
|
552
|
+
"code" in err &&
|
|
553
|
+
err.code === "ENOENT")
|
|
479
554
|
return;
|
|
480
555
|
throw err;
|
|
481
556
|
}
|
|
@@ -496,7 +571,10 @@ function assertSafeLeaf(path) {
|
|
|
496
571
|
throw new Error(`${path} is not a regular file`);
|
|
497
572
|
}
|
|
498
573
|
catch (err) {
|
|
499
|
-
if (err &&
|
|
574
|
+
if (err &&
|
|
575
|
+
typeof err === "object" &&
|
|
576
|
+
"code" in err &&
|
|
577
|
+
err.code === "ENOENT")
|
|
500
578
|
return;
|
|
501
579
|
throw err;
|
|
502
580
|
}
|
|
@@ -582,7 +660,7 @@ cross-family review, and budget balancing. Prefer it for multi-harness work.
|
|
|
582
660
|
- \`claudexor race "<task>" --n 4\` Best-of-N tournament + cross-family review
|
|
583
661
|
- \`claudexor plan "<task>"\` read-only plan
|
|
584
662
|
- \`claudexor create "<task>"\` create a new project
|
|
585
|
-
- \`claudexor inspect <run_id>\` inspect artifacts
|
|
663
|
+
- \`claudexor inspect <run_id>\` inspect artifacts in the external runtime store
|
|
586
664
|
|
|
587
665
|
These plugins are thin shims: they call the local CLI; all orchestration lives in claudexor.`;
|
|
588
666
|
const OLD_LEGACY_CLAUDE_COMMAND = `---
|
|
@@ -603,7 +681,8 @@ function legacyThinShimVerifier(file, text) {
|
|
|
603
681
|
if (file.endsWith("plugin.json"))
|
|
604
682
|
return isOldThinShimManifest(text);
|
|
605
683
|
if (file === "commands/claudexor.md") {
|
|
606
|
-
return exactLegacyText(text, OLD_LEGACY_CLAUDE_COMMAND) ||
|
|
684
|
+
return (exactLegacyText(text, OLD_LEGACY_CLAUDE_COMMAND) ||
|
|
685
|
+
exactLegacyText(text, OLD_LEGACY_CURSOR_COMMAND));
|
|
607
686
|
}
|
|
608
687
|
return false;
|
|
609
688
|
}
|
|
@@ -653,11 +732,14 @@ function backupFile(def, runtime, path) {
|
|
|
653
732
|
return dest;
|
|
654
733
|
}
|
|
655
734
|
function hasManagedMarker(text) {
|
|
656
|
-
return text.includes(MARKER) || text.includes('"marker": "claudexor:managed host-plugin-lifecycle"');
|
|
735
|
+
return (text.includes(MARKER) || text.includes('"marker": "claudexor:managed host-plugin-lifecycle"'));
|
|
657
736
|
}
|
|
658
737
|
function artifactOwned(state, host, artifact, current, force) {
|
|
659
738
|
const entry = state.hosts[host]?.artifacts[artifact.path];
|
|
660
|
-
return entry?.hash === hashText(current) ||
|
|
739
|
+
return (entry?.hash === hashText(current) ||
|
|
740
|
+
(entry !== undefined && hasManagedMarker(current)) ||
|
|
741
|
+
current === artifact.content ||
|
|
742
|
+
(force && hasManagedMarker(current)));
|
|
661
743
|
}
|
|
662
744
|
function isPathInside(root, path) {
|
|
663
745
|
const rel = relative(root, path);
|
|
@@ -712,7 +794,10 @@ function configEntryOwned(stateEntry, current, desired, force, requireState = fa
|
|
|
712
794
|
const currentText = JSON.stringify(current);
|
|
713
795
|
const hasMarker = currentText.includes(MARKER);
|
|
714
796
|
const exactMarkedDesired = !requireState && hasMarker && jsonText(current) === jsonText(desired);
|
|
715
|
-
return stateEntry?.hash === hashText(jsonText(current)) ||
|
|
797
|
+
return (stateEntry?.hash === hashText(jsonText(current)) ||
|
|
798
|
+
exactMarkedDesired ||
|
|
799
|
+
(stateEntry !== undefined && hasMarker) ||
|
|
800
|
+
(force && hasMarker));
|
|
716
801
|
}
|
|
717
802
|
function codexMarketplaceEntries(plugins) {
|
|
718
803
|
return plugins
|
|
@@ -723,8 +808,12 @@ function mergeCodexMarketplace(state, dryRun, force, def, runtime, res) {
|
|
|
723
808
|
const path = join(userHomeDir(), ".agents", "plugins", "marketplace.json");
|
|
724
809
|
const desired = desiredCodexMarketplaceEntry();
|
|
725
810
|
const parsed = readJsonFile(path);
|
|
726
|
-
const base = parsed === undefined
|
|
727
|
-
|
|
811
|
+
const base = parsed === undefined
|
|
812
|
+
? { name: "personal", interface: { displayName: "Personal" }, plugins: [] }
|
|
813
|
+
: parsed;
|
|
814
|
+
if (!base ||
|
|
815
|
+
typeof base !== "object" ||
|
|
816
|
+
!Array.isArray(base.plugins)) {
|
|
728
817
|
res.errors.push(`${path} is not a Codex marketplace JSON object with plugins[]`);
|
|
729
818
|
return false;
|
|
730
819
|
}
|
|
@@ -831,7 +920,10 @@ function checkConfig(host, state, res, runtime) {
|
|
|
831
920
|
return false;
|
|
832
921
|
}
|
|
833
922
|
const desired = desiredCodexMarketplaceEntry();
|
|
834
|
-
if (!parsed ||
|
|
923
|
+
if (!parsed ||
|
|
924
|
+
typeof parsed !== "object" ||
|
|
925
|
+
Array.isArray(parsed) ||
|
|
926
|
+
!Array.isArray(parsed.plugins)) {
|
|
835
927
|
res.errors.push(`${path} is not a Codex marketplace JSON object with plugins[]`);
|
|
836
928
|
return false;
|
|
837
929
|
}
|
|
@@ -848,7 +940,9 @@ function checkConfig(host, state, res, runtime) {
|
|
|
848
940
|
res.errors.push(`${path} has an unowned claudexor marketplace entry`);
|
|
849
941
|
return false;
|
|
850
942
|
}
|
|
851
|
-
res.notes.push(matches.length > 0
|
|
943
|
+
res.notes.push(matches.length > 0
|
|
944
|
+
? "Codex marketplace entry is drifted"
|
|
945
|
+
: "Codex marketplace entry is missing");
|
|
852
946
|
return false;
|
|
853
947
|
}
|
|
854
948
|
if (host === "opencode") {
|
|
@@ -900,7 +994,9 @@ function removeConfig(host, state, dryRun, force, def, runtime, res) {
|
|
|
900
994
|
const parsed = readJsonFile(path);
|
|
901
995
|
if (parsed === undefined)
|
|
902
996
|
return true;
|
|
903
|
-
if (!parsed ||
|
|
997
|
+
if (!parsed ||
|
|
998
|
+
typeof parsed !== "object" ||
|
|
999
|
+
!Array.isArray(parsed.plugins)) {
|
|
904
1000
|
res.errors.push(`${path} is not a Codex marketplace JSON object with plugins[]`);
|
|
905
1001
|
return false;
|
|
906
1002
|
}
|
|
@@ -1012,13 +1108,22 @@ function applyArtifacts(def, artifacts, state, dryRun, force, runtime, res) {
|
|
|
1012
1108
|
function obsoleteArtifactRoots(host, home) {
|
|
1013
1109
|
switch (host) {
|
|
1014
1110
|
case "claude":
|
|
1015
|
-
return [
|
|
1111
|
+
return [
|
|
1112
|
+
join(home, ".claude", "skills", "claudexor"),
|
|
1113
|
+
join(home, ".claude", "plugins", "claudexor"),
|
|
1114
|
+
];
|
|
1016
1115
|
case "codex":
|
|
1017
|
-
return [
|
|
1116
|
+
return [
|
|
1117
|
+
join(home, ".codex", "plugins", "claudexor"),
|
|
1118
|
+
join(home, ".agents", "skills", "claudexor"),
|
|
1119
|
+
];
|
|
1018
1120
|
case "cursor":
|
|
1019
1121
|
return [join(home, ".cursor", "plugins", "local", "claudexor")];
|
|
1020
1122
|
case "opencode":
|
|
1021
|
-
return [
|
|
1123
|
+
return [
|
|
1124
|
+
join(home, ".config", "opencode", "skills", "claudexor"),
|
|
1125
|
+
join(home, ".config", "opencode", "claudexor"),
|
|
1126
|
+
];
|
|
1022
1127
|
}
|
|
1023
1128
|
}
|
|
1024
1129
|
function artifactStatePathAllowed(def, artifacts, path) {
|
|
@@ -1030,7 +1135,9 @@ function removeObsoleteStateArtifacts(def, artifacts, state, dryRun, _force, res
|
|
|
1030
1135
|
const hs = hostState(state, def.host);
|
|
1031
1136
|
const allowed = new Set(artifacts.map((a) => a.path));
|
|
1032
1137
|
for (const [path, entry] of Object.entries(hs.artifacts)) {
|
|
1033
|
-
if (entry.host !== def.host ||
|
|
1138
|
+
if (entry.host !== def.host ||
|
|
1139
|
+
entry.path !== path ||
|
|
1140
|
+
!artifactStatePathAllowed(def, artifacts, path)) {
|
|
1034
1141
|
res.errors.push(`${stateFilePath()} contains out-of-scope ${def.host} artifact state for ${path}; remove that state entry or clean it manually`);
|
|
1035
1142
|
return false;
|
|
1036
1143
|
}
|
|
@@ -1067,7 +1174,9 @@ function removeArtifacts(def, artifacts, state, dryRun, force, res) {
|
|
|
1067
1174
|
continue;
|
|
1068
1175
|
}
|
|
1069
1176
|
const desired = artifacts.find((a) => a.path === path);
|
|
1070
|
-
const owned = hs.artifacts[path]?.hash === hashText(current) ||
|
|
1177
|
+
const owned = hs.artifacts[path]?.hash === hashText(current) ||
|
|
1178
|
+
current === desired?.content ||
|
|
1179
|
+
(force && hasManagedMarker(current));
|
|
1071
1180
|
if (!owned) {
|
|
1072
1181
|
res.errors.push(`${path} exists but no longer matches Claudexor ownership state`);
|
|
1073
1182
|
return false;
|
|
@@ -1082,10 +1191,7 @@ function removeArtifacts(def, artifacts, state, dryRun, force, res) {
|
|
|
1082
1191
|
pruneEmptyDirs(def.root(userHomeDir()));
|
|
1083
1192
|
return true;
|
|
1084
1193
|
}
|
|
1085
|
-
function pruneEmptyDirs(_root) {
|
|
1086
|
-
// Deliberately conservative: removing files is enough for uninstall; avoid
|
|
1087
|
-
// recursive directory cleanup in user config roots.
|
|
1088
|
-
}
|
|
1194
|
+
function pruneEmptyDirs(_root) { }
|
|
1089
1195
|
function removeVerifiedLegacy(def, dryRun, res) {
|
|
1090
1196
|
for (const legacy of def.legacy(userHomeDir())) {
|
|
1091
1197
|
if (!existsSync(legacy.path))
|
|
@@ -1142,7 +1248,8 @@ async function mcpSelfTest(runtime) {
|
|
|
1142
1248
|
const init = lines.find((line) => line && typeof line === "object" && line.id === 1);
|
|
1143
1249
|
if (init?.result?.serverInfo?.name && !sentToolsList) {
|
|
1144
1250
|
sentToolsList = true;
|
|
1145
|
-
child.stdin.write(JSON.stringify({ jsonrpc: "2.0", method: "notifications/initialized", params: {} }) +
|
|
1251
|
+
child.stdin.write(JSON.stringify({ jsonrpc: "2.0", method: "notifications/initialized", params: {} }) +
|
|
1252
|
+
"\n");
|
|
1146
1253
|
child.stdin.write(JSON.stringify({ jsonrpc: "2.0", id: 2, method: "tools/list", params: {} }) + "\n");
|
|
1147
1254
|
}
|
|
1148
1255
|
const tools = lines.find((line) => line && typeof line === "object" && line.id === 2);
|
|
@@ -1151,7 +1258,8 @@ async function mcpSelfTest(runtime) {
|
|
|
1151
1258
|
const listed = tools.result?.tools;
|
|
1152
1259
|
clearTimeout(timer);
|
|
1153
1260
|
child.kill("SIGTERM");
|
|
1154
|
-
if (Array.isArray(listed) &&
|
|
1261
|
+
if (Array.isArray(listed) &&
|
|
1262
|
+
listed.some((t) => t.name === "claudexor_status")) {
|
|
1155
1263
|
resolve(null);
|
|
1156
1264
|
}
|
|
1157
1265
|
else {
|
|
@@ -1168,7 +1276,9 @@ async function mcpSelfTest(runtime) {
|
|
|
1168
1276
|
}
|
|
1169
1277
|
}
|
|
1170
1278
|
});
|
|
1171
|
-
child.stderr.on("data", (d) => {
|
|
1279
|
+
child.stderr.on("data", (d) => {
|
|
1280
|
+
stderr += String(d);
|
|
1281
|
+
});
|
|
1172
1282
|
child.on("error", (err) => {
|
|
1173
1283
|
if (settled)
|
|
1174
1284
|
return;
|
|
@@ -1200,7 +1310,16 @@ async function mcpSelfTest(runtime) {
|
|
|
1200
1310
|
}
|
|
1201
1311
|
function mcpSelfTestEnv(runtime) {
|
|
1202
1312
|
const env = {};
|
|
1203
|
-
for (const key of [
|
|
1313
|
+
for (const key of [
|
|
1314
|
+
"HOME",
|
|
1315
|
+
"PATH",
|
|
1316
|
+
"CLAUDEXOR_CONFIG_DIR",
|
|
1317
|
+
"TMPDIR",
|
|
1318
|
+
"TMP",
|
|
1319
|
+
"TEMP",
|
|
1320
|
+
"LANG",
|
|
1321
|
+
"LC_ALL",
|
|
1322
|
+
]) {
|
|
1204
1323
|
const value = process.env[key];
|
|
1205
1324
|
if (value)
|
|
1206
1325
|
env[key] = value;
|
|
@@ -1234,8 +1353,9 @@ async function runHost(def, verb, options, state, runtime) {
|
|
|
1234
1353
|
try {
|
|
1235
1354
|
if (verb === "status" || verb === "doctor") {
|
|
1236
1355
|
const art = checkArtifacts(def, artifacts, state, res);
|
|
1237
|
-
const configOk = checkConfig(def.host, state, res, runtime)
|
|
1238
|
-
|
|
1356
|
+
const configOk = checkConfig(def.host, state, res, runtime) &&
|
|
1357
|
+
(def.host !== "claude" || manageClaudeStatusline(verb, { ...runtime, dryRun }, res));
|
|
1358
|
+
const hasConfig = def.config !== undefined || def.host === "claude";
|
|
1239
1359
|
if (res.errors.length > 0 || art.blocked)
|
|
1240
1360
|
res.state = "blocked";
|
|
1241
1361
|
else if (art.all && configOk)
|
|
@@ -1246,7 +1366,9 @@ async function runHost(def, verb, options, state, runtime) {
|
|
|
1246
1366
|
res.state = "partial";
|
|
1247
1367
|
else
|
|
1248
1368
|
res.state = "missing";
|
|
1249
|
-
if (verb === "doctor" &&
|
|
1369
|
+
if (verb === "doctor" &&
|
|
1370
|
+
dryRun &&
|
|
1371
|
+
(res.state === "installed" || res.state === "registered")) {
|
|
1250
1372
|
res.actions.push("would run MCP initialize/initialized/tools-list self-test");
|
|
1251
1373
|
}
|
|
1252
1374
|
else if (verb === "doctor" && (res.state === "installed" || res.state === "registered")) {
|
|
@@ -1263,6 +1385,10 @@ async function runHost(def, verb, options, state, runtime) {
|
|
|
1263
1385
|
return res;
|
|
1264
1386
|
}
|
|
1265
1387
|
if (verb === "uninstall") {
|
|
1388
|
+
if (def.host === "claude" && !manageClaudeStatusline(verb, { ...runtime, dryRun }, res)) {
|
|
1389
|
+
res.state = "blocked";
|
|
1390
|
+
return res;
|
|
1391
|
+
}
|
|
1266
1392
|
if (!removeVerifiedLegacy(def, dryRun, res)) {
|
|
1267
1393
|
res.state = "blocked";
|
|
1268
1394
|
return res;
|
|
@@ -1291,11 +1417,17 @@ async function runHost(def, verb, options, state, runtime) {
|
|
|
1291
1417
|
res.state = "blocked";
|
|
1292
1418
|
return res;
|
|
1293
1419
|
}
|
|
1294
|
-
if (def.config === "codex-marketplace" &&
|
|
1420
|
+
if (def.config === "codex-marketplace" &&
|
|
1421
|
+
!mergeCodexMarketplace(state, dryRun, force, def, runtime, res)) {
|
|
1422
|
+
res.state = "blocked";
|
|
1423
|
+
return res;
|
|
1424
|
+
}
|
|
1425
|
+
if (def.config === "opencode-mcp" &&
|
|
1426
|
+
!mergeOpenCodeMcp(state, dryRun, force, def, runtime, res)) {
|
|
1295
1427
|
res.state = "blocked";
|
|
1296
1428
|
return res;
|
|
1297
1429
|
}
|
|
1298
|
-
if (def.
|
|
1430
|
+
if (def.host === "claude" && !manageClaudeStatusline(verb, { ...runtime, dryRun }, res)) {
|
|
1299
1431
|
res.state = "blocked";
|
|
1300
1432
|
return res;
|
|
1301
1433
|
}
|