Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/reject-non-cargo-program.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"cargo-hauler": patch
---

`hauler exec` and `hauler request` now refuse a program that is not cargo, such as `hauler exec -- ls -la`, with `program must be cargo, got ls` and exit code 2. Before, the daemon or the local passthrough ran it and reported it as a cargo run.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Correct the request exit code in the release note

In the documented hauler request -- ls scenario, the daemon rejection is converted to a regular error by runTicketEffect, so the routed CLI exits with code 1; only hauler exec maps a bad-intent response to code 2. Claiming that both commands exit 2 gives scripts consuming the release note the wrong contract, so distinguish the two exit codes or change the request command accordingly.

Useful? React with 👍 / 👎.

2 changes: 1 addition & 1 deletion artifact/agent-bundle.compile-evidence.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion artifact/agent-bundle.manifest.json

Large diffs are not rendered by default.

14 changes: 6 additions & 8 deletions artifact/bin/cargo-hauler-flight.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18541,6 +18541,8 @@ const sortedUnique = (values)=>[
].sort((left, right)=>left.localeCompare(right));
const splitFeatures = (value)=>value.split(/[,\s]+/u).filter((feature)=>feature.length > 0);
const cargoExecutablePattern = /(?:^|[/\\])cargo(?:\.exe)?$/u;
class ProgramNotCargoError extends Error {
}
const envProgramPattern = /(?:^|[/\\])env$/u;
const shellProgramPattern = /(?:^|[/\\])(?:bash|sh|zsh|dash)$/u;
const shellAssignmentPattern = /^([A-Za-z_][A-Za-z0-9_]*)=([\s\S]*)$/u;
Expand Down Expand Up @@ -18903,14 +18905,10 @@ const parseCargoArgv = (input)=>{
}
if (argv[0] !== undefined && cargoExecutablePattern.test(argv[0])) {
argv.shift();
} else if (prefix.peeled) {
throw new Error(`program must be cargo, got ${argv[0] ?? 'nothing'}`);
} else if (argv[0] !== undefined && /[/\\]/u.test(argv[0])) {
// A path-shaped first argument is a program, and the only program the
// broker runs is cargo. A mis-resolved shim once submitted
// `~/.cargo/bin/rustup test …`; running it would fail and the path would
// be recorded as the "subcommand" in every metrics view.
throw new Error(`program must be cargo, got ${argv[0]}`);
} else if (wrapper === null || prefix.peeled) {
// The executor spawns argv[0], so any other first word would run as a
// program rather than be read as a cargo subcommand.
throw new ProgramNotCargoError(`program must be cargo, got ${argv[0] ?? 'nothing'}`);
}
const toolchainArgument = argv[0]?.startsWith('+') === true ? argv.shift() : undefined;
const toolchain = toolchainArgument?.slice(1) || null;
Expand Down
14 changes: 6 additions & 8 deletions artifact/bin/cargo-hauler.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19484,6 +19484,8 @@ const sortedUnique = (values)=>[
].sort((left, right)=>left.localeCompare(right));
const splitFeatures = (value)=>value.split(/[,\s]+/u).filter((feature)=>feature.length > 0);
const cargoExecutablePattern = /(?:^|[/\\])cargo(?:\.exe)?$/u;
class ProgramNotCargoError extends Error {
}
const envProgramPattern = /(?:^|[/\\])env$/u;
const shellProgramPattern = /(?:^|[/\\])(?:bash|sh|zsh|dash)$/u;
const shellAssignmentPattern = /^([A-Za-z_][A-Za-z0-9_]*)=([\s\S]*)$/u;
Expand Down Expand Up @@ -19846,14 +19848,10 @@ const parseCargoArgv = (input)=>{
}
if (argv[0] !== undefined && cargoExecutablePattern.test(argv[0])) {
argv.shift();
} else if (prefix.peeled) {
throw new Error(`program must be cargo, got ${argv[0] ?? 'nothing'}`);
} else if (argv[0] !== undefined && /[/\\]/u.test(argv[0])) {
// A path-shaped first argument is a program, and the only program the
// broker runs is cargo. A mis-resolved shim once submitted
// `~/.cargo/bin/rustup test …`; running it would fail and the path would
// be recorded as the "subcommand" in every metrics view.
throw new Error(`program must be cargo, got ${argv[0]}`);
} else if (wrapper === null || prefix.peeled) {
// The executor spawns argv[0], so any other first word would run as a
// program rather than be read as a cargo subcommand.
throw new ProgramNotCargoError(`program must be cargo, got ${argv[0] ?? 'nothing'}`);
}
const toolchainArgument = argv[0]?.startsWith('+') === true ? argv.shift() : undefined;
const toolchain = toolchainArgument?.slice(1) || null;
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-session-start.claude.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79622,7 +79622,7 @@ __webpack_require__.a(__webpack_module__, async function (__rspack_load_async_de



const artifactEpoch = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const artifactEpoch = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const flightArtifactEpoch = "cargo-hauler@0.9.13";
const canonicalEvent = "session/start";
const capabilityRevision = "2.1.260";
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-session-start.codex.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79622,7 +79622,7 @@ __webpack_require__.a(__webpack_module__, async function (__rspack_load_async_de



const artifactEpoch = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const artifactEpoch = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const flightArtifactEpoch = "cargo-hauler@0.9.13";
const canonicalEvent = "session/start";
const capabilityRevision = "0.147.0";
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-session-start.cursor.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79622,7 +79622,7 @@ __webpack_require__.a(__webpack_module__, async function (__rspack_load_async_de



const artifactEpoch = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const artifactEpoch = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const flightArtifactEpoch = "cargo-hauler@0.9.13";
const canonicalEvent = "session/start";
const capabilityRevision = "2026-08-28";
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-stop.claude.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79622,7 +79622,7 @@ __webpack_require__.a(__webpack_module__, async function (__rspack_load_async_de



const artifactEpoch = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const artifactEpoch = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const flightArtifactEpoch = "cargo-hauler@0.9.13";
const canonicalEvent = "stop";
const capabilityRevision = "2.1.260";
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-stop.codex.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79622,7 +79622,7 @@ __webpack_require__.a(__webpack_module__, async function (__rspack_load_async_de



const artifactEpoch = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const artifactEpoch = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const flightArtifactEpoch = "cargo-hauler@0.9.13";
const canonicalEvent = "stop";
const capabilityRevision = "0.147.0";
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-stop.cursor.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79622,7 +79622,7 @@ __webpack_require__.a(__webpack_module__, async function (__rspack_load_async_de



const artifactEpoch = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const artifactEpoch = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const flightArtifactEpoch = "cargo-hauler@0.9.13";
const canonicalEvent = "stop";
const capabilityRevision = "2026-08-28";
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-tool-after.claude.execute.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79621,7 +79621,7 @@ __webpack_require__.a(__webpack_module__, async function (__rspack_load_async_de



const artifactEpoch = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const artifactEpoch = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const flightArtifactEpoch = "cargo-hauler@0.9.13";
const canonicalEvent = "tool/after";
const capabilityRevision = "2.1.260";
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-tool-after.claude.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28148,7 +28148,7 @@ const prepareRouteInvocation = async (nativeInput, signal, observer, receipt)=>{
return withEventState(signal, async (bindings)=>{
const gate = await (0,_agent_bundle_runtime_request__rspack_import_6/* .runAgentRequest */.iC)({
invocation: {
artifactEpoch: "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37",
artifactEpoch: "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c",
hostContractRevision: capabilityRevision,
kind: "event",
operationId: `event:${canonicalEvent}`,
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-tool-after.codex.execute.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79621,7 +79621,7 @@ __webpack_require__.a(__webpack_module__, async function (__rspack_load_async_de



const artifactEpoch = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const artifactEpoch = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const flightArtifactEpoch = "cargo-hauler@0.9.13";
const canonicalEvent = "tool/after";
const capabilityRevision = "0.147.0";
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-tool-after.codex.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28148,7 +28148,7 @@ const prepareRouteInvocation = async (nativeInput, signal, observer, receipt)=>{
return withEventState(signal, async (bindings)=>{
const gate = await (0,_agent_bundle_runtime_request__rspack_import_6/* .runAgentRequest */.iC)({
invocation: {
artifactEpoch: "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37",
artifactEpoch: "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c",
hostContractRevision: capabilityRevision,
kind: "event",
operationId: `event:${canonicalEvent}`,
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-tool-after.cursor.execute.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79621,7 +79621,7 @@ __webpack_require__.a(__webpack_module__, async function (__rspack_load_async_de



const artifactEpoch = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const artifactEpoch = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const flightArtifactEpoch = "cargo-hauler@0.9.13";
const canonicalEvent = "tool/after";
const capabilityRevision = "2026-08-28";
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-tool-after.cursor.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28148,7 +28148,7 @@ const prepareRouteInvocation = async (nativeInput, signal, observer, receipt)=>{
return withEventState(signal, async (bindings)=>{
const gate = await (0,_agent_bundle_runtime_request__rspack_import_6/* .runAgentRequest */.iC)({
invocation: {
artifactEpoch: "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37",
artifactEpoch: "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c",
hostContractRevision: capabilityRevision,
kind: "event",
operationId: `event:${canonicalEvent}`,
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-tool-before.claude.execute.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79621,7 +79621,7 @@ __webpack_require__.a(__webpack_module__, async function (__rspack_load_async_de



const artifactEpoch = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const artifactEpoch = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const flightArtifactEpoch = "cargo-hauler@0.9.13";
const canonicalEvent = "tool/before";
const capabilityRevision = "2.1.260";
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-tool-before.claude.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25375,7 +25375,7 @@ const prepareRouteInvocation = async (nativeInput, signal, observer, receipt)=>{
return withEventState(signal, async (bindings)=>{
const gate = await (0,_agent_bundle_runtime_request__rspack_import_6/* .runAgentRequest */.iC)({
invocation: {
artifactEpoch: "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37",
artifactEpoch: "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c",
hostContractRevision: capabilityRevision,
kind: "event",
operationId: `event:${canonicalEvent}`,
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-tool-before.codex.execute.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79621,7 +79621,7 @@ __webpack_require__.a(__webpack_module__, async function (__rspack_load_async_de



const artifactEpoch = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const artifactEpoch = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const flightArtifactEpoch = "cargo-hauler@0.9.13";
const canonicalEvent = "tool/before";
const capabilityRevision = "0.147.0";
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-tool-before.codex.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25375,7 +25375,7 @@ const prepareRouteInvocation = async (nativeInput, signal, observer, receipt)=>{
return withEventState(signal, async (bindings)=>{
const gate = await (0,_agent_bundle_runtime_request__rspack_import_6/* .runAgentRequest */.iC)({
invocation: {
artifactEpoch: "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37",
artifactEpoch: "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c",
hostContractRevision: capabilityRevision,
kind: "event",
operationId: `event:${canonicalEvent}`,
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-tool-before.cursor.execute.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79621,7 +79621,7 @@ __webpack_require__.a(__webpack_module__, async function (__rspack_load_async_de



const artifactEpoch = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const artifactEpoch = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const flightArtifactEpoch = "cargo-hauler@0.9.13";
const canonicalEvent = "tool/before";
const capabilityRevision = "2026-08-28";
Expand Down
2 changes: 1 addition & 1 deletion artifact/hooks/event-route-tool-before.cursor.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25375,7 +25375,7 @@ const prepareRouteInvocation = async (nativeInput, signal, observer, receipt)=>{
return withEventState(signal, async (bindings)=>{
const gate = await (0,_agent_bundle_runtime_request__rspack_import_6/* .runAgentRequest */.iC)({
invocation: {
artifactEpoch: "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37",
artifactEpoch: "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c",
hostContractRevision: capabilityRevision,
kind: "event",
operationId: `event:${canonicalEvent}`,
Expand Down
14 changes: 6 additions & 8 deletions artifact/hooks/hooks-flight.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20758,6 +20758,8 @@ const sortedUnique = (values)=>[
].sort((left, right)=>left.localeCompare(right));
const splitFeatures = (value)=>value.split(/[,\s]+/u).filter((feature)=>feature.length > 0);
const cargoExecutablePattern = /(?:^|[/\\])cargo(?:\.exe)?$/u;
class ProgramNotCargoError extends Error {
}
const envProgramPattern = /(?:^|[/\\])env$/u;
const shellProgramPattern = /(?:^|[/\\])(?:bash|sh|zsh|dash)$/u;
const shellAssignmentPattern = /^([A-Za-z_][A-Za-z0-9_]*)=([\s\S]*)$/u;
Expand Down Expand Up @@ -21120,14 +21122,10 @@ const parseCargoArgv = (input)=>{
}
if (argv[0] !== undefined && cargoExecutablePattern.test(argv[0])) {
argv.shift();
} else if (prefix.peeled) {
throw new Error(`program must be cargo, got ${argv[0] ?? 'nothing'}`);
} else if (argv[0] !== undefined && /[/\\]/u.test(argv[0])) {
// A path-shaped first argument is a program, and the only program the
// broker runs is cargo. A mis-resolved shim once submitted
// `~/.cargo/bin/rustup test …`; running it would fail and the path would
// be recorded as the "subcommand" in every metrics view.
throw new Error(`program must be cargo, got ${argv[0]}`);
} else if (wrapper === null || prefix.peeled) {
// The executor spawns argv[0], so any other first word would run as a
// program rather than be read as a cargo subcommand.
throw new ProgramNotCargoError(`program must be cargo, got ${argv[0] ?? 'nothing'}`);
}
const toolchainArgument = argv[0]?.startsWith('+') === true ? argv.shift() : undefined;
const toolchain = toolchainArgument?.slice(1) || null;
Expand Down
14 changes: 6 additions & 8 deletions artifact/mcp/mcp-hauler-2b8242f9-flight.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20771,6 +20771,8 @@ const sortedUnique = (values)=>[
].sort((left, right)=>left.localeCompare(right));
const splitFeatures = (value)=>value.split(/[,\s]+/u).filter((feature)=>feature.length > 0);
const cargoExecutablePattern = /(?:^|[/\\])cargo(?:\.exe)?$/u;
class ProgramNotCargoError extends Error {
}
const envProgramPattern = /(?:^|[/\\])env$/u;
const shellProgramPattern = /(?:^|[/\\])(?:bash|sh|zsh|dash)$/u;
const shellAssignmentPattern = /^([A-Za-z_][A-Za-z0-9_]*)=([\s\S]*)$/u;
Expand Down Expand Up @@ -21133,14 +21135,10 @@ const parseCargoArgv = (input)=>{
}
if (argv[0] !== undefined && cargoExecutablePattern.test(argv[0])) {
argv.shift();
} else if (prefix.peeled) {
throw new Error(`program must be cargo, got ${argv[0] ?? 'nothing'}`);
} else if (argv[0] !== undefined && /[/\\]/u.test(argv[0])) {
// A path-shaped first argument is a program, and the only program the
// broker runs is cargo. A mis-resolved shim once submitted
// `~/.cargo/bin/rustup test …`; running it would fail and the path would
// be recorded as the "subcommand" in every metrics view.
throw new Error(`program must be cargo, got ${argv[0]}`);
} else if (wrapper === null || prefix.peeled) {
// The executor spawns argv[0], so any other first word would run as a
// program rather than be read as a cargo subcommand.
throw new ProgramNotCargoError(`program must be cargo, got ${argv[0] ?? 'nothing'}`);
}
const toolchainArgument = argv[0]?.startsWith('+') === true ? argv.shift() : undefined;
const toolchain = toolchainArgument?.slice(1) || null;
Expand Down
16 changes: 7 additions & 9 deletions artifact/mcp/mcp-hauler-2b8242f9.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16109,6 +16109,8 @@ const sortedUnique = (values)=>[
].sort((left, right)=>left.localeCompare(right));
const splitFeatures = (value)=>value.split(/[,\s]+/u).filter((feature)=>feature.length > 0);
const cargoExecutablePattern = /(?:^|[/\\])cargo(?:\.exe)?$/u;
class ProgramNotCargoError extends Error {
}
const envProgramPattern = /(?:^|[/\\])env$/u;
const shellProgramPattern = /(?:^|[/\\])(?:bash|sh|zsh|dash)$/u;
const shellAssignmentPattern = /^([A-Za-z_][A-Za-z0-9_]*)=([\s\S]*)$/u;
Expand Down Expand Up @@ -16471,14 +16473,10 @@ const parseCargoArgv = (input)=>{
}
if (argv[0] !== undefined && cargoExecutablePattern.test(argv[0])) {
argv.shift();
} else if (prefix.peeled) {
throw new Error(`program must be cargo, got ${argv[0] ?? 'nothing'}`);
} else if (argv[0] !== undefined && /[/\\]/u.test(argv[0])) {
// A path-shaped first argument is a program, and the only program the
// broker runs is cargo. A mis-resolved shim once submitted
// `~/.cargo/bin/rustup test …`; running it would fail and the path would
// be recorded as the "subcommand" in every metrics view.
throw new Error(`program must be cargo, got ${argv[0]}`);
} else if (wrapper === null || prefix.peeled) {
// The executor spawns argv[0], so any other first word would run as a
// program rather than be read as a cargo subcommand.
throw new ProgramNotCargoError(`program must be cargo, got ${argv[0] ?? 'nothing'}`);
}
const toolchainArgument = argv[0]?.startsWith('+') === true ? argv.shift() : undefined;
const toolchain = toolchainArgument?.slice(1) || null;
Expand Down Expand Up @@ -161006,7 +161004,7 @@ const routes = Object.freeze({
name: "hauler_status"
})
});
const EVENT_ARTIFACT_EPOCH = "f882c624b8ebe1a91f905f001ec7fec248d570b04b8312bfa982731eb131eb37";
const EVENT_ARTIFACT_EPOCH = "25ac9cff30db935e4c560a178082b85c33c392cdaa549ff10e3de3f22a26f27c";
const EVENT_ALLOWED_TARGETS = Object.freeze([
"claude",
"codex",
Expand Down
Loading
Loading