@cli-prompts/multiline
v1.0.0
Published
A production-ready multiline text prompt for Node.js CLIs. Flicker-free, smooth, and supports full cursor movement with rich ANSI rendering. Built to fill the gap the other great libraries never covered.
Maintainers
Readme
@cli-prompts/multiline
A modern, flicker-free, feature-rich multiline text input for your command-line applications.
Have you ever been frustrated that inquirer and other great libraries are missing a proper, smooth multiline text input? This package solves that. It's a standalone component designed from the ground up to provide a first-class "textarea" experience in the terminal.

✨ Features
- True Multiline Editing: A native-like textarea experience in the terminal.
- Intuitive Key-bindings:
Enterto submit,Shift+Enterfor newlines. - Advanced Editing: Word-wise navigation (
Ctrl+Left/Right) and deletion (Alt+Backspace,Ctrl+W). - Robust Paste Support: Reliably paste multi-line text without accidentally submitting.
- Rich Feature Set: Supports placeholders, default values, validation, and max length.
- Animated Spinners: Optional loading spinner for a dynamic feel.
- Deeply Customizable: Change prefixes, colors, and more with a simple style object.
- Flicker-Free: Built with a smart, atomic render loop.
- Lightweight & Modern: Zero runtime dependencies, written in TypeScript.
- Battle-Tested: High unit test coverage.
📦 Installation
# pnpm
pnpm add @cli-prompts/multiline
# npm
npm install @cli-prompts/multiline
# yarn
yarn add @cli-prompts/multiline
# bun
bun add @cli-prompts/multiline🚀 Usage
import { multiline, AbortError } from '@cli-prompts/multiline';
async function main() {
try {
const description = await multiline({
prompt: 'Please enter your project description:',
placeholder: 'My project is about...\nIt does really cool things!',
});
console.log('\nYour description:\n ', description);
} catch (error) {
if (error instanceof AbortError) {
// The user aborted the prompt (Ctrl+C).
// The component already printed a cancellation message.
} else {
console.error('An unexpected error occurred:', error);
}
}
}
main();⚙️ API & Options
The multiline function accepts a string for a simple prompt, or an options object for full configuration.
multiline(options: MultilineOptions): Promise<string>
| Option | Type | Default | Description |
| ------------- | -------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------- |
| prompt | string | Required | The main question to ask the user. |
| default | string | '' | A default value to pre-populate the input with. Supports \n for newlines. |
| placeholder | string | undefined | Placeholder text to show when the input is empty. Supports \n for newlines. |
| instruction | string \| boolean | true | A help message shown below the input. Set to false to hide, or a string to override. |
| required | boolean | false | If true, prevents submission if the input is empty or only whitespace. |
| validate | (value: string) => boolean \| string | undefined | A function to validate the input on submission. Return true if valid, or a string for an error message. |
| maxLength | number | undefined | The maximum number of characters allowed. Provides real-time feedback. |
| spinner | boolean | false | If true, replaces the ? prefix with an animated spinner. |
| style | object | {...} | An object to customize prefixes and colors. See "Styling" section below. |
🎨 Styling
You can customize the look and feel by passing a style object. You only need to provide the properties you want to override.
Example:
import chalk from 'chalk';
multiline({
prompt: 'Enter commit message',
style: {
prefixes: {
prompt: '🤔',
success: '✅',
},
colors: {
prompt: 'yellow', // Use a predefined color name
finalAnswer: str => chalk.italic.hex('#888')(str), // Or use a custom function
},
},
});Style Object Structure:
{
prefixes?: {
prompt?: string; // default: '?'
success?: string; // default: '✔'
error?: string; // default: '✖'
input?: string; // default: '›'
};
colors?: {
prompt?: ColorFn | ColorName; // default: 'cyan'
success?: ColorFn | ColorName; // default: 'green'
error?: ColorFn | ColorName; // default: 'red'
instruction?: ColorFn | ColorName; // default: 'gray'
placeholder?: ColorFn | ColorName; // default: 'gray'
finalAnswer?: ColorFn | ColorName; // default: 'cyan'
inputPrefix?: ColorFn | ColorName; // default: 'gray'
promptTitle?: ColorFn | ColorName; // default: 'bold'
};
}ColorName can be one of: 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'gray'. ColorFn is a function (str: string) => string.
⌨️ Key Bindings
| Key | Action |
| ----------------------------------- | ---------------------- |
| Enter | Submit the input |
| Shift + Enter / Alt + Enter | Insert a new line |
| Ctrl + C | Abort the prompt |
| Backspace | Delete character left |
| Delete | Delete character right |
| Alt + Backspace | Delete word left |
| Ctrl + W | Delete word left |
| Arrow Keys | Move cursor |
| Ctrl + Left | Move to previous word |
| Ctrl + Right | Move to next word |
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
