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

OptionTypeDefaultDescription
inputStreamprocess.stdinThe readable stream to read from
outputStreamprocess.stdoutThe writable stream to write to
terminalbooleanfalseWhether to treat input/output as a TTY
promptstring> The prompt string
crlfDelaynumber100Delay between CR and LF detection
removeHistoryDuplicatesbooleanfalseRemove 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

MethodDescription
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();

See Also

  • Fs:: — File system operations
  • Process:: — Process information and control
  • Events:: — Event-driven architecture