CLI Flags in Practice + How to Make Your Own CLI Command with oclif
Tags: tutorial, productivity, node, bash
Published: 2019-05-09 17:23:28

---
title: CLI Flags in Practice + How to Make Your Own CLI Command with oclif
published: true
tags: tutorial, productivity, node, bash
canonical_url: https://blog.heroku.com/cli-flags-get-started-with-oclif
cover_image: https://thepracticaldev.s3.amazonaws.com/i/68snc186nbckp2brk7rq.png
description: The syntax of CLI commands plus how to create your own CLI with oclif
---

_Editor's note: If you like CLIs, you should check out [oclifconf](https://oclif.io/conf) taking place on Friday, May 31st, 2019 in San Francisco. It’s the first community get-together for oclif! Space is limited so let us know soon if you are interested in joining._

What is it that makes working from the command line so empowering? It can feel archaic at times, sure, but when you remember the right sequence of words, characters, and symbols for what you’re trying to do, it hits you with a sense of accomplishment and mastery over your tools that no graphical interface can compete with.

So what better way to continue your adventures as a developer than by developing your own CLI tool?

In this post, we’ll go over what type of parameters CLI commands take—also known as "flags", "arguments", and sometimes "options.” Then, we’ll start you off with [oclif](https://oclif.io/), the CLI framework that makes it easy to create new CLI commands!

## The Syntax of a CLI Command

Any command line interface command has a few standard "parts of speech.” As a user of CLI tools, knowing these parts of speech can help you make fewer typos. It can also help you understand complex commands other people share with you more quickly (like [these](https://www.commandlinefu.com/commands/browse)). If you are designing a CLI tool it is even more important to understand these parts of speech, so you can come up with the most ergonomic interface for your users. Yes, a CLI is a user interface!

Some of you may recognize diagrams like the one below from elementary or primary school. Fortunately, understanding how CLI commands are structured isn’t going to feel like this.

