Command-line tools are essential in software development — they automate repetitive tasks, simplify workflows, and offer fast interaction without the overhead of a full GUI. While shell scripts or Python are common for quick utilities, building CLI tools with Node.js can be incredibly efficient, especially for JavaScript developers. In this post, I’ll walk through how I created a simple, customizable CLI file renaming tool using Node.js and Commander.js — and why I’d recommend this stack for your next CLI project.
Why Node.js for a CLI Tool?
Node.js is a great choice for building CLI tools, particularly when:
- You’re already working in a JavaScript/TypeScript stack.
- You want cross-platform compatibility.
- You want to publish and distribute via NPM.
- You need asynchronous I/O and filesystem operations.
Node’s built-in fs module and process API make it easy to interact with the file system and command-line inputs, and tools like Commander.js make argument parsing trivial.
Introducing Commander.js & Node.js
Commander.js is a minimal yet powerful Node library for parsing command-line options. It abstracts away the manual parsing of process.argv, provides helpful –help messages, and supports subcommands, default values, and flag aliases.
Example:
mytool rename –source ./files –prefix “sample_” –lowercase
The CLI Tool: What It Does
I created a CLI utility that:
- Accepts a source folder path.
- Renames all files by adding a prefix or suffix.
- Offers optional flags:
–lowercase: Converts all filenames to lowercase.
–remove-spaces: Replaces spaces with underscores.
–suffix: Adds a suffix instead of a prefix.
It’s simple but effective for automating bulk file renaming tasks.
Key Implementation Details
- Project Setup
npm init -y
npm install commander
Create a cli.js file with a shebang:

!/usr/bin/env node – Node.js
This makes your script executable when installed globally.
- Argument Handling with Commander
const { program } = require(‘commander’);
program
.name(‘file-rename’)
.description(‘Batch rename files with prefix, suffix, and formatting options’)
.version(‘1.0.0’);
program
.command(‘rename’)
requiredOption (‘-s, –source ‘, ‘Source directory path’)
.option(‘-p, –prefix ‘, ‘Prefix to add to file names’)
.option(‘–suffix ‘, ‘Suffix to add to file names’)
.option(‘–lowercase’, ‘Convert filenames to lowercase’)
.option(‘–remove-spaces’, ‘Replace spaces with underscores’)
.action((options) => {
// core logic
});
program.parse(process.argv);
- File Renaming Logic
const fs = require(‘fs’).promises;
const path = require(‘path’);
async function renameFiles(options) {
const files = await fs.readdir(options.source);
for (const file of files) {
let newName = file;
if (options.lowercase) {
newName = newName.toLowerCase();
}
if (options.removeSpaces) {
newName = newName.replace(/\s+/g, ‘_’);
}
if (options.prefix) {
newName = `${options.prefix}${newName}`;
}
if (options.suffix) {
const ext = path.extname(newName);
const base = path.basename(newName, ext);
newName = `${base}${options.suffix}${ext}`;
}
await fs.rename(
path.join(options.source, file),
path.join(options.source, newName)
);
console.log(‘Renaming completed.’);
}
Common Pitfalls and Fixes
- __dirname vs process.cwd():
Use __dirname for script-relative paths.
Use process.cwd() to work relative to where the command is run. - Async/Await Errors:
Forgetting await can cause inconsistent renaming or file access issues. - Exit Codes:
Always exit with process.exit(0) on success and process.exit(1) on errors to ensure CI/CD compatibility.
Benefits of This Setup
- Cross-Platform: Works on Linux, macOS, and Windows.
- Distributable: Easily publishable on NPM.
- Scalable: You can extend the tool with subcommands or additional processing logic.
- User-Friendly: Commander automatically generates –help and validates inputs.
Final Thoughts
Building a CLI tool with Node.js and Commander.js is an excellent way to automate tasks and learn more about Node’s process and filesystem modules. It’s surprisingly fast to prototype, and the barrier to entry is low if you’re already familiar with JavaScript.
Even a small utility like a file renamer can save hours of repetitive work and serve as the foundation for more advanced developer tooling in the future.
TL;DR
- Tech Stack: Node.js + Commander.js
- Use Case: Batch renaming files with formatting options
- Why It Works: Clean CLI API, async support, easily shareable via NPM
- Pro Tip: Always validate user input and handle edge cases like permission errors or empty folders
Let me know if you’d like the full working codebase or instructions to publish it on NPM.
Read more posts:- React-Based Emotion Detection: A Real-Time App Using Affectiva