typescript-cli-noninteractive-flag-alias
Premise-check first (before dispatching any worker work): grep the existing flag handling —
src/cli.ts:10: .option("--auto", "skip the confirmation prompt (non-interactive)")
src/run-game.ts:23: if (!auto) {
A non-interactive gate already exists: --auto skips the inquirer confirm via if (!auto). The task's "add a non-interactive flag" gap was only the flag name (--yes). So the fix is a 2-line alias, not a full worker dispatch.
Fix 1 — src/cli.ts: 1-line alias option (commander):
program
.name("run-game")
.description("Launch the game")
.option("--auto", "skip the confirmation prompt (non-interactive)")
.option("--yes", "alias for --auto: skip the confirmation prompt") // ← 1-line alias
.action(async (opts: { auto?: boolean; yes?: boolean }) => {
const result = await runGame({ auto: opts.auto, yes: opts.yes });
console.log(result);
});
Fix 2 — src/run-game.ts: extend the gate:
// Gate: only prompt interactively when no non-interactive flag is present.
if (!auto && !yes) { // was: if (!auto)
const ok = await prompt("Start the game?");
if (!ok) return "aborted";
}
Test — test/run-game.test.ts (the new --yes test plus regressions):
it("--yes (alias) skips the inquirer confirm prompt", async () => {
const prompt = vi.fn(async () => {
throw new Error("prompt must not be called in non-interactive mode");
});
const result = await runGame({ yes: true, prompt });
expect(result).toBe("started");
expect(prompt).not.toHaveBeenCalled();
});
All verified in a real, installed project at `~/run-game` (TypeScript 5, inquirer 10, commander 12, vitest 3): 1. **`npx tsc --noEmit`** → `TYPECHECK OK` 2. **`npx vitest run`** → `Test Files 1 passed (1)`, `Tests 3 passed (3)` 3. **E2E with `/dev/null` stdin** (the previously-blocking case): - `node dist/cli.js --yes < /dev/null` → prints `started`, `exit=0`, **36ms** (pre-fix this would block on the inquirer prompt) - `node dist/cli.js --auto < /dev/null` → `started` (regression intact) - `node dist/cli.js --help` → shows both `--auto` and `--yes` options - `node dist/cli.js < /dev/null` (no flag) → still renders `? Start the game? (Y/n)` and blocks on the confirm — gate semantics preserved; the flags exist solely to bypass it **Edge cases covered:** `--yes` alone, `--auto` alone (regression), and neither flag (interactive path still prompts and honors a "no" → `aborted`). The injected-prompt design means the test is hermetic — inquirer is only ever dynamically imported when the interactive branch actually runs. **Project layout:** `src/cli.ts` (arg parsing), `src/run-game.ts` (gate + confirm), `test/run-game.test.ts`.
{"model": "deepseek-v4-flash", "problem_class": "typescript-cli-noninteractive-flag-alias", "result": "passed", "tests": 3}