Menu-driven selection components for choosing from predefined options with keyboard navigation, hints, and grouping support.
Choose one option from a list with keyboard navigation and optional hints.
/**
* Creates a selection prompt for choosing one option from a list
* @param opts - Configuration options for the selection prompt
* @returns Promise resolving to selected value or cancellation symbol
*/
function select<Value>(opts: SelectOptions<Value>): Promise<Value | symbol>;
interface SelectOptions<Value> {
/** The prompt message displayed to the user */
message: string;
/** Array of options to choose from */
options: Option<Value>[];
/** Initial selected value */
initialValue?: Value;
/** Maximum number of items to display at once (defaults to terminal height) */
maxItems?: number;
}
type Option<Value> = Value extends Primitive
? {
/** Internal data for this option */
value: Value;
/** The optional, user-facing text for this option (defaults to string conversion of value) */
label?: string;
/** Optional hint displayed when this option might be selected */
hint?: string;
}
: {
/** Internal data for this option */
value: Value;
/** Required user-facing text for this option */
label: string;
/** Optional hint displayed when this option might be selected */
hint?: string;
};
type Primitive = Readonly<string | boolean | number>;Usage Examples:
import { select, isCancel, cancel } from "@clack/prompts";
// Basic selection with string values
const framework = await select({
message: "Pick a framework:",
options: [
{ value: "react", label: "React" },
{ value: "vue", label: "Vue" },
{ value: "svelte", label: "Svelte" },
],
});
if (isCancel(framework)) {
cancel("Operation cancelled");
process.exit(0);
}
// Selection with hints and initial value
const deployment = await select({
message: "Choose deployment target:",
initialValue: "vercel",
options: [
{ value: "vercel", label: "Vercel", hint: "recommended" },
{ value: "netlify", label: "Netlify" },
{ value: "aws", label: "AWS", hint: "advanced" },
{ value: "self", label: "Self-hosted", hint: "requires setup" },
],
});
// Selection with complex values
const config = await select({
message: "Choose configuration:",
options: [
{
value: { env: "development", debug: true },
label: "Development",
hint: "with debug enabled"
},
{
value: { env: "production", debug: false },
label: "Production",
hint: "optimized build"
},
],
});Select options using keyboard shortcuts for faster interaction.
/**
* Creates a keyboard-driven selection prompt using key shortcuts
* @param opts - Configuration options for the key selection prompt
* @returns Promise resolving to selected value or cancellation symbol
*/
function selectKey<Value extends string>(opts: SelectOptions<Value>): Promise<Value | symbol>;Usage Examples:
import { selectKey, isCancel, cancel } from "@clack/prompts";
// Quick selection using keyboard shortcuts
const action = await selectKey({
message: "What would you like to do?",
options: [
{ value: "c", label: "Create new project" },
{ value: "i", label: "Install dependencies" },
{ value: "b", label: "Build project" },
{ value: "t", label: "Run tests" },
],
});
if (isCancel(action)) {
cancel("Operation cancelled");
process.exit(0);
}
// User can press 'c', 'i', 'b', or 't' to select
console.log(`Selected action: ${action}`);Choose multiple options from a list with checkbox-style interface.
/**
* Creates a multi-selection prompt for choosing multiple options
* @param opts - Configuration options for the multi-selection prompt
* @returns Promise resolving to array of selected values or cancellation symbol
*/
function multiselect<Value>(opts: MultiSelectOptions<Value>): Promise<Value[] | symbol>;
interface MultiSelectOptions<Value> {
/** The prompt message displayed to the user */
message: string;
/** Array of options to choose from */
options: Option<Value>[];
/** Array of initially selected values */
initialValues?: Value[];
/** Maximum number of items to display at once */
maxItems?: number;
/** Whether at least one selection is required (defaults to true) */
required?: boolean;
/** Value to position cursor at initially */
cursorAt?: Value;
}Usage Examples:
import { multiselect, isCancel, cancel } from "@clack/prompts";
// Basic multi-selection
const tools = await multiselect({
message: "Select development tools:",
options: [
{ value: "eslint", label: "ESLint", hint: "code linting" },
{ value: "prettier", label: "Prettier", hint: "code formatting" },
{ value: "jest", label: "Jest", hint: "testing framework" },
{ value: "typescript", label: "TypeScript", hint: "type checking" },
],
});
if (isCancel(tools)) {
cancel("Operation cancelled");
process.exit(0);
}
console.log(`Selected tools: ${tools.join(", ")}`);
// Multi-selection with initial values and optional selection
const features = await multiselect({
message: "Choose optional features:",
required: false,
initialValues: ["auth"],
options: [
{ value: "auth", label: "Authentication" },
{ value: "db", label: "Database integration" },
{ value: "api", label: "REST API" },
{ value: "docs", label: "Documentation" },
],
});Choose multiple options from categorized groups with optional group selection.
/**
* Creates a grouped multi-selection prompt with categorized options
* @param opts - Configuration options for the grouped multi-selection prompt
* @returns Promise resolving to array of selected values or cancellation symbol
*/
function groupMultiselect<Value>(opts: GroupMultiSelectOptions<Value>): Promise<Value[] | symbol>;
interface GroupMultiSelectOptions<Value> {
/** The prompt message displayed to the user */
message: string;
/** Object with group names as keys and option arrays as values */
options: Record<string, Option<Value>[]>;
/** Array of initially selected values */
initialValues?: Value[];
/** Whether at least one selection is required (defaults to true) */
required?: boolean;
/** Value to position cursor at initially */
cursorAt?: Value;
/** Whether group headers can be selected to toggle all items in group (defaults to true) */
selectableGroups?: boolean;
}Usage Examples:
import { groupMultiselect, isCancel, cancel } from "@clack/prompts";
// Grouped selection with categories
const packages = await groupMultiselect({
message: "Select packages to install:",
options: {
"Frontend": [
{ value: "react", label: "React" },
{ value: "vue", label: "Vue" },
{ value: "svelte", label: "Svelte" },
],
"Build Tools": [
{ value: "webpack", label: "Webpack" },
{ value: "vite", label: "Vite", hint: "recommended" },
{ value: "rollup", label: "Rollup" },
],
"Testing": [
{ value: "jest", label: "Jest" },
{ value: "vitest", label: "Vitest" },
{ value: "cypress", label: "Cypress" },
],
},
});
if (isCancel(packages)) {
cancel("Operation cancelled");
process.exit(0);
}
// Group selection without selectable groups
const permissions = await groupMultiselect({
message: "Grant permissions:",
selectableGroups: false,
options: {
"Read Access": [
{ value: "read-files", label: "Read files" },
{ value: "read-config", label: "Read configuration" },
],
"Write Access": [
{ value: "write-files", label: "Write files" },
{ value: "write-config", label: "Modify configuration" },
],
},
});All selection prompts support consistent keyboard navigation:
For selectKey, users can press the key corresponding to the option's value for instant selection.
When there are more options than can fit on screen, the prompts automatically handle scrolling:
maxItems to control how many options are visible at onceOptions can contain different value types:
// Primitive values (string, number, boolean) have optional labels
const stringOptions: Option<string>[] = [
{ value: "react", label: "React Framework" },
{ value: "vue" }, // label defaults to "vue"
];
// Complex values require explicit labels
interface ProjectConfig {
framework: string;
typescript: boolean;
}
const objectOptions: Option<ProjectConfig>[] = [
{
value: { framework: "react", typescript: true },
label: "React with TypeScript",
hint: "recommended setup"
},
];