---
title: "Prompts"
description: "Learn about the prompts package and its capabilities"
canonical: https://bomb.sh/docs/clack/packages/prompts/
---

# 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

* **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
* **AbortController support**: Cancel prompts programmatically
* **Custom I/O streams**: Use custom input/output streams

## Installation

**npm**

```bash
npm install @clack/prompts
```

**pnpm**

```bash
pnpm add @clack/prompts
```

**Yarn**

```bash
yarn add @clack/prompts
```

## Usage

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](/docs/clack/guides/examples) and [best practices](/docs/clack/guides/best-practices).

## Common Options

All prompts share these common options:

### Guide Lines

The `withGuide` option (boolean **option**, not a separate API) turns Clack’s border/guide lines on or off. Every prompt accepts it alongside `message` and friends, and so do the output helpers that draw their own gutter, such as [`box`](#box). You can set it globally with `updateSettings` or override it per call.

```ts
import { text, updateSettings } from '@clack/prompts';

// Disable globally
updateSettings({ withGuide: false });

// Or per-prompt
const name = await text({
  message: 'What is your name?',
  withGuide: false,  // Disable guide lines for this prompt
});
```

Session helpers use the same option on their **second argument**: `intro(title, { withGuide: false })`, `outro(message, { withGuide: false })`, and `cancel(message, { withGuide: false })`.

`autocomplete` and `multiselect` respect `withGuide: false` per prompt (as of v1.2.0), matching other prompts.

### AbortController Support

All prompts accept a `signal` option for programmatic cancellation, and so does the [spinner](#spinner):

```ts
import { confirm } from '@clack/prompts';

// Auto-cancel after 10 seconds
const shouldContinue = await confirm({
  message: 'This will self-destruct in 10 seconds',
  signal: AbortSignal.timeout(10000),
});
```

### Custom I/O Streams

You can provide custom input and output streams for all prompts:

```ts
import { Writable, Readable } from 'node:stream';
import { text } from '@clack/prompts';

declare const customInput: Readable;
declare const customOutput: Writable;

const name = await text({
  message: 'What is your name?',
  input: customInput,
  output: customOutput,
});
```

## Available Prompts

### Text Input

The text prompt accepts a single line of text.

```ts
import { text } from '@clack/prompts';

const name = await text({
  message: 'What is your name?',
  placeholder: 'John Doe',
  validate: (value) => {
    if (!value || value.length < 2) return 'Name must be at least 2 characters';
    return undefined;
  },
});
```

│
◆  What is your name?
│  John Doe
└

Options:

* `message`: The prompt message shown to the user above the input.
* `placeholder`: A visual hint shown when the field has no content.
* `defaultValue`: A fallback value returned when the user provides nothing (empty input).
* `initialValue`: The starting value shown when the prompt first renders. Users can edit this value before submitting.
* `validate`: A function or a [Standard Schema](https://github.com/standard-schema/standard-schema) that validates user input. If a custom function is given, you should return a `string` or `Error` to show as a validation error, or `undefined` to accept the result. May return a `Promise`; the prompt shows a validating state and blocks input until it resolves (v1.8.0).
* All [Common Options](#common-options)

Validation can be asynchronous (v1.8.0). While the promise is pending, the prompt ignores keypresses and shows a dim `Validating...` line. Async [Standard Schema](https://github.com/standard-schema/standard-schema) validators are supported too.

```ts
import { text } from '@clack/prompts';

declare function isUsernameTaken(name: string): Promise<boolean>;

const username = await text({
  message: 'Pick a username',
  validate: async (value) => {
    if (!value) return 'Username is required';
    if (await isUsernameTaken(value)) return 'That name is taken';
    return undefined;
  },
});
```

│
◆  Pick a username
│  ada
└  Validating...

### Password Input

Behaves like the text component, but the input is masked.

```ts
import { password } from '@clack/prompts';

const secret = await password({
  message: 'What is your password?',
  mask: '*',
  clearOnError: true,  // Clear input when validation fails
  validate: (value) => {
    if (!value || value.length < 8) return 'Your password must be at least 8 characters';
    if (!/[A-Z]/.test(value)) return 'Your password must be least contain 1 uppercase letter';
    if (!/[0-9]/.test(value)) return 'Your password must be least contain 1 number';
    if (!/[*?!@&]/.test(value)) return 'Your password must be least contain 1 special characters (*?!@&)';
    return undefined;
  },
});
```

│
◆  What is your password?
│  \*\*\*\*\*\_
└

Options:

* `message`: The prompt message or question shown to the user above the input.
* `mask`: Character to use for masking input. Default: `'▪/•'`.
* `validate`: A function or a [Standard Schema](https://github.com/standard-schema/standard-schema) that validates user input. If a custom function is given, you should return a `string` or `Error` to show as a validation error, or `undefined` to accept the result. May return a `Promise`; the prompt blocks input until it resolves (v1.8.0).
* `clearOnError`: When enabled it causes the input to be cleared if/when validation fails. Default: `false`.
* Submitting with no input resolves to `""`, matching `text()` and the documented `Promise<string | symbol>` return type (v1.4.2).
* All [Common Options](#common-options)

Common options (`withGuide`, `signal`, `input`, `output`) are also supported.

### Multi-line Text

The multi-line component accepts multiple lines of text input. By default, pressing Enter twice **at the end of the input** submits; a double Enter elsewhere in the text adds a blank line instead (v1.4.2).

```ts
import { multiline } from '@clack/prompts';

const bio = await multiline({
	message: 'Enter your bio',
	placeholder: 'Tell us about yourself...',
	showSubmit: true,
});
```

│
◆ Enter your bio
│  Tell us about yourself...
└
&#x20; \[ submit ]

Options:

* `showSubmit`: When enabled it shows a `[ submit ]` button that can be focused with tab. By default, pressing Enter twice at the end of the input submits. Default: `false`.
* `initialValue`: Pre-fills editable content when the prompt opens; the cursor is placed at the end (v1.4.2). See also [Text Options](#text-input).
* All [Text Options](#text-input)

### Selection

`select`, `multiselect`, and `groupMultiselect` show persistent keyboard hint footers while active (v1.6.0), matching `autocomplete`. Pass `showInstructions: false` to hide them (v1.7.0). Default: `true`.

#### Simple value

```ts
import { select } from '@clack/prompts';

const framework = await select({
  message: 'Pick a framework',
  options: [
    { value: 'next', label: 'Next.js', hint: 'React framework' },
    { value: 'astro', label: 'Astro', hint: 'Content-focused' },
    { value: 'svelte', label: 'SvelteKit', hint: 'Compile-time framework' },
  ],
  maxItems: 5, // Maximum number of items to display at once
});
```

│
◆  Pick a framework
│  ● Next.js (React framework)
│  ○ Astro (Content-focused)
│  ○ SvelteKit (Compile-time framework)
│  ↑/↓ to navigate • Enter: confirm
└

#### Hide instructions

```ts
import { select } from '@clack/prompts';

const framework = await select({
  message: 'Pick a framework',
  options: [
    { value: 'next', label: 'Next.js', hint: 'React framework' },
    { value: 'astro', label: 'Astro', hint: 'Content-focused' },
    { value: 'svelte', label: 'SvelteKit', hint: 'Compile-time framework' },
  ],
  showInstructions: false,
});
```

│
◆  Pick a framework
│  ● Next.js (React framework)
│  ○ Astro (Content-focused)
│  ○ SvelteKit (Compile-time framework)
└

#### Complex value

```ts
import { select } from '@clack/prompts';

const framework = await select({
  message: 'Pick a framework',
  options: [
    { value: { framework: 'Next', language: 'React' }, label: 'Next.js', hint: 'React framework' },
    { value: { framework: null, language: 'Astro' }, label: 'Astro', hint: 'Content-focused' },
    { value: { framework: 'Sveltekit', language: 'Svelte' }, label: 'SvelteKit', hint: 'Compile-time framework' },
  ],
});
```

│
│  Pick a framework
│  ● Next.js (React framework)
│  ○ Astro (Content-focused)
│  ○ SvelteKit (Compile-time framework)
└

#### Disabled options

You can disable specific options to prevent selection:

```ts
import { select } from '@clack/prompts';

const database = await select({
  message: 'Select a database',
  options: [
    { value: 'postgres', label: 'PostgreSQL', hint: 'Recommended' },
    { value: 'mysql', label: 'MySQL' },
    { value: 'mongodb', label: 'MongoDB', disabled: true, hint: 'Coming soon' },
    { value: 'sqlite', label: 'SQLite' },
  ],
});
```

│
◆  Select a database
│  ● PostgreSQL (Recommended)
│  ○ MySQL
│  ○ MongoDB (Coming soon)
│  ○ SQLite
└

Disabled options are displayed with strikethrough styling and cannot be selected.

#### Multiple values

```ts
import { multiselect } from '@clack/prompts';

const framework = await multiselect({
  message: 'Pick a framework',
  options: [
    { value: { framework: 'Next', language: 'React' }, label: 'Next.js', hint: 'React framework' },
    { value: { framework: null, language: 'Astro' }, label: 'Astro', hint: 'Content-focused' },
    { value: { framework: 'Sveltekit', language: 'Svelte' }, label: 'SvelteKit', hint: 'Compile-time framework' },
  ],
  maxItems: 5, // Maximum number of items to display at once
});
```

│
◆  Pick a framework
│  ◼ Next.js (React framework)
│  ◻ Astro (Content-focused)
│  ◻ SvelteKit (Compile-time framework)
│  ↑/↓ to navigate • Space: select • Enter: confirm
└

### Select by key

`selectKey` shows each option with a visible key (the option `value`, typically one character). The user presses that key instead of moving a cursor with arrows—useful for compact yes/no/maybe menus or vim-style shortcuts.

```ts
import { selectKey, isCancel } from '@clack/prompts';

const action = await selectKey({
  message: 'What next?',
  options: [
    { value: 'y', label: 'Continue' },
    { value: 'n', label: 'Stop' },
    { value: 's', label: 'Skip', hint: 'optional' },
  ],
  caseSensitive: false,
});

if (isCancel(action)) {
  process.exit(0);
}
```

### 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.

```ts
import { autocomplete } from '@clack/prompts';

const framework = await autocomplete({
  message: 'Search for a framework',
  options: [
    { value: 'next', label: 'Next.js', hint: 'React framework' },
    { value: 'astro', label: 'Astro', hint: 'Content-focused' },
    { value: 'svelte', label: 'SvelteKit', hint: 'Compile-time framework' },
    { value: 'remix', label: 'Remix', hint: 'Full stack framework' },
    { value: 'nuxt', label: 'Nuxt', hint: 'Vue framework' },
  ],
  placeholder: 'Type to search...',
  maxItems: 5,
});
```

│
◆ Search for a framework
│  Search: n
│  (2 matches)
│  ● Next.js (React framework)
│  ○ Nuxt (Vue framework)
└

Options:

* `message`: The message or question shown to the user above the input.
* `options`: The options to present, or a function that returns the options to present allowing for custom search/filtering. [Learn more below](#dynamic-options-getter).
* `maxItems`: The maximum number of items/options to display in the autocomplete list at once.
* `placeholder`: Placeholder text displayed when the search field is empty. When set, pressing Tab on an empty input copies the placeholder into the input. This takes precedence over `completeOnTab`.
* `completeOnTab`: When `true`, pressing Tab fills the input with the focused option's value and adds a `Tab: complete` hint to the footer. Single-select only; ignored with `multiple: true`. Default: `false` (v1.8.0).
* `validate`: A function that validates user input. Return a `string` or `Error` to show as a validation error, or `undefined` to accept the result. May return a `Promise`; the prompt blocks input until it resolves (v1.8.0).
* `filter`: Custom filter function to match options against the search input.
* `initialValue`: The initially selected option from the list.
* `initialUserInput`: The starting value shown in the users input box.
* All [Common Options](#common-options)

#### Dynamic options (getter)

Instead of a static array, `options` can be a **function** whose `this` is the underlying [`AutocompletePrompt`](https://github.com/bombshell-dev/clack/blob/main/packages/core/src/prompts/autocomplete.ts) from `@clack/core`. The function runs again whenever the search text changes, so you can read **`this.userInput`** and return a **new array in display order**—for example closest / highest-score matches first (similar to [fzf](https://github.com/junegunn/fzf)-style UIs). This pattern is what [issue #467](https://github.com/bombshell-dev/clack/issues/467) discusses for custom ranking and libraries like [Fuse.js](https://fusejs.io/).

The high-level `autocomplete` wrapper still applies its **default `filter`** (substring match on label, hint, and value) to whatever your getter returns. If you already narrow or rank items in the getter, disable that second pass with **`filter: (_search, _option) => true`**, or pass a custom `(search, option) => boolean` aligned with your getter.

`options` as a getter must be **synchronous**; there is no async API here—preload or sync work inside the function.

The same `options` shape is supported on **`autocompleteMultiselect`**.

```ts
import { autocomplete } from '@clack/prompts';
import type { AutocompletePrompt } from '@clack/core';
import type { Option } from '@clack/prompts';

const pool: Option<string>[] = [
  { value: 'next', label: 'Next.js', hint: 'React' },
  { value: 'nuxt', label: 'Nuxt', hint: 'Vue' },
  { value: 'nest', label: 'NestJS', hint: 'Node' },
];

function rankByQuery(query: string, items: Option<string>[]): Option<string>[] {
  const q = query.trim().toLowerCase();
  if (!q) return [...items];
  return [...items]
    .filter((o) => {
      const t = `${o.label ?? ''} ${o.hint ?? ''} ${o.value}`.toLowerCase();
      return t.includes(q);
    })
    .sort((a, b) => {
      const la = (a.label ?? '').toLowerCase();
      const lb = (b.label ?? '').toLowerCase();
      const sa = la.startsWith(q) ? 0 : 1;
      const sb = lb.startsWith(q) ? 0 : 1;
      return sa - sb || la.localeCompare(lb);
    });
}

const picked = await autocomplete({
  message: 'Pick a framework',
  options(this: AutocompletePrompt<Option<string>>) {
    return rankByQuery(this.userInput, pool);
  },
  filter: (_search, _option) => true,
});
```

### Autocomplete Multiselect

The `autocompleteMultiselect` prompt combines the search functionality of [autocomplete](#autocomplete) with the ability to select multiple options.

```ts
import { autocompleteMultiselect } from '@clack/prompts';

const frameworks = await autocompleteMultiselect({
  message: 'Select frameworks',
  options: [
    { value: 'next', label: 'Next.js', hint: 'React framework' },
    { value: 'astro', label: 'Astro', hint: 'Content-focused' },
    { value: 'svelte', label: 'SvelteKit', hint: 'Compile-time framework' },
    { value: 'remix', label: 'Remix', hint: 'Full stack framework' },
    { value: 'nuxt', label: 'Nuxt', hint: 'Vue framework' },
  ],
  placeholder: 'Type to search...',
  maxItems: 5, // Maximum number of items to display at once
});
```

│
◆ Select frameworks
│  Search: n
│  (2 matches)
│  ◼ Next.js (React framework)
│  ◻ Nuxt (Vue framework)
└

Options:

* `message`: The prompt message or question shown to the user above the input.
* `options`: The options to present, or a function that returns the options to present allowing for custom search/filtering. [Learn more below](#dynamic-options-getter).
* `maxItems`: The maximum number of items/options to display in the autocomplete list at once.
* `placeholder`: Placeholder text displayed when the search field is empty. When set, pressing tab copies the placeholder into the input.
* `validate`: A function that validates user input. Return a `string` or `Error` to show as a validation error, or `undefined` to accept the result.
* `filter`: Custom filter function to match options against the search input.
* `initialValues`: The initially selected option(s) from the list.
* `required`: When `true` at least one option must be selected (default: `false`).
* All [Common Options](#common-options)

### Path Selection

The `path` prompt extends [`autocomplete`](#autocomplete) to provide file and directory suggestions. Press **Tab** to complete the focused suggestion, then type `/` and press Tab again to descend into it (v1.8.0).

```ts
import { path } from '@clack/prompts';

const selectedPath = await path({
  message: 'Select a file:',
  root: process.cwd(), // Starting directory
  directory: false, // Set to true to only show directories
});
```

│
◆  Select a file:
│  Search: /Users/project/
│  (3 matches)
│  ● /Users/project/src
│  ○ /Users/project/package.json
│  ○ /Users/project/tsconfig.json
└

Options:

* `message`: The message or question shown to the user above the input.
* `root`: The starting directory for path suggestions (defaults to current working directory).
* `directory`: When `true` only **directories** appear in suggestions while you navigate (v1.2.0 fixes for directory-only mode).
* `initialValue`: The starting path shown when the prompt first renders, which users can edit before submitting. If not provided it will fall back to the given `root`, or the current working directory. In `directory` mode, if the initial value points to a directory that exists, pressing enter will submit the input instead of jumping to the first child (v1.2.0).
* `validate`: A function that validates the given path. Return a `string` or `Error` to show as a validation error, or `undefined` to accept the result. May return a `Promise`; the prompt blocks input until it resolves (v1.8.0).
* All [Common Options](#common-options)

### Date input

The `date` prompt provides an interactive date picker, allowing users to navigate between year, month, and day segments and increment/decrement values using keyboard controls.

```ts
import { date } from '@clack/prompts';

const birthday = await date({
  message: 'Pick your birthday',
  minDate: new Date('1900-01-01'),
  initialValue: new Date(),
  maxDate: new Date(),
});
```

Options:

* `message`: The message or question shown to the user above the input.
* `format`: The date format to use (default: based on `locale`).
* `locale`: The [BCP 47 language tag](https://developer.mozilla.org/en-US/docs/Glossary/BCP_47_language_tag) to use for formatting.
* `defaultValue`: The default value returned when the user doesn't select a date.
* `initialValue`: The starting date shown when the prompt first renders. Users can edit this value before submitting.
* `minDate`: The minimum allowed date for validation.
* `maxDate`: The maximum allowed date for validation.
* `validate`: A function or a [Standard Schema](https://github.com/standard-schema/standard-schema) that validates user input. If a custom function is given, you should return a `string` or `Error` to show as a validation error, or `undefined` to accept the result. May return a `Promise`; the prompt blocks input until it resolves (v1.8.0).
* All [Common Options](#common-options)

### Confirmation

The `confirm` prompt accepts a yes or no choice, returning a boolean value corresponding to the user's selection.

```ts
import { confirm } from '@clack/prompts';

const shouldProceed = await confirm({
  message: 'Do you want to continue?',
});
```

│
◆ Do you want to continue?
│  ● Yes / ○ No
└

:::tip
Multi-line `message` strings wrap correctly; guide lines apply to wrapped confirmation text (v1.2.0).
:::

Options:

* `message`: The message or question shown to the user above the input.
* `active`: The label to use for the active (true) option (default: `Yes`).
* `inactive`: The label to use for the inactive (false) option (default: `No`).
* `initialValue`: The initial selected value (true or false) (default: `true`).
* `vertical`: Whether to render the options vertically instead of horizontally (default: `false`) (v1.0.1+).
* All [Common Options](#common-options)

## Grouping

### Group Multiselect

The `groupMultiselect` prompt extends the [`multiselect`](#multiple-values) prompt to allow arranging distinct Multi-Selects, whilst keeping all of them interactive.

```ts
import { groupMultiselect } from '@clack/prompts';

const projectOptions = await groupMultiselect({
    message: 'Define your project',
    options: {
        'Testing': [
            { value: 'Jest', hint: 'JavaScript testing framework' },
            { value: 'Playwright', hint: 'End-to-end testing' },
            { value: 'Vitest', hint: 'Vite-native testing' },
        ],
        'Language': [{
            label: "Javascript",
            value: 'js',
            hint: 'Dynamic typing'
        }, {
            label: 'TypeScript',
            value: 'ts',
            hint: 'Static typing'
        }, {
            label: "CoffeeScript",
            value: 'coffee',
            hint: 'JavaScript with Ruby-like syntax'
        }],
        'Code quality': [
            { value: 'Prettier', hint: 'Code formatter' },
            { value: 'ESLint', hint: 'Linter' },
            { value: 'Biome.js', hint: 'Formatter and linter' },
        ],
    },
    groupSpacing: 1, // Add one new line between each group
    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)
│  ↑/↓ to navigate • Space: select • Enter: confirm
└

Options:

* `message`: The message or question shown to the user above the input.
* `options`: Grouped options to display. Each key is a group label, and each value is an array of options.
* `initialValues`: The initially selected option(s).
* `maxItems`: The maximum number of items/options to display at once.
* `required`: When `true` at least one option must be selected (default: `true`).
* `cursorAt`: The value the cursor should be positioned at initially.
* `selectableGroups`: Whether entire groups can be selected at once (default: `true`).
* `groupSpacing`: Number of blank lines between groups (default: `0`).
* `showInstructions`: Whether to show keyboard instructions below the option list (default: `true`) (v1.7.0).
* All [Common Options](#common-options)

### Group

The `group` utility provides a consistent way to combine a series of prompts, combining each answer into one object. Each prompt receives the results of all previously completed prompts, and are executed sequentially.

```ts
import { group, text, password } from '@clack/prompts';

const account = await group({
    email: () => text({
        message: 'What is your email address?',
        validate: (value) => {
            if (!value || !/^[a-z0-9_.-]+@[a-z0-9_.-]+\.[a-z]{2,}$/i.test(value)) return 'Please enter a valid email'
        }
    }),
    username: ({results}) => text({
        message: 'What is your username?',
        placeholder: results.email?.replace(/@.+$/, '').toLowerCase() ?? '',
        validate: (value) => {
            // FOR DEMO PURPOSES ONLY! Use a robust validation library in production
            if (!value || value.length < 2) return 'Please enter at least 2 characters'
        }
    }),
    password: () => password({
        message: 'Define your password'
    }),
});
```

│
◇ What is your email address?
│  <user.name@example.com>
│
◇ What is your username?
│  bomb\_sh
│
◆ Define your password
│  ▪▪▪▪▪▪▪▪▪▪▪▪\_
└

Options:

* `onCancel`: Called when any one of the prompts is canceled.

### Tasks

The `tasks` function provides a convenient API for sequencing several asynchronous actions one after the other.

```ts
import { tasks } from "@clack/prompts";

await tasks([
    {
        title: 'Downloading package',
        task: async () => {
            // Do a fetch
            return 'Download completed';
        },
    },
    {
        title: "Un-archiving",
        task: async (message) => {
            const parts: Array<string> = [/* ... */];
            for (let index = 0; index < parts.length; index++) {
                const type = parts[index];
                // Update the message to indicate what is done
                message(`Un-archiving ${type} (${index + 1}/${parts.length})`);
                // Do the un-archiving task
            }
            return 'Un-archiving completed';
        },
    },
    {
        title: 'Linking',
        task: async () => {
            // Do work
            return 'Package linked';
        },
    },
]);
```

│
◇  Download completed
│
◐  Un-archiving lib (2/3)..

## Support functions

### Intro

The `intro` function defines the beginning of an interaction.
It accepts an optional string parameter which is displayed as a title for the interaction.

> **Tip:**
>
> Feel free to use ANSI escape sequences to add colors and a more branded feel to your intro message!

```ts
import { intro } from '@clack/prompts';

intro('Welcome to clack');
```

┌  Welcome to clack

Options:

* All [Common Options](#common-options)

### Outro

The `outro` function defines the end of an interaction.
It accepts an optional string parameter which is displayed as a concluding message.

```ts
import { outro } from '@clack/prompts';

outro('All operations are finished');
```

│
└  All operations are finished
 

Options:

* All [Common Options](#common-options)

### 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.

```ts
import { cancel } from '@clack/prompts';
import process from 'node:process';

cancel('Installation canceled');
process.exit(1);
```

└  Installation canceled
 

Options:

* All [Common Options](#common-options)

To detect a cancelled prompt, use `isCancel()`. The raw sentinel it checks for, `CANCEL_SYMBOL`, is also exported from both `@clack/prompts` and `@clack/core` for cases where you need the value itself, such as returning it from a custom `Prompt` or comparing against it in tests (v1.8.0).

### Spinner

The `spinner` function provides a loading indicator for long-running operations.

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

const spin = spinner();
spin.start('Loading');
// Do something
spin.message('Finishing');
// Do more things
spin.stop('Done');
```

│
◒  Loading

#### Spinner Methods

The spinner provides multiple methods to indicate different completion states:

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

const spin = spinner();
spin.start('Processing');

// Success - shows green checkmark
spin.stop('Completed successfully');

// Or cancel - shows red square
// spin.cancel('Operation cancelled');

// Or error - shows yellow triangle
// spin.error('An error occurred');

// Or clear - stops without showing any message
// spin.clear();
```

You can also check if the spinner was cancelled via SIGINT (Ctrl+C):

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

const spin = spinner({
  onCancel: () => {
    console.log('User pressed Ctrl+C');
  }
});

spin.start('Long running task');
// ... after some work
if (spin.isCancelled) {
  // Handle cancellation
}
```

The spinner also accepts a `signal` option. Aborting the signal stops the spinner exactly as Ctrl+C does. The cancel message is printed, `isCancelled` becomes `true`, and `onCancel` runs. The process itself keeps going, so you decide what happens next.

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

const controller = new AbortController();
const spin = spinner({ signal: controller.signal });

spin.start('Fetching data');
// Abort from elsewhere, such as a timeout or a failing parent task
controller.abort();
```

#### Customization Options

```ts
import { spinner, updateSettings } from '@clack/prompts';

// Global customization for i18n
updateSettings({
  messages: {
    cancel: "Operation cancelled",
    error: "An error occurred",
  },
});

// Per-instance customization
const spin = spinner({
  indicator: 'timer',        // 'dots' (default) or 'timer' for elapsed time display
  cancelMessage: "Process cancelled",
  errorMessage: "Process failed",
  frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],  // Custom animation frames
  delay: 80,                 // Animation delay in ms
  styleFrame: (frame) => `\x1b[35m${frame}\x1b[0m`,  // Custom frame styling
});

spin.start('Loading');
// Do something
spin.stop('Done');
```

The `indicator` option supports two modes:

* `'dots'`: Animated dots that cycle (default)
* `'timer'`: Shows elapsed time like `[5s]` or `[1m 30s]`

### Progress

The `progress` function displays a progress bar for long-running operations with multiple visual styles.

```ts
import { progress } from '@clack/prompts';

const prog = progress({
  style: 'heavy',  // 'light', 'heavy', or 'block'
  max: 100,        // Maximum value (default: 100)
  size: 40,        // Width of the progress bar (default: 40)
});

prog.start('Processing files');

// Advance the progress bar
prog.advance(10);  // Advance by 10 steps
prog.advance(25, 'Processing images...');  // Advance with a message update

// Update just the message
prog.message('Almost done...');

// Complete the progress
prog.stop('All files processed');
```

│
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Processing images...

The progress bar supports three visual styles:

* `'light'`: Uses thin lines (`─`)
* `'heavy'`: Uses thick lines (`━`) - default
* `'block'`: Uses solid blocks (`█`)

Additional methods:

* `advance(step?, msg?)`: Advance the progress bar by `step` (default: 1) and optionally update the message
* `message(msg)`: Update the displayed message without advancing
* `stop(msg?)`: Complete the progress bar with a success message
* `cancel(msg?)`: Stop with a cancellation indicator
* `error(msg?)`: Stop with an error indicator
* `clear()`: Stop and clear the progress bar without a message

You can also use the timer indicator mode for time-based feedback:

```ts
import { progress } from '@clack/prompts';

const prog = progress({
  indicator: 'timer',  // Shows elapsed time instead of animated dots
  style: 'block',
  max: 50,
});

prog.start('Downloading');
// Progress shows: ████████████░░░░░░░░ Downloading [5s]
```

### Note

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.

```ts
import { note } from '@clack/prompts';

note(
  'You can edit the file src/index.jsx',
  'Next steps.'
);
```

│
◇  Next steps. ─────────────────────────╮
│                                       │
│  You can edit the file src/index.jsx  │
│                                       │
├───────────────────────────────────────╯

> **Note:**
>
> As of v1.6.0, body lines in&#x20;
>
> `note()`
>
> &#x20;are no longer dimmed by default. To restore the previous styling, pass a&#x20;
>
> `format`
>
> &#x20;function—for example, using&#x20;
>
> `styleText`
>
> &#x20;from&#x20;
>
> `node:util`
>
> :

```ts
import { note } from '@clack/prompts';
import { styleText } from 'node:util';

note(
  'You can edit the file src/index.jsx',
  'Next steps.',
  { format: (text) => styleText('dim', text) }
);
```

The second parameter (the title) is optional. You can also provide a format function to customize how each line is displayed:

```ts
import { note } from '@clack/prompts';

note(
  'Line 1\nLine 2\nLine 3',
  'Formatted steps',
  {
    format: (line: string) => `→ ${line}`
  }
);
```

│
◇  Formatted steps
◇   ─────────────────────────────╮
│                                │
│  → Line 1                      │
│  → Line 2                      │
│  → Line 3                      │
│                                │
├────────────────────────────────╯

### Box

The `box` function renders a customizable box around text content. It's similar to `note` but offers more styling options.

```ts
import { box } from '@clack/prompts';

box('This is the content of the box', 'Box Title', {
  contentAlign: 'center',
  titleAlign: 'center',
  width: 'auto',
  rounded: true,
});
```

│  ╭──────────Box Title───────────╮
│  │                              │
│  │  This is the content of the  │
│  │            box               │
│  │                              │
│  ╰──────────────────────────────╯

Options:

* `contentAlign`: Alignment of the content (`'left'`, `'center'`, or `'right'`. default `'left'`).
* `titleAlign`: Alignment of the title (`'left'`, `'center'`, or `'right'`. default `'left'`).
* `width`: The width of the box, either `'auto'` to fit the content or a number for a fixed width (default: `'auto'`).
* `titlePadding`: Padding around the title (default: `1`).
* `contentPadding`: Padding around the content (default: `2`).
* `rounded`: Use rounded corners when `true` (default), square corners when `false` (default: `true`).
* `formatBorder`: Custom function to style the border characters.
* `withGuide`: Draw the guide bar to the left of the box (default: follows the global `withGuide` setting, which is `true`). As of v1.8.0 the bar is grey, matching the gutter drawn by `log`, `note` and the spinner.

### 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.

```ts
import { taskLog } from '@clack/prompts';

const log = taskLog({
  title: 'Installing dependencies',
  limit: 10,        // Limit visible log lines (optional)
  retainLog: false, // Keep full log history (optional)
});
log.message('Fetching package information...');
// Do some work
log.message('Installing packages...');
// Do more work
log.success('Installation complete');
```

│
◆  Installing dependencies
│  Fetching package information...
│  Installing packages...
◆  Installation complete

#### Task Log Groups

Task logs support named groups, which allow you to organize logs into separate sections with their own headers and completion states:

```ts
import { taskLog } from '@clack/prompts';

const log = taskLog({
  title: 'Building project'
});

// Create a group for TypeScript compilation
const tsGroup = log.group('Compiling TypeScript');
tsGroup.message('Processing src/index.ts...');
tsGroup.message('Processing src/utils.ts...');
tsGroup.success('TypeScript compiled');

// Create another group for bundling
const bundleGroup = log.group('Bundling');
bundleGroup.message('Creating bundle...');
bundleGroup.message('Minifying...');
bundleGroup.success('Bundle created');

// Complete the overall task
log.success('Build complete');
```

Each group has its own `message()`, `success()`, and `error()` methods, allowing independent tracking of subtasks within a larger operation.

### Logs

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 state
* `log.info` displays a message with a neutral state
* `log.warn` (alias `log.warning`) displays a message with a caution state
* `log.error` displays a message with a danger state
* `log.success` displays a message with a success state
* `log.step` displays a message with a neutral, completed state

```ts
import { log } from '@clack/prompts';

log.message('Entering directory "src"');
log.info('No files to update');
log.warn('Directory is empty, skipping');
log.warning('Directory is empty, skipping');
log.error('Permission denied on file src/secret.js');
log.success('Installation complete');
log.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

The prompts package supports internationalization through the `updateSettings` function. You can customize the messages used by various prompts to match your preferred language.

```ts
import { updateSettings, select, cancel } from '@clack/prompts';

// Update global messages
updateSettings({
  messages: {
    cancel: "Operación cancelada",
    error: "Se ha producido un error",
  },
  date: {
    monthNames: [
      "enero", "febrero", "marzo", "abril", "mayo", "junio",
      "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre",
    ],
    messages: {
      required: "Introduce una fecha válida",
      invalidMonth: "Solo hay 12 meses",
      invalidDay: (days, month) => `Solo hay ${days} días en ${month}`,
      afterMin: (min) => `La fecha debe ser el ${min.toISOString().slice(0, 10)} o posterior`,
      beforeMax: (max) => `La fecha debe ser el ${max.toISOString().slice(0, 10)} o anterior`,
    },
  },
});

// Use the select prompt with translated content
const framework = await select({
  message: 'Selecciona un framework',
  options: [
    { value: 'next', label: 'Next.js', hint: 'Framework de React' },
    { value: 'astro', label: 'Astro', hint: 'Enfocado en contenido' },
    { value: 'svelte', label: 'SvelteKit', hint: 'Framework de compilación' },
  ]
});

// If the user cancels, they'll see the translated message
if (!framework) {
  cancel();
}
```

│
◆  Selecciona un framework
│  ● Next.js (Framework de React)
│  ○ Astro (Enfocado en contenido)
│  ○ SvelteKit (Framework de compilación)
└
└  Operación cancelada
 

### Stream

The `stream` utilities allow you, like the `log` utilities, to add semantic contextual information during an interaction,
except that the message contains an unknown number of lines.
Each function renders with specific styling to communicate status.

> **Tip:**
>
> These utilities are useful to print content of&#x20;
>
> [`node:stream`](https://nodejs.org/api/stream.html)
>
> ,
> like&#x20;
>
> [file stream](https://nodejs.org/api/fs.html#fscreatereadstreampath-options)

```ts
import { stream } from "@clack/prompts";
import * as fs from "node:fs";

await stream.message(fs.createReadStream('./banner.txt', { encoding: 'utf-8' }));
await stream.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 stream.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

### limitOptions

Trims an option list to what fits the terminal, while keeping the active option (cursor) visible using a Clack style sliding window. Returns the lines to render.

```ts
import { limitOptions } from '@clack/prompts';
import { styleText } from 'node:util';

const options = ['apple', 'banana', 'cherry', 'date'];
const lines = limitOptions({
  options,
  cursor: 2,
  maxItems: 8,
  style: (opt, active) =>
    active ? styleText('cyan', opt) : styleText('dim', opt),
});
```

Options:

* `options`: The list of options to display.
* `cursor`: The index of the currently active/selected option.
* `style`: A function that styles the given option string. The `active` parameter indicates whether the option is currently selected.
* `maxItems`: Maximum number of options to display at once (default: `Infinity`).
* `columnPadding`: Number of columns to reserve for padding (default: `0`).
* `rowPadding`: Number of rows to reserve for padding (default: `0`).
* All [Common Options](#common-options)
