Print CLI errors as one line instead of a stack trace (closes #102)
check / check (push) Successful in 54s

An error a command throws now reaches the user as one `quak: MESSAGE`
line on stderr, and the CLI exits 1 once output has drained. The wrapper
moved from bin/quak.ts to src/cli-run.ts so it can be tested, and
bin/quak.ts awaits program.parseAsync() so async actions are awaited.

Model: opus-5-5
This commit is contained in:
2026-09-23 05:05:38 +00:00
parent cda57eebda
commit cc5b90104f
5 changed files with 107 additions and 20 deletions
+4 -18
View File
@@ -18,6 +18,7 @@ import {
listMissingThumbnailsCommand,
fixMissingThumbnailsCommand,
} from "../src/cli-commands.js";
import { run as runCommand } from "../src/cli-run.js";
import { loadSession } from "../src/cli-session.js";
import { VERSION } from "../src/index.js";
@@ -43,23 +44,8 @@ const context = (): CliContext => ({
loadSession,
});
// Run a command and exit with its code once stdout/stderr have drained.
// Exiting before the drain can truncate piped output, and the library can keep
// the event loop alive after a command returns, so a plain return could hang.
const run = async (command: Promise<number>): Promise<void> => {
process.exitCode = await command;
const pending = [stdout, stderr].filter((s) => s.writableLength > 0);
if (pending.length === 0) {
process.exit();
return;
}
let remaining = pending.length;
for (const s of pending) {
s.once("drain", () => {
if (--remaining === 0) process.exit();
});
}
};
const run = (command: Promise<number>): Promise<void> =>
runCommand(command, stdout, stderr, (code) => process.exit(code));
program
.command("login")
@@ -169,4 +155,4 @@ helper
);
await init();
program.parse();
await program.parseAsync();