|
| 1 | +/** |
| 2 | + * Regression for product#3847 — Claude Code install failing with a misleading |
| 3 | + * `unknown option '--scope'` / `--env`. |
| 4 | + * |
| 5 | + * The `claude mcp add` subprocess tail must satisfy TWO constraints at once: |
| 6 | + * |
| 7 | + * 1. No SHORT `-p` flag. Even after the `--` separator, `-p` leaks back into |
| 8 | + * Claude Code's own Commander parser on current CLIs, which then rejects an |
| 9 | + * earlier option (`--scope`/`--env`) with a confusing `unknown option` |
| 10 | + * error — the install aborts at `claude mcp add` time. |
| 11 | + * |
| 12 | + * 2. The package MUST still be flagged (`--package=…`) AND the `leadbay-mcp` |
| 13 | + * bin named explicitly. @leadbay/mcp declares several bins and none is |
| 14 | + * named `mcp`, so a bare `npx -y @leadbay/mcp@latest` (with or without a |
| 15 | + * trailing bin) can't be resolved by npx — it dies at LAUNCH with |
| 16 | + * `could not determine executable to run`, even though `claude mcp add` |
| 17 | + * itself succeeded. |
| 18 | + * |
| 19 | + * The `=`-joined long form `--package=@leadbay/mcp@latest` is the shape that |
| 20 | + * satisfies both. This test pins it and guards against a `-p` regression. |
| 21 | + * |
| 22 | + * New file — no existing test is modified. |
| 23 | + */ |
| 24 | +import { describe, it, expect } from "vitest"; |
| 25 | +import { buildClaudeCodeAddArgs } from "../../installer/install-claude-code.js"; |
| 26 | + |
| 27 | +describe("buildClaudeCodeAddArgs — subprocess tail (product#3847)", () => { |
| 28 | + it("post-`--` tail is exactly `npx -y --package=@leadbay/mcp@latest leadbay-mcp`", () => { |
| 29 | + const args = buildClaudeCodeAddArgs("tok", "us", true, true); |
| 30 | + const sep = args.indexOf("--"); |
| 31 | + expect(args.slice(sep + 1)).toEqual([ |
| 32 | + "npx", |
| 33 | + "-y", |
| 34 | + "--package=@leadbay/mcp@latest", |
| 35 | + "leadbay-mcp", |
| 36 | + ]); |
| 37 | + }); |
| 38 | + |
| 39 | + it("carries no bare `-p` short flag after the separator (would break the parser)", () => { |
| 40 | + const args = buildClaudeCodeAddArgs("tok", "us", true, true); |
| 41 | + const tail = args.slice(args.indexOf("--") + 1); |
| 42 | + expect(tail).not.toContain("-p"); |
| 43 | + }); |
| 44 | + |
| 45 | + it("flags the package AND names the leadbay-mcp bin (so npx can launch it)", () => { |
| 46 | + const args = buildClaudeCodeAddArgs("tok", "us", true, true); |
| 47 | + const tail = args.slice(args.indexOf("--") + 1); |
| 48 | + // Package must be flagged (bare `@leadbay/mcp@latest` as the command is |
| 49 | + // unresolvable) and the explicit bin present (no bin is named `mcp`). |
| 50 | + expect(tail.some((a) => a.startsWith("--package=@leadbay/mcp@"))).toBe(true); |
| 51 | + expect(tail).toContain("leadbay-mcp"); |
| 52 | + }); |
| 53 | + |
| 54 | + it("localBinPath dev override still uses `-- node <path>` (no npx, no -p)", () => { |
| 55 | + const args = buildClaudeCodeAddArgs("tok", "us", true, true, "/abs/dist/bin.js"); |
| 56 | + const sep = args.indexOf("--"); |
| 57 | + expect(args.slice(sep + 1)).toEqual(["node", "/abs/dist/bin.js"]); |
| 58 | + }); |
| 59 | +}); |
0 commit comments