# How to Run Node.js Readline Functions: A Complete Guide to Interactive CLI Input

> Master Node.js readline functions for interactive CLI input. Learn to create interfaces, handle line events, and use question methods effectively in this comprehensive guide.

- Repository: [Node.js/node](https://github.com/nodejs/node)
- Tags: tutorial
- Published: 2026-02-15

---

**You run Node.js readline functions by requiring the `readline` core module, creating an interface with `readline.createInterface()` pointing to `process.stdin` and `process.stdout`, then listening for `'line'` events or using methods like `question()` to handle user input.**

The Node.js `readline` module provides a powerful way to handle streaming input line-by-line, making it essential for building interactive command-line tools. Whether you're prompting users for configuration details or processing large log files, understanding how to run **nodejs readline functions** unlocks robust stream processing capabilities. According to the Node.js source code, the implementation resides in [`lib/readline.js`](https://github.com/nodejs/node/blob/main/lib/readline.js) and exposes an `Interface` class that manages input/output streams, line buffering using `StringDecoder`, and event emission.

## Creating a Readline Interface

### Basic Setup with process.stdin

To start using readline functions, you must create an interface instance that binds input and output streams. The `readline.createInterface()` method accepts an options object specifying `input` (a readable stream) and `output` (a writable stream).

```javascript
const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

```

### Configuration Options

The `createInterface` method supports several critical options defined in [`lib/readline.js`](https://github.com/nodejs/node/blob/main/lib/readline.js):

- **crlfDelay**: Specifies the maximum delay between `\r` and `\n` to treat them as a single newline (useful for Windows-style line endings)
- **terminal**: Boolean indicating whether the output should be treated as a TTY (set to `false` when reading from files)
- **prompt**: The prompt string to use (defaults to `"> "`)

## Core Readline Functions and Methods

### Handling Line-by-Line Input with Events

The Interface instance emits a `'line'` event whenever the input stream receives a newline. This is the fundamental mechanism for processing user input incrementally.

```javascript
rl.on('line', (line) => {
  console.log(`Received: ${line}`);
  if (line === 'exit') {
    rl.close();
  }
});

rl.on('close', () => {
  console.log('Interface closed');
  process.exit(0);
});

```

### Prompting Users with question()

The `question()` method provides a convenient way to ask a single question and receive the answer through a callback. According to the source in [`lib/readline.js`](https://github.com/nodejs/node/blob/main/lib/readline.js), this method writes the query to the output stream, then waits for the next `'line'` event.

```javascript
rl.question('What is your favorite programming language? ', (answer) => {
  console.log(`You chose: ${answer}`);
  rl.close();
});

```

### Writing Output and Prompts

- **prompt()**: Redisplays the current prompt without waiting for input
- **write()**: Writes arbitrary text to the output stream without affecting the prompt line

```javascript
rl.write('Loading configuration...\n');
rl.prompt();

```

## Modern Async Patterns

### Using Async Iterators (Node.js v10+)

Since Node.js v10, the readline Interface implements `[Symbol.asyncIterator]`, allowing you to process lines using `for await...of` loops. This pattern, benchmarked in [`benchmark/readline/readline-iterable.js`](https://github.com/nodejs/node/blob/main/benchmark/readline/readline-iterable.js), provides cleaner syntax for asynchronous input handling.

```javascript
const rl = require('readline').createInterface({
  input: process.stdin,
  crlfDelay: Infinity
});

(async () => {
  for await (const line of rl) {
    console.log(`> ${line}`);
    if (line === 'quit') break;
  }
})();

```

## Processing File Streams

When reading from files instead of interactive terminals, set `terminal: false` to disable prompt handling and TTY-specific behaviors. The test file [`test/pseudo-tty/readline-dumb-tty.js`](https://github.com/nodejs/node/blob/main/test/pseudo-tty/readline-dumb-tty.js) demonstrates handling minimal terminal capabilities.

```javascript
const fs = require('fs');
const readline = require('readline');

const fileStream = fs.createReadStream('data.txt');
const rl = readline.createInterface({
  input: fileStream,
  output: process.stdout,
  terminal: false
});

rl.on('line', (line) => {
  console.log(`File line: ${line}`);
});

```

## Summary

- **Create an interface** using `readline.createInterface()` with `input` and `output` streams, typically `process.stdin` and `process.stdout`.
- **Process input** by listening for `'line'` events or using the `question()` method for single prompts.
- **Use async iterators** (`for await...of`) for modern, promise-based line processing available in Node.js v10 and later.
- **Handle files** by setting `terminal: false` and passing a file stream to the `input` option.
- **Clean up** by calling `rl.close()` to remove listeners and restore terminal state.

## Frequently Asked Questions

### What is the difference between readline and readFile for reading lines?

`readline` processes streams line-by-line in real-time with minimal memory usage, making it ideal for large files or interactive input. `fs.readFile` loads the entire file into memory as a buffer or string, which is inefficient for large datasets but simpler for small configuration files.

### How do I handle Ctrl+C (SIGINT) in a readline interface?

The readline interface automatically handles `Ctrl+C` by emitting a `'SIGINT'` event if the input is a TTY. Listen for this event to perform cleanup or exit gracefully: `rl.on('SIGINT', () => { rl.close(); process.exit(0); });`.

### Can I use readline with promises instead of callbacks?

Yes. Since Node.js v10, you can use the async iterator protocol (`for await...of`) to process lines as promises. For the `question()` method specifically, you can promisify it using `util.promisify` or wrap it in a Promise constructor to avoid callback-based code.

### Why does my readline script hang after processing all lines?

This typically happens because the input stream (like `process.stdin`) remains open waiting for more data. Always call `rl.close()` when finished, or ensure the input stream ends (e.g., via EOF/`Ctrl+D`). For file streams, the interface automatically closes when the file ends, but for stdin, you must explicitly close or exit the process.