Following my previous blog post 5 Cli Tools That Will Increase Your Dev Velocity And Code Quality I wrote a quick guide on how to write and publish a CLI.
What’s in it for you?
- Write a cool as f*** CLI tool.
- Learn how to set up a project using Typescript.
- Publish your new shiny CLI to npm.
We will use Scaffolder to generate all the boilerplate we need for our shiny CLI.
Scaffolder makes creating and sharing boilerplate code a breeze, Check it out!
npm has finished installing all of our dependencies, we should have a clean, greenfield project.
Let’s have a quick look at the
First of all, as you can see we got a postfix to our
name field, I added this to prevent naming conflicts with existing packages 😄
Second, we got a
bin field tells npm that this package has an executable that should be invoked using the
Finally, we have
commander as a dependency. We are going to use it to register commands for our cli to act on.
In a gist commander makes creating CLI’s a breeze
Now Let’s quickly go over the
./dist/cli.js in the
bin field. We can do that because we tell typescript to compile our code into a
If you want to learn more about Typescript or tsconfig.json, I recommend this free book.
We are finally done going over our boilerplate. Let’s get down to business.
We are going to write a simple CLI that does the following:
- Go over all the files in a directory and get their extension.
- Create a folder for each type of file extension.
- Move all the files to their matching folders.
0.5. Some imports for later
1. Go over all the files in a directory and get their extension.
2. Create a folder for each type of file extension.
If the folder already exists, then skip its creation to avoid errors.
3. Move all the files to their matching folders.
Putting it all together
We are going to put all of this logic inside a file named
We got all of our logic in working condition. Now, let’s wire this thing up.
What will be a reasonable workflow for this CLI? Let’s write it up as a user story.
1. As a user, I want to type
coolGroup in my cli and have all files in my current working directory grouped.
By importing our
groupFilesByExtensions function into
We add a shebang(
#!/usr/bin/env node) to specify the script interpreter that’s used to execute our code.
Let’s introduce another requirement and see we can adjust to it.
2. As a user, I to be able to specify the folder
coolGroup will work on.
coolGroup --entry-point ./group/this/folder
cli.ts file to accommodate this change
Now our users can specify a path to the folder they want to group.
As a bonus, we get a nice help section out of the box!
npm run buildand then
node ./dist/cli.jsto see it in action locally (or use npm link)
Share it with the world!
We got a cool working CLI but it only exists on our local machine.
Let’s share this brilliant creation with the world by publishing it to npm.
Before moving to the next section, if you don’t have an npm user follow this guide to create one and set up the credentials.
To publish our package all we need is to run
npm publish and you should be good to go!
For a more polished publish flow check np out.
If everything went well you should see something like this.
check it out by running
npx <your-module-name-here> inside whatever folder you like.
woohoo, we are all done.