How do I implement a command line tool?
Tags: cli, fcheat, npm, typescript
Published: 2020-01-04 19:32:04

After the new year has started a few days ago and I've been planning to blog myself again for a while now, I finally want to tackle this.

Let's start with one of my last small private projects: [fcheat](https://github.com/urbanisierung/fcheat).

![fcheat](https://thepracticaldev.s3.amazonaws.com/i/olb1iqry7ynw70vkk37e.gif)

TL;DR: I use [i3](https://i3wm.org/) as my window manager (which is the best window manager around, in my opinion). But that also means that I use the console intensively. My problem is that the syntax for commands that I don't use all the time need to be googled over and over again. That's not a problem in itself, since you can find the right result super fast on the internet if you know exactly what you need. Nevertheless I wanted to optimize this. My requirements for it:

1. command line tool that can be easily installed globally
2. the possibility to add own commands easily
3. simply import existing cheats and keep them up to date

Tools like [tldr](https://tldr.sh/) or man pages are already very helpful, but they do not meet all my requirements. So I implemented one for myself. I am very impressed of [fkill](https://github.com/sindresorhus/fkill-cli), which is a better version of kill, with some extensions that make life easier for the user. I was inspired by that.

In the end, there are no more than 5 steps necessary for the implementation:

- The WHAT: Define MVP
- The HOW: Select technology stack
- Implement core logic and CLI interface
- Provide first cheatsheets
- Publish

I am a big fan of separation of concerns - the WHAT and HOW are two very different disciplines that require different skills (I could write another blog post about this).

## Define MVP

I'm a software engineer, so I expect a direction in which a product should be developed, and then I decide how the product will be implemented. In this case I am also the product owner.

Since I want to solve a personal problem it is relatively simple. I am the target group, so I decide what is the minimum that needs to be implemented before the product can be shipped. My requirements are clear, tasks can be derived from this:

- Command line tool that can be used globally
- Simple search for commands
- Easy extensibility of commands

## Select technology stack

In this area developers feel much more comfortable ;) Since I've been mostly in the `node` universe lately and `npm` is a widely used package manager available on Linux, MacOS and Windows systems, the decision was quite easy for me:

- The logic is implemented in TypeScript and Node.
- The tool will be released on npmjs.
- The project is hosted as an open source project at GitHub.

## Implement core logic and CLI interface

I don't want to go too deep into details, the project can be viewed at GitHub. There are a few things I want to highlight though, as I'm sure you'll find them interesting:

[inquirer-autocomplete-prompt](https://www.npmjs.com/package/inquirer-autocomplete-prompt) is a very simple and nice input library that is well configurable. It allows you to search for an entry in an array and have it output to the terminal without any custom development.

Every command line tool has a version number, a help, can process parameters or flags if necessary. Nowadays nobody has to implement this himself. [meow](https://www.npmjs.com/package/meow) gives us a basic framework that only needs to be filled up.

## Provide first cheatsheets

This is necessary so that a user can use the tool immediately: no one wants to install a tool and then has to specify long configurations that are needed to use the tool. I personally need `kubectl` commands again and again, whose syntax I have to look up (unfortunately too often). 
Furthermore there are some `zsh git` shortcuts for which I have to look into the cheatsheet from time to time. So I've prepared something for them. As a bonus there are `gitmojis` ;)

## Publish

There is not much to tell about this point: an [npmjs](https://www.npmjs.com/) account is quickly set up, customize the project accordingly and run `npm publish`.

## What do I get out of it now?

I personally have made my life a little bit easier. I now get commands much faster that I can't remember. If there is another command that seems useful but is not used very often, I can simply add it to the list and that's it.

I also have a simple blueprint that I can use to write more tools if I need them. And maybe it helps the one or other reader too ;)