readline module
Added in vnodejs · Updated March 13, 2026 · Node.js Modules
javascript nodejs readline streams cli
The readline module provides an interface for reading data from a readable stream one line at a time. It is essential for building interactive command-line interfaces (CLIs) in Node.js.
Installation
The readline module is a built-in Node.js module. No installation is required:
const readline = require('readline');
Creating an Interface
The primary function is readline.createInterface(), which creates an interface for reading from streams:
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
Options
| Option | Type | Default | Description |
|---|---|---|---|
input | Stream | process.stdin | The readable stream to read from |
output | Stream | process.stdout | The writable stream to write to |
terminal | boolean | false | Whether to treat input/output as a TTY |
prompt | string | > | The prompt string |
crlfDelay | number | 100 | Delay between CR and LF detection |
removeHistoryDuplicates | boolean | false | Remove duplicates from history |
Reading Input
The question Method
The simplest way to get input:
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('What is your name? ', (answer) => {
console.log(`Hello, ${answer}!`);
rl.close();
});
The line Event
For continuous line-by-line reading, use the line event:
const readline = require('readline');
const fs = require('fs');
const rl = readline.createInterface({
input: fs.createReadStream('file.txt'),
crlfDelay: Infinity
});
rl.on('line', (line) => {
console.log(`Line: ${line}`);
});
rl.on('close', () => {
console.log('File reading complete');
});
Interface Methods
| Method | Description |
|---|---|
rl.question(query, callback) | Prompts the user with a question |
rl.pause() | Pauses the input stream |
rl.resume() | Resumes the input stream |
rl.close() | Closes the interface |
rl.write(data) | Writes to the output |
rl.setPrompt(prompt) | Sets the prompt string |
rl.prompt() | Writes the prompt to the output |
Events
The readline interface emits several events.
line Event
Emitted whenever the input stream receives a line break:
rl.on('line', (line) => {
console.log(`Received: ${line}`);
});
close Event
Emitted when the interface is closed:
rl.on('close', () => {
console.log('Interface closed');
});
pause and resume Events
rl.on('pause', () => {
console.log('Readline paused');
});
rl.on('resume', () => {
console.log('Readline resumed');
});
Signal Events
The interface emits signals similar to terminal signals:
// Handle Ctrl+C
rl.on('SIGINT', () => {
rl.question('Are you sure you want to exit? ', (answer) => {
if (answer.match(/^y(es)?$/i)) {
rl.close();
}
});
});
// Handle process resume (after Ctrl+Z suspend)
rl.on('SIGCONT', () => {
console.log('Suspended');
});
Practical Example
Here is a complete example of an interactive CLI:
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true
});
const tasks = [Global_Objects::eval];
function showMenu() {
console.log('\n--- Task Manager ---');
console.log('1. Add task');
console.log('2. List tasks');
console.log('3. Quit');
rl.question('Choose an option: ', handleInput);
}
function handleInput(choice) {
switch (choice.trim()) {
case '1':
rl.question('Enter task: ', (task) => {
tasks.push(task);
console.log(`Added: ${task}`);
showMenu();
});
break;
case '2':
console.log('\nYour tasks:');
tasks.forEach((t, i) => console.log(`${i + 1}. ${t}`));
showMenu();
break;
case '3':
console.log('Goodbye!');
rl.close();
break;
default:
console.log('Invalid option');
showMenu();
}
}
rl.on('close', () => {
process.exit(0);
});
showMenu();
Using readline with Async/Await
For cleaner code, wrap readline in a promise:
const readline = require('readline');
function createInterface(options) {
const rl = readline.createInterface(options);
return {
rl,
question: (query) => new Promise((resolve) => {
rl.question(query, resolve);
})
};
}
async function main() {
const { rl, question } = createInterface({
input: process.stdin,
output: process.stdout
});
const name = await question('What is your name? ');
const age = await question('How old are you? ');
console.log(`Hello, ${name}! You are ${age} years old.`);
rl.close();
}
main();