Install
openclaw skills install clack-promptsBuild beautiful interactive Node.js command-line apps with @clack/prompts. Use when building CLI apps, wizards, setup scripts, or any interactive terminal prompt flow in Node.js. Covers text input, password, confirm, select, autocomplete, multiselect, spinner, progress bars, grouped prompts, task runners, and styled logging.
openclaw skills install clack-promptsBuild beautiful, minimal interactive CLI apps. Pre-styled, tree-shakeable, 80% smaller than alternatives.
npm install @clack/prompts
import { intro, outro, text, isCancel, cancel } from '@clack/prompts';
intro('create-my-app');
const name = await text({ message: 'Project name?' });
if (isCancel(name)) { cancel('Cancelled.'); process.exit(0); }
outro(`Done! Created ${name}.`);
Every prompt can return a cancel symbol (user pressed Ctrl+C). Always use isCancel():
const result = await text({ message: 'Name?' });
if (isCancel(result)) {
cancel('Cancelled.');
process.exit(0);
}
| Need | Component | Returns |
|---|---|---|
| Single-line text | text | string |
| Masked secret | password | string |
| Yes / No | confirm | boolean |
| Pick one from list | select | string (value) |
| Searchable pick one | autocomplete | string (value) |
| Single-key selection | selectKey | string (value) |
| Pick many from list | multiselect | string[] |
| Pick many, grouped | groupMultiselect | string[] |
| Multi-line text area | multiline | string |
| Filesystem path | path | string |
| Calendar date | date | Date |
Chain prompts where later ones depend on earlier answers:
import * as p from '@clack/prompts';
const result = await p.group(
{
name: () => p.text({ message: 'What is your name?' }),
age: () => p.text({ message: 'What is your age?' }),
color: ({ results }) =>
p.multiselect({
message: `What is your favorite color ${results.name}?`,
options: [
{ value: 'red', label: 'Red' },
{ value: 'blue', label: 'Blue' },
],
}),
},
{
onCancel: ({ results }) => {
p.cancel('Operation cancelled.');
process.exit(0);
},
},
);
Run sequential tasks, each with its own spinner:
import { tasks } from '@clack/prompts';
await tasks([
{
title: 'Installing via npm',
task: async () => {
// Return a string = success with checkmark
return 'Installed via npm';
},
},
{
title: 'Running tests',
task: async () => {
throw new Error('Tests failed!'); // Error = red X
},
},
]);
import { spinner } from '@clack/prompts';
const s = spinner();
s.start('Uploading...');
try { await upload(); s.stop('Uploaded!'); }
catch { s.stop('Upload failed'); }
const p = progress({ max: 100 });
p.start('Downloading');
for (const chunk of chunks) { p.advance(1); }
p.stop('Done');
import { taskLog } from '@clack/prompts';
const log = taskLog({ title: 'npm install' });
for await (const line of npmInstall()) { log.message(line); }
log.success('Done!'); // Clears output on success
// log.error('Failed!'); // Keeps output visible on failure
import { log } from '@clack/prompts';
import color from 'picocolors';
log.info('Starting setup...');
log.success('Config written!');
log.step('Checking dependencies...');
log.warn('Optional peer dep missing');
log.error('Build failed');
log.message('Custom', { symbol: color.cyan('~') });
For LLM output or dynamic streams:
import { stream } from '@clack/prompts';
stream.info((function* () { yield 'Info!'; })());
stream.success((async function* () { yield 'Done!'; })());
stream.message(
(function* () { yield 'Hello'; yield ', World'; })(),
{ symbol: color.cyan('~') }
);
Used by select, autocomplete, selectKey, multiselect, groupMultiselect:
{ value: 'ts', label: 'TypeScript' } // Basic
{ value: 'js', label: 'JavaScript', disabled: true } // Disabled
{ value: 'coffee', label: 'CoffeeScript', hint: 'oh no' } // With hint
Most components accept a validate(value) that returns string (error message) or undefined (valid):
const name = await text({
message: 'Username?',
validate(value) {
if (!value.length) return 'Username is required!';
if (value.length < 3) return 'At least 3 characters.';
},
});
See references/api.md for every component's complete signature, options table, and examples.