Skip to content

Core

The @clack/core package provides the fundamental building blocks for creating interactive command-line interfaces. It’s designed to be flexible, extensible, and easy to use.

  • Low-level primitives: Base components for building custom prompts
  • Type-safe: Built with TypeScript for better developer experience
  • Flexible rendering: Customizable rendering system for prompts
  • Cancel handling: Built-in support for handling user cancellation
  • Event system: Comprehensive event handling for user interactions
  • Input validation: Built-in support for input validation
  • Abort signal support: Integration with AbortController for cancellation
  • Custom I/O streams: Support for custom input/output streams
  • Configurable guide lines: Toggle the default Clack border with withGuide

To start using the core package, first install it:

Terminal window
npm install @clack/core

Then import the components you need:

import {
// Prompt classes
class TextPrompt
TextPrompt
,
class SelectPrompt<T extends { value: any; disabled?: boolean; }>
SelectPrompt
,
class ConfirmPrompt
ConfirmPrompt
,
class PasswordPrompt
PasswordPrompt
,
class MultiSelectPrompt<T extends OptionLike>
MultiSelectPrompt
,
class GroupMultiSelectPrompt<T extends { value: any; }>
GroupMultiSelectPrompt
,
class SelectKeyPrompt<T extends { value: string; }>
SelectKeyPrompt
,
class AutocompletePrompt<T extends OptionLike$1>
AutocompletePrompt
,
// Utilities
function isCancel(value: unknown): value is symbol
isCancel
,
function updateSettings(updates: ClackSettings): void
updateSettings
,
const settings: InternalClackSettings
settings
,
// Types
type
(alias) interface ClackSettings
import ClackSettings
ClackSettings
,
type
interface PromptOptions<TValue, Self extends Prompt<TValue>>
PromptOptions
,
type
(alias) interface ConfirmOptions
import ConfirmOptions
ConfirmOptions
,
type
(alias) interface PasswordOptions
import PasswordOptions
PasswordOptions
,
type
interface MultiSelectOptions<T extends OptionLike>
MultiSelectOptions
,
type
interface GroupMultiSelectOptions<T extends { value: any; }>
GroupMultiSelectOptions
,
type
interface SelectKeyOptions<T extends { value: string; }>
SelectKeyOptions
,
type
interface AutocompleteOptions<T extends OptionLike$1>
AutocompleteOptions
,
} from '@clack/core';

The package exports both the prompt classes and their corresponding options types (e.g., ConfirmOptions, PasswordOptions) for TypeScript users.

The core package is organized into two main directories:

  • prompts/: Contains the base prompt implementations
  • utils/: Contains utility functions and helpers

The Prompt class serves as the foundation for all prompt types. It provides:

  • Custom rendering capabilities
  • Input handling
  • State management
  • Event system
  • Validation support
  • Abort signal integration
interface Prompt {
// Event handling
on<T extends string>(event: T, cb: (value: any) => void): void;
once<T extends string>(event: T, cb: (value: any) => void): void;
emit<T extends string>(event: T, ...data: any[]): void;
// Core functionality
prompt(): Promise<string | symbol>;
close(): void;
}

The Prompt interface provides several events that can be handled:

import {
class Prompt<TValue>
Prompt
} from '@clack/core';
// Example usage
const
const p: Prompt<unknown>
p
= new
new Prompt<unknown>(options: PromptOptions<unknown, Prompt<unknown>>, trackValue?: boolean): Prompt<unknown>
Prompt
({
PromptOptions<unknown, Prompt<unknown>>.render(this: Omit<Prompt<unknown>, "prompt">): string | undefined
render
: () => 'Enter your name:'
});
// Handle value changes
const p: Prompt<unknown>
p
.
Prompt<unknown>.on<"value">(event: "value", cb: (value?: unknown) => void): void

Subscribe to an event

@paramevent - The event name

@paramcb - The callback

on
('value', (
value: string | undefined
value
?: string) => {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
('Value changed:',
value: string | undefined
value
);
});
// Handle submission
const p: Prompt<unknown>
p
.
Prompt<unknown>.on<"submit">(event: "submit", cb: (value?: any) => void): void

