en un clic
clack-cli-patterns
// 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.
// 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.
Use when implementing drag-to-reorder / sortable lists or chips in OpenChamber with @dnd-kit — covers the correct setup for BOTH desktop and mobile (touch), the variable-width "stretch" fix, the wrapping multi-row strategy choice, and the pitfalls (infinite update loop, offset overlay) we already hit and fixed.
Use when creating or modifying UI components, styling, visual elements, or icons in OpenChamber. All UI colors must use theme tokens - never hardcoded values or Tailwind color classes. All icons must use the shared Icon component from the SVG sprite system - never import from @remixicon/react directly.
Use when creating or modifying OpenChamber UI text, labels, buttons, placeholders, aria labels, empty states, toasts, dialogs, settings copy, navigation labels, or any user-facing strings.
Use when creating or modifying UI components, styling, or visual elements related to Settings in OpenChamber.
| name | clack-cli-patterns |
| description | 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. |
| license | MIT |
| compatibility | opencode |
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