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 user for the anme 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 that is 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);
    
});

Take a look at 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 the 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 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 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 makes sure that the input we receive from the user for the name property is properly 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 very good choice if you are planning to build a solid CLI tool in Node.js.

✌️ Like this article? Follow @attacomsian on Twitter. You can also follow me on LinkedIn and DEV. Subscribe to RSS Feed.

👋 If you enjoy reading my articles and want to support me to continue creating free tutorials, Buy me a coffee (cost $5) .

Need help to launch a new product? I am available for contract work. Hire me to accomplish your business goals with engineering and design.