Skip to content

Commit 31c9ff5

Browse files
fix(cli): fail invalid integration commands (#160)
1 parent 12731fd commit 31c9ff5

3 files changed

Lines changed: 38 additions & 10 deletions

File tree

bin/moshcode.mjs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,12 @@ async function main() {
265265
return;
266266
}
267267
if (cmd === "mcp") {
268-
return mcpCommand(rest);
268+
process.exitCode = (await mcpCommand(rest)) || 0;
269+
return;
269270
}
270271
if (cmd === "skill" || cmd === "skills") {
271-
return skillCommand(rest);
272+
process.exitCode = (await skillCommand(rest)) || 0;
273+
return;
272274
}
273275
if (cmd === "install") {
274276
const target = rest.find((a) => !a.startsWith("-"))?.toLowerCase();

src/integrations.mjs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,9 @@ function summarize(results) {
155155
/** Run `/mcp …`. `tokens` are the words after `mcp`. */
156156
export async function mcpCommand(tokens) {
157157
const parsed = parseMcp(tokens);
158-
if (parsed.list) { printMcpTargets(); return; }
159-
if (parsed.showCatalog) { printMcpCatalog(); return; }
160-
if (parsed.error) { console.log(err(parsed.error)); return; }
158+
if (parsed.list) { printMcpTargets(); return 0; }
159+
if (parsed.showCatalog) { printMcpCatalog(); return 0; }
160+
if (parsed.error) { console.log(err(parsed.error)); return 1; }
161161

162162
const { spec } = parsed;
163163
console.log(info(`registering ${bone(spec.name)}${ash(spec.target)} across MCP engines…`));
@@ -174,32 +174,34 @@ export async function mcpCommand(tokens) {
174174
if (spec.headers.length || /^https?:/i.test(spec.target)) {
175175
console.log(ash(" note: OAuth/HTTP servers may still need per-engine auth (e.g. `opencode mcp auth`, `codex mcp login`)."));
176176
}
177+
return 0;
177178
}
178179

179180
/** Run `/skill …`. `tokens` are the words after `skill`. */
180181
export async function skillCommand(tokens) {
181182
const verb = tokens[0];
182-
if (!verb || verb === "list") { printSkillTargets(); return; }
183+
if (!verb || verb === "list") { printSkillTargets(); return 0; }
183184
if (verb !== "install") {
184185
console.log(err(`unknown skill verb "${verb}" — try ${SKILL_VERBS.map(({ name }) => name).join(" or ")}`));
185-
return;
186+
return 1;
186187
}
187188

188189
const rest = tokens.slice(1);
189190
let name, source;
190191
for (let i = 0; i < rest.length; i++) {
191192
if (rest[i] === "--name") {
192193
const next = flagValue(rest, i, rest[i]);
193-
if (next.error) { console.log(err(next.error)); return; }
194+
if (next.error) { console.log(err(next.error)); return 1; }
194195
name = next.value;
195196
i++;
196197
}
197198
else if (!source) source = rest[i];
198199
}
199-
if (!source) { console.log(err("usage: /skill install <git-url|path> [--name <name>]")); return; }
200+
if (!source) { console.log(err("usage: /skill install <git-url|path> [--name <name>]")); return 1; }
200201

201202
const spec = { source, name: skillName(source, name) };
202203
console.log(info(`installing skill ${bone(spec.name)}${ash(source)} across skills engines…`));
203204
const results = await runSkillInstall(planSkillInstall(spec));
204205
summarize(results);
206+
return 0;
205207
}

test/skill-command.test.mjs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,33 @@ for (const extraArgs of [["--name"], ["--name", "--bogus"]]) {
1212
encoding: "utf8",
1313
});
1414

15-
assert.equal(result.status, 0);
15+
assert.equal(result.status, 1);
1616
assert.equal(result.stderr, "");
1717
assert.match(result.stdout, /--name requires a value/);
1818
assert.doesNotMatch(result.stdout, /installing skill/);
1919
});
2020
}
21+
22+
for (const { args, message } of [
23+
{ args: ["skill", "install"], message: /usage: \/skill install/ },
24+
{ args: ["skill", "bogus"], message: /unknown skill verb/ },
25+
{ args: ["mcp", "install"], message: /needs an explicit --name/ },
26+
{ args: ["mcp", "bogus"], message: /unknown mcp verb/ },
27+
]) {
28+
test(`${args.join(" ")} exits non-zero`, () => {
29+
const result = spawnSync(process.execPath, [BIN, ...args], { encoding: "utf8" });
30+
31+
assert.equal(result.status, 1);
32+
assert.equal(result.stderr, "");
33+
assert.match(result.stdout, message);
34+
});
35+
}
36+
37+
for (const args of [["skill", "list"], ["mcp", "list"], ["mcp", "catalog"]]) {
38+
test(`${args.join(" ")} still exits successfully`, () => {
39+
const result = spawnSync(process.execPath, [BIN, ...args], { encoding: "utf8" });
40+
41+
assert.equal(result.status, 0);
42+
assert.equal(result.stderr, "");
43+
});
44+
}

0 commit comments

Comments
 (0)