Subscribe to an event

@paramevent - The event name

@paramcb - The callback

on
('submit', (
value: string | undefined
value
?: string) => {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
('Submitted:',
value: string | undefined
value
);
});
// Handle cancellation
const p: Prompt<unknown>
p
.
Prompt<unknown>.on<"cancel">(event: "cancel", cb: (value?: any) => void): void

Subscribe to an event

@paramevent - The event name

@paramcb - The callback

on
('cancel', () => {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
('Operation cancelled');
});
  1. TextPrompt: For text input

    • Supports validation
    • Placeholder text
    • Initial value
    • Separate userInput and value tracking
  2. SelectPrompt: For selection from options

    • Custom rendering
    • Option filtering
    • Disabled options support
    • Text wrapping support
  3. ConfirmPrompt: For yes/no confirmations

    • Yes/No shortcuts
    • Custom messages
  4. AutocompletePrompt: For searchable selection

    • Type-ahead filtering
    • Custom filtering logic
    • Multiple selection support (multiple: true)
    • Dynamic options (function or array)
  5. PasswordPrompt: For secure input

    • Character masking
    • Validation support
    • clearOnError option to reset on validation failure
  6. MultiSelectPrompt: For multiple selections

    • Checkbox interface
    • Selection limits
    • Custom rendering
    • Disabled options support
    • Invert selection support
  7. GroupMultiSelectPrompt: For grouped selections

    • Hierarchical options
    • Group selection (selectableGroups option)
    • Custom rendering
    • Group spacing control
  8. SelectKeyPrompt: For key-based selection

    • Custom key bindings
    • Multiple selection support

The core package provides global settings that affect all prompts:

import {
function updateSettings(updates: ClackSettings): void
updateSettings
,
const settings: InternalClackSettings
settings
} from '@clack/core';
// Update global settings
function updateSettings(updates: ClackSettings): void
updateSettings
({
// Custom key aliases for navigation
ClackSettings.aliases?: Record<string, "up" | "down" | "left" | "right" | "space" | "enter" | "cancel">

Set custom global aliases for the default actions. This will not overwrite existing aliases, it will only add new ones!

@paramaliases - An object that maps aliases to actions

@default{ k: 'up', j: 'down', h: 'left', l: 'right', '\x03': 'cancel', 'escape': 'cancel' }

aliases
: {
w: "up"
w
: 'up',
a: "left"
a
: 'left',
s: "down"
s
: 'down',
d: "right"
d
: 'right',
},
// Disable guide lines globally
ClackSettings.withGuide?: boolean
withGuide
: false,
// Custom messages for i18n
ClackSettings.messages?: {
cancel?: string;
error?: string;
}

Custom messages for prompts

messages
: {
cancel?: string

Custom message to display when a spinner is cancelled

@default"Canceled"

cancel
: 'Operación cancelada',
error?: string

Custom message to display when a spinner encounters an error

@default"Something went wrong"

error
: 'Se produjo un error',
},
});
// Access current settings
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
(
const settings: InternalClackSettings
settings
.
InternalClackSettings.messages: {
cancel: string;
error: string;
}
messages
.
cancel: string
cancel
);

Default keybindings include Vim-style navigation:

KeyAction
kup
jdown
hleft
lright
Escapecancel

You can add custom aliases but cannot disable the default keybindings.

The withGuide setting controls the display of Clack’s signature border lines. Set to false to render prompts without the decorative guide.

You can create custom prompts by extending the base Prompt class:

import {
class Prompt<TValue>
Prompt
} from '@clack/core';
// Example of extending the base Prompt class
class
class CustomPrompt
CustomPrompt
extends
class Prompt<TValue>
Prompt
<string> {
constructor(
options: {
message: string;
}
options
: {
message: string
message
: string }) {
super({
...
options: {
message: string;
}
options
,
PromptOptions<string, Prompt<string>>.render(this: Omit<Prompt<string>, "prompt">): string | undefined
render
() {
return `${
options: {
message: string;
}
options
.
message: string
message
}\n${this.
value: string | undefined
value
?? ''}`;
}
});
}
}

For detailed examples and usage patterns, check out our examples guide.