Use when creating or modifying terminal CLI commands, prompts, or output formatting in OpenChamber. Enforces Clack UX standards with strict parity and safety across TTY/non-TTY, --quiet, and --json modes.
OpenChamber terminal CLI uses @clack/prompts for interactive UX, but command policy and validation must be mode-agnostic.
Core principle: policy-first, UX-second. Clack is presentation, not enforcement.
Use this skill for terminal CLI work only (for example packages/web/bin/*).
Do not use this skill for web UI or VS Code webview styling work.
Validation first
Mode parity is required
--quiet--jsonPrompt guard contract
--quiet--jsonOutput contract
--json: machine-readable output only.--quiet: suppress non-essential output only.Cancellation contract
isCancel + cancel(...).intro, outro, cancellog.info, log.success, log.warn, log.error, log.stepnoteboxselect, confirm, text, passwordspinnerprogresstasksCentralize Clack imports and formatting helpers in one adapter module (for example cli-output.js) so command logic stays focused on behavior and policy.
Use a small shared helper surface rather than command-specific formatting logic.
isJsonMode(options)isQuietMode(options)shouldRenderHumanOutput(options)canPrompt(options)createSpinner(options)createProgress(options, config)printJson(payload)Keep this layer minimal. Do not hide core validation or command semantics inside output helpers.
--quiet contract--quiet should still return essential result data.
Quiet output should still be complete enough for scripts and quick human scanning.
running/ok.port 3000 pass:yes).--json contract (strict)status, messages).intro, close with outro (or outro('') when you want structure without text).spinner.clear() when a trailing spinner line is not wanted).spinner.clear() to avoid duplicate success lines.initialValue (not only placeholder) so users can accept or edit quickly.[CODE]) when the message has follow-up docs or repeat use.Optional Tips for non-required next actions.logStatus('info', '[CODE]', '<actionable command or short guidance>')[START_PROFILE], [PORT_MISMATCH]) so users can quickly scan and recognize repeated guidance.note/boxed callouts for rare, high-context guidance where a long paragraph is truly necessary.For each command/subcommand, manually verify:
--quiet output (minimal but informative)--json output (JSON-only)if (canPrompt(options)) {
const value = await select({
message: 'Choose an option',
options: [{ value: 'a', label: 'Option A' }],
});
if (isCancel(value)) {
cancel('Operation cancelled.');
return;
}
}
if (!resolvedValue) {
if (canPrompt(options)) {
// prompt path
} else {
throw new Error('Missing required value. Provide --flag <value>.');
}
}
const spin = createSpinner(options);
spin?.start('Running operation...');
// ...work...
spin?.stop('Done');
if (options.json) {
printJson({ ok: true, data });
return;
}
intro('Operation');
log.success('Completed');
outro('done');
AGENTS.md (CLI Parity and Safety Policy)packages/web/bin/cli.jspackages/web/bin/cli-output.js