![sentence-diagram](https://heroku-blog-files.s3.amazonaws.com/posts/1557265553-sentence-diagram.png)

CLI commands are pretty straightforward compared to the typical English sentence.

For starters, let’s look at the parameters that appear to the right of CLI commands. Sure, there are many ways you can pass data to a CLI command, but these three types of parameters to the "right" of the command might be the most common: argument, long flag, and short flag. These two formats for flags are the standard for GNU-style flags. Not all CLIs follow this convention, but it has become the most popular style on Unix-like and POSIX compliant operating systems.

What better way for us to start than with the `ls` command? It’s one of the most common and simplest commands on Unix-like operating systems. It simply lists the contents of a directory.

### Command

```term
$ ls
```

This command, `ls`, works on its own, as a standalone command. Without any parameters, this command will list the contents of the current directory.

### Argument

```term
$ ls .
```

But you can do the same thing with an argument! Turns out that `ls .` and `ls` are the same thing, with `ls` simply using an implied `.` directory. For those that don’t remember or don’t know, `.` always refers to the current directory.

But now, the argument syntax makes it possible for you to pass any directory path to `ls`, and to get a look at what’s in there.

```term
$ ls /home/casey/code/some-repo-name
```

An argument is anything to the right of a command that is not a flag (we’ll get to flags next). And fortunately, an argument can come before or after flags–it can coexist with them happily.

### Long Flag

To list files that are normally hidden (like `~/.bashrc`), you can use a flag on the `ls` command. `ls --all` is the long flag form. A long flag always uses a double dash, and it is always represented by multiple characters.

```term
$ ls --all
$ ls . --all
```

### Short Flag

There is also a short flag form of this flag: `ls -a`. The `a` is short for `all` in this case. A short flag always uses a single dash, and it is always represented by a single letter.

```term
$ ls -a
$ ls . -a
```

Short flags can stack too, so you don't need a separate dash for each one. Order does not matter for these, unless passing a _flag argument_.

```term
$ ls -la
```

### Flag Argument

Many flags accept an option called a "flag argument" (not to be confused with a "command argument"). In general a command's parameters can be in any order, but flags that accept options must have the option directly after the flag. That way, the command doesn’t get confused by non-flag arguments.

For an example, here the `-x` flag does not accept an option but the `-f` flag does. `archive.tar` is the option being passed to `-f`. Both of these are valid.

```term
$ tar -x -f archive.tar
$ tar -xf archive.tar
```

A flag and its option can be separated by a space or an equals sign `=`. Interestingly, short flags (but not long flags) can even skip the space, although many people find it much easier to read with the space or equals sign.These three are all valid and equivalent.

```term
$ tar -f archive.tar
$ tar -f=archive.tar
$ tar -farchive.tar
```

Long flags must have a space or equals sign to separate the flag from its option.

```term
$ git log --pretty=oneline
$ git log --pretty oneline
```

### Other Ways of Passing Data

We've covered parameters, which are arguments, long flags, and short flags. There are two other ways to pass data to a command: [environment variables ("env vars")](https://en.wikipedia.org/wiki/Environment_variable), or [standard input ("stdin")](https://en.wikipedia.org/wiki/Standard_streams#Standard_input_(stdin)). These won't be covered in this blog post, but check out the links to learn more about them.

## Building a New Command With `oclif`

Scenario: we want to design an oclif command that takes an input like "Casey", and returns "hi, Casey!". There are many ways the user could pass this in. Here we show an example of each type of input using an argument, a long flag, and a short flag.

First, let’s get started with `oclif`. Getting a CLI app going is very, very straightforward with it. Open up your terminal and type the following, which will use `npx` to run `oclif` and then create a new CLI. `npx` is a pretty useful command to [simplify running CLI tools and other executables hosted on the npm registry](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b).

```term
$ npx oclif single greet-me
```

We won’t go into the details of the `single` (vs `multi`) argument above. Check out the [oclif documentation](https://oclif.io/docs/introduction.html#single-command-or-multi-command) for more about this.

Now, you’ll get the chance to specify some details of your new CLI, including the command name. When it asks you, just press enter, choosing the deafult. It’ll take the `greet-me` argument you passed into the above command. You can choose the default for most of the questions it asks you. The answers won't make much of a difference for this simple tutorial. However, they are very important to answer accurately if you will be sharing your CLI command with others.

```term
? npm package name: greet-me
? command bin name the CLI will export: greet-me

...

Created greet-me in /home/casey/code/greet-me
```

Now that we have things set up, let’s check out what’s happening in `/greet-me/src/index.ts`, where all the important argument and flag-handling code for your CLI will live.

```javascript
const {Command, flags} = require('@oclif/command')

class GreetMeCommand extends Command {
  async run() {
    const {flags} = this.parse(GreetMeCommand)
    const name = flags.name || 'world'
    this.log(`hello ${name} from ./src/index.js`)
  }
}

GreetMeCommand.description = `Describe the command here
...
Extra documentation goes here
`

GreetMeCommand.flags = {
  // add --version flag to show CLI version
  version: flags.version({char: 'v'}),
  // add --help flag to show CLI version
  help: flags.help({char: 'h'}),
  name: flags.string({char: 'n', description: 'name to print'}),
  // flag with no value (-f, --force)
  force: flags.boolean({char: 'f'}),
}

module.exports = GreetMeCommand
```

What we can see here is that it accepts a few different flag names out the gate (`version`, `name`, `help`, and `force`) by registering them in the `flags` object.

```javascript
{
    /* … */
    version: flags.version({char: 'v'}),
    /* … */
}
```

Here, with the `version` flag, the key acts as the ‘version’ long flag name, and on the right side of the expression, we use the method's in `oclif`’s `flags` module to register a flag, a type it’ll return, and the short flag name.

Now, we’re ready to rock: let’s see just how many things `oclif` handles out of the box by running the CLI. Right now, it’s only available with a slightly awkward command.

```term
$ ./bin/run
```

But [npm allows](https://docs.npmjs.com/cli/link.html) us to symlink this to the name of our CLI.

```term
$ npm link

...

$ greet-me
> hello world from ./src/index.ts
```

Excellent! Try passing your name in using `-n` or `--name` next–and see if there are any other ways `oclif` will let you pass in arguments.

## `SIGTERM`

While that’s all we’re going to cover in this blog post, oclif has a growing community and its code is open source so there are lots of other ways to learn more. Here are some links to continue exploring oclif.

- An episode of the [Code[ish] podcast](https://www.heroku.com/podcasts/codeish) about oclif with Jeff Dickey, one of the creators of oclif, and Nahid Samsami, Heroku’s PM for oclif {% podcast https://dev.to/codeish/13-oclif-an-open-source-cli-framework %}
- 💻🎙️ [oclifconf details](https://oclif.io/conf) if you’ll be in the San Francisco Bay Area on Friday, May 31, 2019
- 👀🗣️ oclif’s [Spectrum community](https://spectrum.chat/oclif)
- And finally, oclif’s GitHub repository {% github oclif/oclif %}