Are you developing a little CLI tool in Node.js and want to be able to prompt users to enter input from the command line? Node.js provides the readline module precisely for this purpose. It offers an interface for reading data from a readable stream such as process.stdin, one line at a time.

Here is a simple example that prompts the user to input their name and nationality and then print these details on the console:

const readline = require('readline')

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

// ask the user for the name input
rl.question(`What's your name? `, name => {
  // ask for nationality
  rl.question(`What are you from? `, country => {
    // log user details
    console.log(`${name} is from ${country}`)

    // close the stream
    rl.close()
  })
})

In the above example, the readline.createInterface() method is used to create an instance of readline by defining readable and writable streams.

The rl.question() method displays the query (the question) and waits for the user to enter an answer. Once the input data is available, it calls the callback method passing the user's input as the first parameter.

Finally, we call the rl.close() method in the final callback to close the readline interface. You can also listen to the close event invoked when the stream is closed. It can be useful to do some post questions work:

// listen for close event
rl.on('close', () => {
  console.log('Goodbye 👋')

  // exit the process
  process.exit(0)
})

Read the readline documentation to learn more about all the available methods and events.

3rd-Party Modules

The readline module is a low-level Node.js package that you might think is too complicated for complex use cases. If you want a higher-level interface for handling user input, just use the prompt module from the Node Package Manager (NPM). You can add it to your project by executing the following command:

$ npm install prompt --save

It is relatively easy to use prompt than the readline module. You don't need to explicitly configure readable and writable streams.

Let us rewrite the above example by using the prompt module:

const prompt = require('prompt')

// start the prompt
prompt.start()

// ask the user for the input
prompt.get(['name', 'country'], (err, result) => {
  if (err) {
    throw err
  }

  // print user details
  console.log(`${result.name} is from ${result.country}`)
})

Handling Passwords

The prompt module makes it easier to securely ask the user to input a password. It will mask the input instead of showing the actual characters of the password:

const prompt = require('prompt')

// start the prompt
prompt.start()

// define properties schema
var schema = {
  properties: {
    name: {
      pattern: /^[a-zA-Z\s\-]+$/,
      message: 'Name must be only letters, spaces, or dashes',
      required: true
    },
    password: {
      hidden: true
    }
  }
}

// ask the user for the input
prompt.get(schema, (err, result) => {
  if (err) {
    throw err
  }

  // print user credentials
  console.log(`${result.name} / ${result.password}`)
})

Notice the pattern attribute in the above example. It ensures that the input, we receive from the user for the name property, is validated before moving to the next property input.

Adding Properties to an Object

The prompt module exposes another convenient method called addProperties() to extend an existing object by adding properties data from the command line:

const prompt = require('prompt')

// start the prompt
prompt.start()

// create an object
const user = {
  name: 'John Doe',
  country: 'USA'
}

// extend `user` object
prompt.addProperties(user, ['email', 'age'], err => {
  if (err) {
    throw err
  }

  // print modified object
  console.dir(user)
})

Now, if you run the above program, you should see an output similar to the following:

$ node index.js
prompt: email:  john.doe@example.com
prompt: age:  23
{ name: 'John Doe',
  country: 'USA',
  email: 'john.doe@example.com',
  age: '23' }

As you can see above, prompt is highly customizable. Check out the official documentation for more information. prompt can be a good choice if you are planning to build a solid CLI tool in Node.js.

✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.