360 Secure SkillHub
360 安全技能中心

Build beautiful interactive Node.js command-line apps with @clack/prompts.

这是轻量预样式化的Node.js交互式CLI工具库,体积比同类小80%。核心功能涵盖文本输入、密码、选择/多选、spinner、进度条等组件,支持分组提示、任务流、样式日志及自定义校验,适用于CLI应用、向导、安装脚本等场景,通过JS调用API生成交互界面,返回用户输入结果。

openlark
openlark
热度 29.56
最近更新 2026-05-11 17:47:34
分类:开发依赖:纯提示词应用场景:代码生成 / 自动化脚本

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add clack-prompts
Metadata
name
clack-prompts
description
Build 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.

@clack/prompts

Build beautiful, minimal interactive CLI apps. Pre-styled, tree-shakeable, 80% smaller than alternatives.

Quick Start

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}.`);

Core Pattern — Always Guard Cancellation

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);
}

Choosing the Right Component

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

Common Patterns

Sequential Prompts with group()

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);
    },
  },
);

Task Runner with Spinners

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
    },
  },
]);

Standalone Spinner

import { spinner } from '@clack/prompts';

const s = spinner();
s.start('Uploading...');
try { await upload(); s.stop('Uploaded!'); }
catch { s.stop('Upload failed'); }

Progress Bar

const p = progress({ max: 100 });
p.start('Downloading');
for (const chunk of chunks) { p.advance(1); }
p.stop('Done');

Live Sub-Process Output with taskLog

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

Styled Logging (no user input)

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('~') });

Streaming Logs

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('~') }
);

Selection Options Shape

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

Validation

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.';
  },
});

Full API Reference

See references/api.md for every component's complete signature, options table, and examples.