Prompts
The @clack/prompts
package provides a collection of pre-built, high-level prompts that make it easy to create interactive command-line interfaces. It builds on top of the core package to provide a more developer-friendly experience.
Key Features
Section titled “Key Features”- Pre-built prompts: Ready-to-use prompt components
- Consistent styling: Unified look and feel across all prompts
- Type-safe: Full TypeScript support
- Customizable: Easy to extend and modify
Installation
Section titled “Installation”npm install @clack/prompts
pnpm add @clack/prompts
yarn add @clack/prompts
The prompts package is designed to be intuitive and easy to use. Each prompt function returns a Promise that resolves to the user’s input.
For more detailed examples and advanced usage patterns, check out our examples guide and best practices.
Available Prompts
Section titled “Available Prompts”Text Input
Section titled “Text Input”import { const text: (opts: TextOptions) => Promise<string | symbol>
text } from '@clack/prompts';
const const name: string | symbol
name = await function text(opts: TextOptions): Promise<string | symbol>
text({ TextOptions.message: string
message: 'What is your name?', TextOptions.placeholder?: string
placeholder: 'John Doe', TextOptions.validate?: (value: string) => string | Error | undefined
validate: (value: string
value) => { if (value: string
value.String.length: number
Returns the length of a String object.
length < 2) return 'Name must be at least 2 characters'; return var undefined
undefined; },});
│
◆ What is your name?
│ John Doe
└
Password Input
Section titled “Password Input”import { const password: (opts: PasswordOptions) => Promise<string | symbol>
password } from '@clack/prompts';
const const secret: string | symbol
secret = await function password(opts: PasswordOptions): Promise<string | symbol>
password({ PasswordOptions.message: string
message: 'What is your password?', PasswordOptions.mask?: string
mask: '*', PasswordOptions.validate?: (value: string) => string | Error | undefined
validate: (value: string
value) => { if (value: string
value.String.length: number
Returns the length of a String object.
length < 8) return 'Your password must be at least 8 characters'; if (!/[A-Z]/.RegExp.test(string: string): boolean
Returns a Boolean value that indicates whether or not a pattern exists in a searched string.
test(value: string
value)) return 'Your password must be least contain 1 uppercase letter'; if (!/[0-9]/.RegExp.test(string: string): boolean
Returns a Boolean value that indicates whether or not a pattern exists in a searched string.
test(value: string
value)) return 'Your password must be least contain 1 number'; if (!/[*?!@&]/.RegExp.test(string: string): boolean
Returns a Boolean value that indicates whether or not a pattern exists in a searched string.
test(value: string
value)) return 'Your password must be least contain 1 special characters (*?!@&)'; return var undefined
undefined; },});
│
◆ What is your password?
│ *****_
└
Selection
Section titled “Selection”Simple value
Section titled “Simple value”import { const select: <Value>(opts: SelectOptions<Value>) => Promise<Value | symbol>
select } from '@clack/prompts';
const const framework: symbol | "next" | "astro" | "svelte"
framework = await select<"next" | "astro" | "svelte">(opts: SelectOptions<"next" | "astro" | "svelte">): Promise<symbol | "next" | "astro" | "svelte">
select({ SelectOptions<Value>.message: string
message: 'Pick a framework', SelectOptions<"next" | "astro" | "svelte">.options: ({ value: "next"; label?: string; hint?: string;} | { value: "astro"; label?: string; hint?: string;} | { value: "svelte"; label?: string; hint?: string;})[]
options: [ { value: "next"
Internal data for this option.
value: 'next', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'Next.js', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'React framework' }, { value: "astro"
Internal data for this option.
value: 'astro', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'Astro', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Content-focused' }, { value: "svelte"
Internal data for this option.
value: 'svelte', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'SvelteKit', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Compile-time framework' }, ], SelectOptions<Value>.maxItems?: number
maxItems: 5, // Maximum number of items to display at once});
│ ◆ Pick a framework │ ● Next.js (React framework) │ ○ Astro (Content-focused) │ ○ SvelteKit (Compile-time framework) └
Complex value
Section titled “Complex value”import { const select: <Value>(opts: SelectOptions<Value>) => Promise<Value | symbol>
select } from '@clack/prompts';
const const framework: symbol | { framework: string; language: string;} | { framework: null; language: string;}
framework = await select<{ framework: string; language: string;} | { framework: null; language: string;}>(opts: SelectOptions<{ framework: string; language: string;} | { framework: null; language: string;}>): Promise<...>
select({ SelectOptions<Value>.message: string
message: 'Pick a framework', SelectOptions<{ framework: string; language: string; } | { framework: null; language: string; }>.options: ({ value: { framework: string; language: string; }; label: string; hint?: string;} | { value: { framework: null; language: string; }; label: string; hint?: string;})[]
options: [ { value: { framework: string; language: string;}
value: { framework: string
framework: 'Next', language: string
language: 'React' }, label: string
Required. The user-facing text for this option.
label: 'Next.js', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'React framework' }, { value: { framework: null; language: string;}
value: { framework: null
framework: null, language: string
language: 'Astro' }, label: string
Required. The user-facing text for this option.
label: 'Astro', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Content-focused' }, { value: { framework: string; language: string;}
value: { framework: string
framework: 'Sveltekit', language: string
language: 'Svelte' }, label: string
Required. The user-facing text for this option.
label: 'SvelteKit', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Compile-time framework' }, ],});
│ │ Pick a framework │ ● Next.js (React framework) │ ○ Astro (Content-focused) │ ○ SvelteKit (Compile-time framework) └
Multiple values
Section titled “Multiple values”import { const multiselect: <Value>(opts: MultiSelectOptions<Value>) => Promise<Value[] | symbol>
multiselect } from '@clack/prompts';
const const framework: symbol | ({ framework: string; language: string;} | { framework: null; language: string;})[]
framework = await multiselect<{ framework: string; language: string;} | { framework: null; language: string;}>(opts: MultiSelectOptions<{ framework: string; language: string;} | { framework: null; language: string;}>): Promise<...>
multiselect({ MultiSelectOptions<Value>.message: string
message: 'Pick a framework', MultiSelectOptions<{ framework: string; language: string; } | { framework: null; language: string; }>.options: ({ value: { framework: string; language: string; }; label: string; hint?: string;} | { value: { framework: null; language: string; }; label: string; hint?: string;})[]
options: [ { value: { framework: string; language: string;}
value: { framework: string
framework: 'Next', language: string
language: 'React' }, label: string
Required. The user-facing text for this option.
label: 'Next.js', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'React framework' }, { value: { framework: null; language: string;}
value: { framework: null
framework: null, language: string
language: 'Astro' }, label: string
Required. The user-facing text for this option.
label: 'Astro', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Content-focused' }, { value: { framework: string; language: string;}
value: { framework: string
framework: 'Sveltekit', language: string
language: 'Svelte' }, label: string
Required. The user-facing text for this option.
label: 'SvelteKit', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Compile-time framework' }, ], MultiSelectOptions<Value>.maxItems?: number
maxItems: 5, // Maximum number of items to display at once});
│ ◆ Pick a framework │ ◼ Next.js (React framework) │ ◻ Astro (Content-focused) │ ◻ SvelteKit (Compile-time framework) └
Autocomplete
Section titled “Autocomplete”The autocomplete
prompt combines text input with a searchable list of options. It’s perfect for when you have a large list of options and want to help users find what they’re looking for quickly.
import { const autocomplete: <Value>(opts: AutocompleteOptions<Value>) => Promise<Value | symbol>
autocomplete } from '@clack/prompts';
const const framework: symbol | "next" | "astro" | "svelte" | "remix" | "nuxt"
framework = await autocomplete<"next" | "astro" | "svelte" | "remix" | "nuxt">(opts: AutocompleteOptions<"next" | "astro" | "svelte" | "remix" | "nuxt">): Promise<symbol | "next" | "astro" | "svelte" | "remix" | "nuxt">
autocomplete({ AutocompleteOptions<Value>.message: string
The message to display to the user.
message: 'Search for a framework', AutocompleteOptions<"next" | "astro" | "svelte" | "remix" | "nuxt">.options: ({ value: "next"; label?: string; hint?: string;} | { value: "astro"; label?: string; hint?: string;} | { value: "svelte"; label?: string; hint?: string;} | { value: "remix"; label?: string; hint?: string;} | { ...;})[]
Available options for the autocomplete prompt.
options: [ { value: "next"
Internal data for this option.
value: 'next', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'Next.js', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'React framework' }, { value: "astro"
Internal data for this option.
value: 'astro', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'Astro', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Content-focused' }, { value: "svelte"
Internal data for this option.
value: 'svelte', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'SvelteKit', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Compile-time framework' }, { value: "remix"
Internal data for this option.
value: 'remix', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'Remix', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Full stack framework' }, { value: "nuxt"
Internal data for this option.
value: 'nuxt', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'Nuxt', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Vue framework' }, ], AutocompleteOptions<Value>.placeholder?: string
Placeholder text to display when no input is provided.
placeholder: 'Type to search...', AutocompleteOptions<Value>.maxItems?: number
Maximum number of items to display at once.
maxItems: 5, // Maximum number of items to display at once});
│
◆ Search for a framework
│ Search: n
│ (2 matches)
│ ● Next.js (React framework)
│ ○ Nuxt (Vue framework)
└
Autocomplete Multiselect
Section titled “Autocomplete Multiselect”The autocompleteMultiselect
combines the search functionality of autocomplete with the ability to select multiple options.
import { const autocompleteMultiselect: <Value>(opts: AutocompleteMultiSelectOptions<Value>) => Promise<Value | symbol>
Integrated autocomplete multiselect - combines type-ahead filtering with multiselect in one UI
autocompleteMultiselect } from '@clack/prompts';
const const frameworks: symbol | "next" | "astro" | "svelte" | "remix" | "nuxt"
frameworks = await autocompleteMultiselect<"next" | "astro" | "svelte" | "remix" | "nuxt">(opts: AutocompleteMultiSelectOptions<"next" | "astro" | "svelte" | "remix" | "nuxt">): Promise<...>
Integrated autocomplete multiselect - combines type-ahead filtering with multiselect in one UI
autocompleteMultiselect({ AutocompleteMultiSelectOptions<Value>.message: string
The message to display to the user
message: 'Select frameworks', AutocompleteMultiSelectOptions<"next" | "astro" | "svelte" | "remix" | "nuxt">.options: ({ value: "next"; label?: string; hint?: string;} | { value: "astro"; label?: string; hint?: string;} | { value: "svelte"; label?: string; hint?: string;} | { value: "remix"; label?: string; hint?: string;} | { ...;})[]
The options for the user to choose from
options: [ { value: "next"
Internal data for this option.
value: 'next', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'Next.js', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'React framework' }, { value: "astro"
Internal data for this option.
value: 'astro', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'Astro', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Content-focused' }, { value: "svelte"
Internal data for this option.
value: 'svelte', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'SvelteKit', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Compile-time framework' }, { value: "remix"
Internal data for this option.
value: 'remix', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'Remix', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Full stack framework' }, { value: "nuxt"
Internal data for this option.
value: 'nuxt', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'Nuxt', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Vue framework' }, ], AutocompleteMultiSelectOptions<Value>.placeholder?: string
The placeholder to display in the input
placeholder: 'Type to search...', AutocompleteMultiSelectOptions<Value>.maxItems?: number
The maximum number of items that can be selected
maxItems: 5, // Maximum number of items to display at once});
│
◆ Select frameworks
│ Search: n
│ (2 matches)
│ ◼ Next.js (React framework)
│ ◻ Nuxt (Vue framework)
└
Confirmation
Section titled “Confirmation”import { const confirm: (opts: ConfirmOptions) => Promise<boolean | symbol>
confirm } from '@clack/prompts';
const const shouldProceed: boolean | symbol
shouldProceed = await function confirm(opts: ConfirmOptions): Promise<boolean | symbol>
confirm({ ConfirmOptions.message: string
message: 'Do you want to continue?',});
│ ◆ Do you want to continue? │ ● Yes / ○ No └
Grouping
Section titled “Grouping”Group Multiselect
Section titled “Group Multiselect”import { const groupMultiselect: <Value>(opts: GroupMultiSelectOptions<Value>) => Promise<Value[] | symbol>
groupMultiselect } from '@clack/prompts';
const const projectOptions: symbol | ("Jest" | "Playwright" | "Vitest" | "js" | "ts" | "coffee" | "Prettier" | "ESLint" | "Biome.js")[]
projectOptions = await groupMultiselect<"Jest" | "Playwright" | "Vitest" | "js" | "ts" | "coffee" | "Prettier" | "ESLint" | "Biome.js">(opts: GroupMultiSelectOptions<"Jest" | "Playwright" | "Vitest" | "js" | "ts" | "coffee" | "Prettier" | "ESLint" | "Biome.js">): Promise<...>
groupMultiselect({ GroupMultiSelectOptions<Value>.message: string
message: 'Define your project', GroupMultiSelectOptions<"Jest" | "Playwright" | "Vitest" | "js" | "ts" | "coffee" | "Prettier" | "ESLint" | "Biome.js">.options: Record<string, ({ value: "Jest"; label?: string; hint?: string;} | { value: "Playwright"; label?: string; hint?: string;} | { value: "Vitest"; label?: string; hint?: string;} | { value: "js"; label?: string; hint?: string;} | ... 4 more ... | { ...;})[]>
options: { 'Testing': [ { value: "Jest"
Internal data for this option.
value: 'Jest', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'JavaScript testing framework' }, { value: "Playwright"
Internal data for this option.
value: 'Playwright', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'End-to-end testing' }, { value: "Vitest"
Internal data for this option.
value: 'Vitest', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Vite-native testing' }, ], 'Language': [{ label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: "Javascript", value: "js"
Internal data for this option.
value: 'js', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Dynamic typing' }, { label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'TypeScript', value: "ts"
Internal data for this option.
value: 'ts', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Static typing' }, { label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: "CoffeeScript", value: "coffee"
Internal data for this option.
value: 'coffee', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'JavaScript with Ruby-like syntax' }], 'Code quality': [ { value: "Prettier"
Internal data for this option.
value: 'Prettier', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Code formatter' }, { value: "ESLint"
Internal data for this option.
value: 'ESLint', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Linter' }, { value: "Biome.js"
Internal data for this option.
value: 'Biome.js', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Formatter and linter' }, ], }, GroupMultiSelectOptions<Value>.groupSpacing?: number
groupSpacing: 1, // Add one new line between each group GroupMultiSelectOptions<Value>.selectableGroups?: boolean
selectableGroups: false, // Disable selection of top-level groups});
│ ◆ Define your project │ ◼ Testing │ │ ◼ Jest (JavaScript testing framework) │ │ ◼ Playwright (End-to-end testing) │ └ ◼ Vitest (Vite-native testing) │ │ ◻ Language │ │ ◼ Javascript (Dynamic typing) │ │ ◻ TypeScript (Static typing) │ └ ◻ CoffeeScript (JavaScript with Ruby-like syntax) │ │ ◻ Code quality │ │ ◻ Prettier (Code formatter) │ │ ◻ ESLint (Linter) │ └ ◼ Biome.js (Formatter and linter) └
The groupMultiselect
prompt supports two additional options:
groupSpacing
: An integer that specifies how many new lines to add between each group. This helps improve readability when you have many groups.selectableGroups
: A boolean that determines whether top-level groups can be selected. When set tofalse
, only individual items within groups can be selected.
The group
function provides a convenient API for combining a series of questions.
Each question receives the results
of previous answers.
The group
function returns an object containing the result of every question.
import { const group: <T>(prompts: PromptGroup<T>, opts?: PromptGroupOptions<T>) => Promise<{ [P in keyof PromptGroupAwaitedReturn<...>]: PromptGroupAwaitedReturn<...>[P]; }>
Define a group of prompts to be displayed
and return a results of objects within the group
group, const text: (opts: TextOptions) => Promise<string | symbol>
text, const password: (opts: PasswordOptions) => Promise<string | symbol>
password } from '@clack/prompts';
const const account: { email: string; username: unknown; password: string;}
account = await group<{ email: string | symbol; username: unknown; password: string | symbol;}>(prompts: PromptGroup<{ email: string | symbol; username: unknown; password: string | symbol;}>, opts?: PromptGroupOptions<{ email: string | symbol; username: unknown; password: string | symbol;}> | undefined): Promise<...>
Define a group of prompts to be displayed
and return a results of objects within the group
group({ email: (opts: { results: { username?: unknown; password?: string; };}) => Promise<string | symbol | undefined> | undefined
email: () => function text(opts: TextOptions): Promise<string | symbol>
text({ TextOptions.message: string
message: 'What is your email address?', TextOptions.validate?: (value: string) => string | Error | undefined
validate: (value: string
value) => { if (!/^[a-z0-9_.-]+@[a-z0-9_.-]+\.[a-z]{2,}$/i.RegExp.test(string: string): boolean
Returns a Boolean value that indicates whether or not a pattern exists in a searched string.
test(value: string
value)) return 'Please enter a valid email' } }), username: (opts: { results: { email?: string; password?: string; };}) => Promise<unknown> | undefined
username: ({results: { email?: string; password?: string;}
results}) => function text(opts: TextOptions): Promise<string | symbol>
text({ TextOptions.message: string
message: 'What is your username?', TextOptions.placeholder?: string
placeholder: results: { email?: string; password?: string;}
results.email?: string | undefined
email?.String.replace(searchValue: string | RegExp, replaceValue: string): string (+3 overloads)
Replaces text in a string, using a regular expression or search string.
replace(/@.+$/, '').String.toLowerCase(): string
Converts all the alphabetic characters in a string to lowercase.
toLowerCase() ?? '', TextOptions.validate?: (value: string) => string | Error | undefined
validate: (value: string
value) => { // FOR DEMO PURPOSES ONLY! Use a robust validation library in production if (value: string
value.String.length: number
Returns the length of a String object.
length < 2) return 'Please enter at least 2 characters' } }), password: (opts: { results: { email?: string; username?: unknown; };}) => Promise<string | symbol | undefined> | undefined
password: () => function password(opts: PasswordOptions): Promise<string | symbol>
password({ PasswordOptions.message: string
message: 'Define your password' }),});
│ ◇ What is your email address? │ user.name@example.com │ ◇ What is your username? │ bomb_sh │ ◆ Define your password │ ▪▪▪▪▪▪▪▪▪▪▪▪_ └
The tasks
function provides a convenient API for sequencing several asynchronous actions one after the other.
import { const tasks: (tasks: Task[], opts?: CommonOptions) => Promise<void>
Define a group of tasks to be executed
tasks } from "@clack/prompts";
await function tasks(tasks: Task[], opts?: CommonOptions): Promise<void>
Define a group of tasks to be executed
tasks([ { title: string
Task title
title: 'Downloading package', task: (message: (string: string) => void) => string | Promise<string> | void | Promise<void>
Task function
task: async () => { // Do a fetch return 'Download completed'; }, }, { title: string
Task title
title: "Un-archiving", task: (message: (string: string) => void) => string | Promise<string> | void | Promise<void>
Task function
task: async (message: (string: string) => void
message) => { const const parts: string[]
parts: interface Array<T>
Array<string> = [/* ... */]; for (let let index: number
index = 0; let index: number
index < const parts: string[]
parts.Array<T>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length; let index: number
index++) { const const type: string
type = const parts: string[]
parts[let index: number
index]; // Update the message to indicate what is done message: (string: string) => void
message(`Un-archiving ${const type: string
type} (${let index: number
index + 1}/${const parts: string[]
parts.Array<T>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length})`); // Do the un-archiving task } return 'Un-archiving completed'; }, }, { title: string
Task title
title: 'Linking', task: (message: (string: string) => void) => string | Promise<string> | void | Promise<void>
Task function
task: async () => { // Do work return 'Package linked'; }, },]);
│ ◇ Download completed │ ◐ Un-archiving lib (2/3)..
Support functions
Section titled “Support functions”The intro
function defines the beginning of an interaction.
It accepts an optional string parameter which is displayed as a title for the interaction.
import { const intro: (title?: string, opts?: CommonOptions) => void
intro } from '@clack/prompts';
function intro(title?: string, opts?: CommonOptions): void
intro('Welcome to clack');
┌ Welcome to clack
The outro
function defines the end of an interaction.
It accepts an optional string parameter which is displayed as a concluding message.
import { const outro: (message?: string, opts?: CommonOptions) => void
outro } from '@clack/prompts';
function outro(message?: string, opts?: CommonOptions): void
outro('All operations are finished');
│ └ All operations are finished
Cancel
Section titled “Cancel”The cancel
function defines an interruption of an interaction and therefore its end.
It accepts an optional string parameter which is displayed as a cancellation message.
import { const cancel: (message?: string, opts?: CommonOptions) => void
cancel } from '@clack/prompts';
function cancel(message?: string, opts?: CommonOptions): void
cancel('Installation canceled');
└ Installation canceled
Spinner
Section titled “Spinner”The spinner
function provides a loading indicator for long-running operations.
import { const spinner: ({ indicator, onCancel, output, cancelMessage, errorMessage, frames, delay, }?: SpinnerOptions) => SpinnerResult
spinner } from '@clack/prompts';
const const spin: SpinnerResult
spin = function spinner({ indicator, onCancel, output, cancelMessage, errorMessage, frames, delay, }?: SpinnerOptions): SpinnerResult
spinner();const spin: SpinnerResult
spin.SpinnerResult.start(msg?: string): void
start('Loading');// Do somethingconst spin: SpinnerResult
spin.SpinnerResult.message(msg?: string): void
message('Finishing');// Do more thingsconst spin: SpinnerResult
spin.SpinnerResult.stop(msg?: string, code?: number): void
stop('Done');
│ ◒ Loading...
You can customize the spinner’s messages either per instance or globally:
import { const spinner: ({ indicator, onCancel, output, cancelMessage, errorMessage, frames, delay, }?: SpinnerOptions) => SpinnerResult
spinner, function updateSettings(updates: ClackSettings): void
updateSettings } from '@clack/prompts';
// Global customizationfunction updateSettings(updates: ClackSettings): void
updateSettings({ ClackSettings.messages?: { cancel?: string; error?: string;}
Custom messages for prompts
messages: { cancel?: string
Custom message to display when a spinner is cancelled
cancel: "Operation cancelled", error?: string
Custom message to display when a spinner encounters an error
error: "An error occurred", },});
// Per-instance customizationconst const spin: SpinnerResult
spin = function spinner({ indicator, onCancel, output, cancelMessage, errorMessage, frames, delay, }?: SpinnerOptions): SpinnerResult
spinner({ SpinnerOptions.cancelMessage?: string
cancelMessage: "Process cancelled", SpinnerOptions.errorMessage?: string
errorMessage: "Process failed",});
const spin: SpinnerResult
spin.SpinnerResult.start(msg?: string): void
start('Loading');// Do somethingconst spin: SpinnerResult
spin.SpinnerResult.stop(msg?: string, code?: number): void
stop('Done');
The second parameter of spinner.stop
(code
) allow you to indicate the ending status of the spinner:
0
(or no value) indicate a success and the symbol for a finished task will be used1
indicate a cancellation and the red square symbol will be used- Any other code indicate an error and the yellow triangle symbol will be used
You can also use custom frames for the spinner:
import { const spinner: ({ indicator, onCancel, output, cancelMessage, errorMessage, frames, delay, }?: SpinnerOptions) => SpinnerResult
spinner } from '@clack/prompts';
const const spin: SpinnerResult
spin = function spinner({ indicator, onCancel, output, cancelMessage, errorMessage, frames, delay, }?: SpinnerOptions): SpinnerResult
spinner({ SpinnerOptions.frames?: string[]
frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']});const spin: SpinnerResult
spin.SpinnerResult.start(msg?: string): void
start('Loading');// Do somethingconst spin: SpinnerResult
spin.SpinnerResult.stop(msg?: string, code?: number): void
stop('Done');
Progress
Section titled “Progress”The progress
prompt displays a progress bar for long-running operations.
import { function progress({ style, max: userMax, size: userSize, ...spinnerOptions }?: ProgressOptions): ProgressResult
progress } from '@clack/prompts';
const const prog: ProgressResult
prog = function progress({ style, max: userMax, size: userSize, ...spinnerOptions }?: ProgressOptions): ProgressResult
progress();const prog: ProgressResult
prog.SpinnerResult.start(msg?: string): void
start('Processing files');// Update progressconst prog: ProgressResult
prog.SpinnerResult.message(msg?: string): void
message('Halfway there');// Update againconst prog: ProgressResult
prog.SpinnerResult.message(msg?: string): void
message('Complete');const prog: ProgressResult
prog.SpinnerResult.stop(msg?: string, code?: number): void
stop('All files processed');
│ ◆ Processing files │ [████████████████████████████████████] 100% │ Complete ◆ All files processed
The note
function renders a box around a message to draw a user’s attention.
This is useful for displaying next steps and linking to your documentation towards the end of an interaction.
import { const note: (message?: string, title?: string, opts?: NoteOptions) => void
note } from '@clack/prompts';
function note(message?: string, title?: string, opts?: NoteOptions): void
note( 'You can edit the file src/index.jsx', 'Next steps.');
│ ◇ Next steps. ─────────────────────────╮ │ │ │ You can edit the file src/index.jsx │ │ │ ├───────────────────────────────────────╯
The second parameter (the title) is optional. You can also provide a format function to customize how each line is displayed:
import { const note: (message?: string, title?: string, opts?: NoteOptions) => void
note } from '@clack/prompts';
function note(message?: string, title?: string, opts?: NoteOptions): void
note( 'Line 1\nLine 2\nLine 3', 'Formatted steps', { NoteOptions.format?: (line: string) => string
format: (line: string
line: string) => `→ ${line: string
line}` });
│ ◇ Formatted steps ◇ ─────────────────────────────╮ │ │ │ → Line 1 │ │ → Line 2 │ │ → Line 3 │ │ │ ├────────────────────────────────╯
Task Log
Section titled “Task Log”The taskLog
prompt provides a way to display log output that is cleared on success. This is useful for showing progress or status updates that should be removed once the task is complete.
import { const taskLog: (opts: TaskLogOptions) => { message(msg: string, mopts?: TaskLogMessageOptions): void; error(message: string, opts?: TaskLogCompletionOptions): void; success(message: string, opts?: TaskLogCompletionOptions): void;}
Renders a log which clears on success and remains on failure
taskLog } from '@clack/prompts';
const const log: { message(msg: string, mopts?: TaskLogMessageOptions): void; error(message: string, opts?: TaskLogCompletionOptions): void; success(message: string, opts?: TaskLogCompletionOptions): void;}
log = function taskLog(opts: TaskLogOptions): { message(msg: string, mopts?: TaskLogMessageOptions): void; error(message: string, opts?: TaskLogCompletionOptions): void; success(message: string, opts?: TaskLogCompletionOptions): void;}
Renders a log which clears on success and remains on failure
taskLog({ TaskLogOptions.title: string
title: 'Installing dependencies'});const log: { message(msg: string, mopts?: TaskLogMessageOptions): void; error(message: string, opts?: TaskLogCompletionOptions): void; success(message: string, opts?: TaskLogCompletionOptions): void;}
log.function message(msg: string, mopts?: TaskLogMessageOptions): void
message('Fetching package information...');// Do some workconst log: { message(msg: string, mopts?: TaskLogMessageOptions): void; error(message: string, opts?: TaskLogCompletionOptions): void; success(message: string, opts?: TaskLogCompletionOptions): void;}
log.function message(msg: string, mopts?: TaskLogMessageOptions): void
message('Installing packages...');// Do more workconst log: { message(msg: string, mopts?: TaskLogMessageOptions): void; error(message: string, opts?: TaskLogCompletionOptions): void; success(message: string, opts?: TaskLogCompletionOptions): void;}
log.function success(message: string, opts?: TaskLogCompletionOptions): void
success('Installation complete');
│ ◆ Installing dependencies │ Fetching package information… │ Installing packages… ◆ Installation complete
The log
utilities allow you to add semantic contextual information during an interaction.
Each function renders with specific styling to communicate status.
log
is an object containing the following methods:
log.message
displays a message without any symbols to communicate statelog.info
displays a message with a neutral statelog.warn
(aliaslog.warning
) displays a message with a caution statelog.error
displays a message with a danger statelog.success
displays a message with a success statelog.step
displays a message with a neutral, completed state
import { const log: { message: (message?: string | string[], { symbol, secondarySymbol, output, spacing, }?: LogMessageOptions) => void; info: (message: string, opts?: LogMessageOptions) => void; ... 4 more ...; error: (message: string, opts?: LogMessageOptions) => void;}
log } from '@clack/prompts';
const log: { message: (message?: string | string[], { symbol, secondarySymbol, output, spacing, }?: LogMessageOptions) => void; info: (message: string, opts?: LogMessageOptions) => void; ... 4 more ...; error: (message: string, opts?: LogMessageOptions) => void;}
log.message: (message?: string | string[], { symbol, secondarySymbol, output, spacing, }?: LogMessageOptions) => void
message('Entering directory "src"');const log: { message: (message?: string | string[], { symbol, secondarySymbol, output, spacing, }?: LogMessageOptions) => void; info: (message: string, opts?: LogMessageOptions) => void; ... 4 more ...; error: (message: string, opts?: LogMessageOptions) => void;}
log.info: (message: string, opts?: LogMessageOptions) => void
info('No files to update');const log: { message: (message?: string | string[], { symbol, secondarySymbol, output, spacing, }?: LogMessageOptions) => void; info: (message: string, opts?: LogMessageOptions) => void; ... 4 more ...; error: (message: string, opts?: LogMessageOptions) => void;}
log.warn: (message: string, opts?: LogMessageOptions) => void
warn('Directory is empty, skipping');const log: { message: (message?: string | string[], { symbol, secondarySymbol, output, spacing, }?: LogMessageOptions) => void; info: (message: string, opts?: LogMessageOptions) => void; ... 4 more ...; error: (message: string, opts?: LogMessageOptions) => void;}
log.warning: (message: string, opts?: LogMessageOptions) => void
alias for log.warn()
.
warning('Directory is empty, skipping');const log: { message: (message?: string | string[], { symbol, secondarySymbol, output, spacing, }?: LogMessageOptions) => void; info: (message: string, opts?: LogMessageOptions) => void; ... 4 more ...; error: (message: string, opts?: LogMessageOptions) => void;}
log.error: (message: string, opts?: LogMessageOptions) => void
error('Permission denied on file src/secret.js');const log: { message: (message?: string | string[], { symbol, secondarySymbol, output, spacing, }?: LogMessageOptions) => void; info: (message: string, opts?: LogMessageOptions) => void; ... 4 more ...; error: (message: string, opts?: LogMessageOptions) => void;}
log.success: (message: string, opts?: LogMessageOptions) => void
success('Installation complete');const log: { message: (message?: string | string[], { symbol, secondarySymbol, output, spacing, }?: LogMessageOptions) => void; info: (message: string, opts?: LogMessageOptions) => void; ... 4 more ...; error: (message: string, opts?: LogMessageOptions) => void;}
log.step: (message: string, opts?: LogMessageOptions) => void
step('Check files');
│ │ Entering directory “src” │ ● No files to update │ ▲ Directory is empty, skipping │ ▲ Directory is empty, skipping │ ■ Permission denied on file src/secret.js │ ◆ Installation complete │ ◇ Check files
Internationalization
Section titled “Internationalization”The prompts package supports internationalization through the updateSettings
function. You can customize the messages used by various prompts to match your preferred language.
import { function updateSettings(updates: ClackSettings): void
updateSettings, const select: <Value>(opts: SelectOptions<Value>) => Promise<Value | symbol>
select, const cancel: (message?: string, opts?: CommonOptions) => void
cancel } from '@clack/prompts';
// Update global messagesfunction updateSettings(updates: ClackSettings): void
updateSettings({ ClackSettings.messages?: { cancel?: string; error?: string;}
Custom messages for prompts
messages: { cancel?: string
Custom message to display when a spinner is cancelled
cancel: "Operación cancelada", error?: string
Custom message to display when a spinner encounters an error
error: "Se ha producido un error" }});
// Use the select prompt with translated contentconst const framework: symbol | "next" | "astro" | "svelte"
framework = await select<"next" | "astro" | "svelte">(opts: SelectOptions<"next" | "astro" | "svelte">): Promise<symbol | "next" | "astro" | "svelte">
select({ SelectOptions<Value>.message: string
message: 'Selecciona un framework', SelectOptions<"next" | "astro" | "svelte">.options: ({ value: "next"; label?: string; hint?: string;} | { value: "astro"; label?: string; hint?: string;} | { value: "svelte"; label?: string; hint?: string;})[]
options: [ { value: "next"
Internal data for this option.
value: 'next', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'Next.js', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Framework de React' }, { value: "astro"
Internal data for this option.
value: 'astro', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'Astro', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Enfocado en contenido' }, { value: "svelte"
Internal data for this option.
value: 'svelte', label?: string
The optional, user-facing text for this option.
By default, the value
is converted to a string.
label: 'SvelteKit', hint?: string
An optional hint to display to the user when
this option might be selected.
By default, no hint
is displayed.
hint: 'Framework de compilación' }, ]});
// If the user cancels, they'll see the translated messageif (!const framework: symbol | "next" | "astro" | "svelte"
framework) { function cancel(message?: string, opts?: CommonOptions): void
cancel();}
│ ◆ Selecciona un framework │ ● Next.js (Framework de React) │ ○ Astro (Enfocado en contenido) │ ○ SvelteKit (Framework de compilación) └ └ Operación cancelada
Stream
Section titled “Stream”The stream
utilities allow you, like the log
utilities, to add semantic contextual information during an interaction,
expect that the message contains an unknown number of lines.
Each function renders with specific styling to communicate status.
import { const stream: { message: (iterable: Iterable<string> | AsyncIterable<string>, { symbol }?: LogMessageOptions) => Promise<void>; info: (iterable: Iterable<string> | AsyncIterable<string>) => Promise<void>; ... 4 more ...; error: (iterable: Iterable<string> | AsyncIterable<string>) => Promise<void>;}
stream } from "@clack/prompts";import * as module "node:fs"
fs from "node:fs";
await const stream: { message: (iterable: Iterable<string> | AsyncIterable<string>, { symbol }?: LogMessageOptions) => Promise<void>; info: (iterable: Iterable<string> | AsyncIterable<string>) => Promise<void>; ... 4 more ...; error: (iterable: Iterable<string> | AsyncIterable<string>) => Promise<void>;}
stream.message: (iterable: Iterable<string> | AsyncIterable<string>, { symbol }?: LogMessageOptions) => Promise<void>
message(module "node:fs"
fs.function createReadStream(path: fs.PathLike, options?: BufferEncoding | ReadStreamOptions): fs.ReadStream
options
can include start
and end
values to read a range of bytes from
the file instead of the entire file. Both start
and end
are inclusive and
start counting at 0, allowed values are in the
[0, Number.MAX_SAFE_INTEGER
] range. If fd
is specified and start
is
omitted or undefined
, fs.createReadStream()
reads sequentially from the
current file position. The encoding
can be any one of those accepted by Buffer
.
If fd
is specified, ReadStream
will ignore the path
argument and will use
the specified file descriptor. This means that no 'open'
event will be
emitted. fd
should be blocking; non-blocking fd
s should be passed to net.Socket
.
If fd
points to a character device that only supports blocking reads
(such as keyboard or sound card), read operations do not finish until data is
available. This can prevent the process from exiting and the stream from
closing naturally.
By default, the stream will emit a 'close'
event after it has been
destroyed. Set the emitClose
option to false
to change this behavior.
By providing the fs
option, it is possible to override the corresponding fs
implementations for open
, read
, and close
. When providing the fs
option,
an override for read
is required. If no fd
is provided, an override for open
is also required. If autoClose
is true
, an override for close
is
also required.
import { createReadStream } from 'node:fs';
// Create a stream from some character device.const stream = createReadStream('/dev/input/event0');setTimeout(() => { stream.close(); // This may not close the stream. // Artificially marking end-of-stream, as if the underlying resource had // indicated end-of-file by itself, allows the stream to close. // This does not cancel pending read operations, and if there is such an // operation, the process may still not be able to exit successfully // until it finishes. stream.push(null); stream.read(0);}, 100);
If autoClose
is false, then the file descriptor won't be closed, even if
there's an error. It is the application's responsibility to close it and make
sure there's no file descriptor leak. If autoClose
is set to true (default
behavior), on 'error'
or 'end'
the file descriptor will be closed
automatically.
mode
sets the file mode (permission and sticky bits), but only if the
file was created.
An example to read the last 10 bytes of a file which is 100 bytes long:
import { createReadStream } from 'node:fs';
createReadStream('sample.txt', { start: 90, end: 99 });
If options
is a string, then it specifies the encoding.
createReadStream('./banner.txt', { StreamOptions.encoding?: BufferEncoding | undefined
encoding: 'utf-8' }));await const stream: { message: (iterable: Iterable<string> | AsyncIterable<string>, { symbol }?: LogMessageOptions) => Promise<void>; info: (iterable: Iterable<string> | AsyncIterable<string>) => Promise<void>; ... 4 more ...; error: (iterable: Iterable<string> | AsyncIterable<string>) => Promise<void>;}
stream.info: (iterable: Iterable<string> | AsyncIterable<string>) => Promise<void>
info((async function*() { yield 'Open file...'; // Open file yield ' \x1b[32mOK\x1b[39m\n';
yield 'Parsing file...'; // Parse data yield ' \x1b[32mOK\x1b[39m'; return;})());await const stream: { message: (iterable: Iterable<string> | AsyncIterable<string>, { symbol }?: LogMessageOptions) => Promise<void>; info: (iterable: Iterable<string> | AsyncIterable<string>) => Promise<void>; ... 4 more ...; error: (iterable: Iterable<string> | AsyncIterable<string>) => Promise<void>;}
stream.step: (iterable: Iterable<string> | AsyncIterable<string>) => Promise<void>
step([ 'Job1...', ' \x1b[32mdone\x1b[39m\n', 'Job2...', ' \x1b[32mdone\x1b[39m\n', 'Job3...', ' \x1b[32mdone\x1b[39m',]);
│ │ │ ⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣶⣶⣿⣿⣿⣿⣿⣿⣶⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ │ ⠀⠀⠀⠀⠀⣠⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ │ ⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ │ ⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ │ ⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀ │ ⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⣀⠀⠀⠀⠀⣿⣿⣿⡿⠀⠀⠀⠀⣀⠀ │ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⢠⣿⣿⣶⣤⣄⣻⣿⣿⣇⣠⣴⣶⣿⣿⡀ │ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⢾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡧ │ ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠉⢉⣿⣿⣿⣿⣿⣯⡉⠉⠀⠀⠀ │ ⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⠟⢻⣿⣿⣿⣦⠀⠀⠀ │ ⠀⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠐⠿⣿⣿⣿⠏⠀⠀⢻⣿⣿⣿⠷⠀⠀ │ ⠀⠀⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⠏⠀⠀⠀⠀⠹⠋⠁⠀⠀⠀ │ ⠀⠀⠀⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ │ ⠀⠀⠀⠀⠀⠙⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ │ ⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠻⠿⢿⣿⣿⣿⣿⡿⠿⠟⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ │ │ ● Open file... OK │ Parsing file... OK │ ◇ Job1... done │ Job2... done │ Job3... done