๐ป Day 2 โ Build a Real CLI Interface
14 min readยทJan 1, 2026
Welcome to Day 2.
In yesterday's lesson, you built the foundation of the lb_notes command and made --help work from your terminal.
In today's lesson, you'll add the first two features of LBNotes: adding a note and listing notes.
You'll learn how CLI commands are structured, how input is validated, and how to produce clear error messages when the command is used incorrectly.
By the end of this lesson, you'll be able to run lb_notes add "..." and lb_notes list and see the expected behavior.
Implement a fake add() function
Within the src/cli/commands directory, let's create a new file named add.js.
~/projects/
โโ lb_notes/
โโ bin/
โโ package.json
โโ src/
โโ cli/
โโ commands/
โ โโ add.js
โ โโ help.js
โโ index.js
โโ parse_args.js
Within this file, let's export the following placeholder function used to check if the provided note is valid (i.e. a non-empty string) and output a fake validation message, or throw an error otherwise.
export default function add(note) {
note = note?.trim();
if (!note || !note.length) {
throw new Error('Invalid note');
}
console.log('Note saved!');
}
Where:
noteis a string of characters that represents a simple note (e.g.,"Get a carton of 12 eggs").
Implement a fake list() function
Within the src/cli/commands directory, let's create a new file named list.js.
~/projects/
โโ lb_notes/
โโ bin/
โโ package.json
โโ src/
โโ cli/
โโ commands/
โ โโ add.js
โ โโ help.js
โ โโ list.js
โโ index.js
โโ parse_args.js
Within this file, let's export the following placeholder function used to output a fake list of notes.
export default function list() {
console.log([
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
'Vivamus vel odio blandit, pretium leo et, pretium nibh.'
]);
}
Parse the add and list commands
Within the parseArgs() function, let's add a new conditional statement that checks if the first element of the args array equals to the "add" string, and return an object that contains the add command and the list of remaining command-line arguments, concatenated as a single string.
export default function parseArgs(args) {
if (!args || !args.length || args[0] === '-h' || args[0] === '--help') {
return {
command: 'help'
};
}
else if (args[0] === 'add') {
return {
command: 'add',
value: args.slice(1).join(' ')
};
}
throw new Error(`${args[0]}: Unknown command`);
}
Then, let's add another conditional statement that checks if the first element of the args array equals to the "list" string, and return an object that contains the list command.
export default function parseArgs(args) {
if (!args || !args.length || args[0] === '-h' || args[0] === '--help') {
return {
command: 'help'
};
}
else if (args[0] === 'add') {
return {
command: 'add',
value: args.slice(1).join(' ')
};
}
else if (args[0] === 'list') {
return {
command: 'list'
};
}
throw new Error(`${args[0]}: Unknown command`);
}
Execute the add and list commands
Within the run() function, let's import the add.js and list.js modules from the commands directory, and execute the add() and list() functions exported by these modules based on the command property of the object returned by the parseArgs() function.
import parseArgs from './parse_args.js';
import help from './commands/help.js';
import add from './commands/add.js';
import list from './commands/list.js';
export default function run(args) {
try {
const { command, value } = parseArgs(args);
if (command === 'help') {
help();
}
else if (command === 'add') {
add(value);
}
else if (command === 'list') {
list();
}
} catch(error) {
console.error(`lb_notes: error: ${error.message}`);
return 1;
}
return 0;
}
โ ๏ธ Don't forget to execute the
add()function with thevalueproperty returned by theparseArgs()function.
Update the help command
Now that our implementation is complete, let's not forget to update the help() function to document the changes made to the CLI.
export default function help() {
console.log(`NAME
LBNotes โ a tiny CLI notes tool
SYNOPSIS
lb_notes [-h|--help]
Output this help menu.
lb_notes add string ...
Concatenate and add the specified strings to the list of notes.
lb_notes list
Output the list of notes.`);
}
Test the CLI
Let's now make sure that everything works as expected.
Test the --help flag
When running the lb_notes command with the --help flag, it should output the help menu.
~/projects/lb_notes$ lb_notes --help
Test the add command
When running the lb_notes command with the add command and no arguments, it should output an error.
~/projects/lb_notes$ lb_notes add
lb_notes: error: Invalid note
When running the lb_notes command with the add command and an empty string as argument, it should output an error.
~/projects/lb_notes$ lb_notes add ""
lb_notes: error: Invalid note
When running the lb_notes command with the add command and a valid string as argument, it should output "Note saved!".
~/projects/lb_notes$ lb_notes add "Get a carton of eggs"
Note saved!
Test the list command
When running the lb_notes command with the list command, it should output a list of notes.
~/projects/lb_notes$ lb_notes list
[
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
'Vivamus vel odio blandit, pretium leo et, pretium nibh.'
]
You're done for today โ