# Getting started

Welcome aboard!

Caporal A full-featured framework for building awesome command-line applications with Node.js. This getting started guide will help you learn the basics in a few minutes.

For Caporal 1.x users, be sure to checkout the migration guide.

# Install

Simply add @caporal/core as a dependency.

npm install @caporal/core

# Glossary

We will refer to the following expressions within this guide:

  • Program: a cli app built using Caporal
  • Command: a command within your program. A program can have multiple commands.
  • Action: each command has an associated action run when executing the command.
  • Argument: a command can have one or more arguments passed after the command.
  • Options: Short and long options like -f or --file can be specified.

# Writing a program

# Hello world

Let's build the simplest program with Caporal: Hello world.

#!/usr/bin/env node
// file: hello-world.js (make the file executable using `chmod +x hello.js`)

// Caporal provides you with a program instance
const { program } = require("@caporal/core")

// Simplest program ever: this program does only one thing
program.action(({ logger }) => {
  logger.info("Hello, world!")
})

// always run the program at the end
program.run()

/* 
# Now, in your terminal:

$ ./hello-world.js
Hello, world!

*/

This program contains only one action. An action is a function executed when the program, or one of its commands, is run.

# Arguments

Let's get things more personal. by adding an argument name and making our program displaying Hello, ${name}! when run.

#!/usr/bin/env node

const { program } = require("@caporal/core")

program
  .argument("<name>", "Name to greet")
  .action(({ logger, args }) => {
    logger.info("Hello, %s!", args.name)
  })

program.run()

/*
$ ./hello.js Matt
Hello, Matt!
*/

Angled brackets vs square brackets

angled brackets (e.g. <item>) indicate required input while square brackets (e.g. [env]) indicate optional input. In the above example the <name> argument is mandatory.

Of course you can add multiple arguments just by chaining them:

#!/usr/bin/env node
const { program } = require("@caporal/core")
program
  .argument("<name>", "Name to greet")
  .argument("<other-name>", "Another argument")
  .argument("[third-arg]", "This argument is optional")
  .action(({ logger, args }) =>
    // Notice that args are camel-cased, so <other-name> becomes otherName
    logger.info("Hello, %s and %s!", args.name, args.otherName),
  )

program.run()

# Options

Let's add a way to modify the greeting by adding a --greeting option to our program.

#!/usr/bin/env node
const program = require("@caporal/core")
program
  .argument("<name>", "Name to greet")
  .option("--greating <word>", "Greating to use", {
    default: "Hello",
  })
  .action(({ logger, args, options }) => {
    logger.info("%s, %s!", options.greating, args.name)
  })

program.run()

/*
$ ./hello.js Matt --greeting Hi
Hi, Matt!

$ ./hello.js Matt
Hello, Matt!
*/

Note that our --greeting option has a default value of Hello. We specified what we called a long option, prefixed with a double dash. We can also specify an alternative short notation like this:

#!/usr/bin/env node
const { program } = require("@caporal/core")
program
  .argument("<name>", "Name to greet")
  // we will be able to use either `-g` or `--greeting` in the command line
  .option("-g, --greating <word>", "Greating to use", {
    default: "Hello",
  })
  .action(({ logger, args, options }) =>
    logger.info("%s, %s!", options.greating, args.name),
  )

program.run()

/*
$ ./hello.js Matt -g Hi
Hi, Matt!
*/

Learn more about Options.

# Commands

So far, our program only manage one possible action. Let's build something a little more complex to illustrate commands.

#!/usr/bin/env ts-node
// file: pizza-hit.ts
import program from "@caporal/core"

program
  // First possible command: "order"
  .command("order", "Order a pizza")
  .argument("<type>", "Type of pizza")
  .option("-e, --extra-ingredients <ingredients>", "Extra ingredients")
  .action(({ logger, args, options }) => {
    logger.info("Order received: %s", args.type)
    if (options.extraIngredients) {
      logger.info("Extra: %s", options.extraIngredients)
    }
  })

  // Another command: "cancel"
  .command("cancel", "Cancel an order")
  .argument("<order-id>", "Order id")
  .action(({ logger, args }) => {
    logger.info("Order canceled: %s", args.orderId)
  })

program.run()

Now our program contains 2 commands: order and cancel, which can be called this way:

# order a margherita with pepperoni on top
./pizza-hit.js order margherita -e pepperoni

# cancel an order
./pizza-hit.js cancel 12345

Note that in the previous Hello world examples, even if there was no explicit Command specified, Caporal still created a unnamed Command under the hood (called a program-command), directly attached to the program. Learn more about Commands.

# Help generation

Caporal automatically generates a help command for you so you don't have to!

  • prog --help and prog help will display global help.
  • prog help ${command} prog --help ${command} and will display command-related help.

Checkout the help section of this guide to learn how to customize it.

# Publishing your CLI

Publishing your CLI is easy with npm. Simply specify the bin property inside your package.json:

{
  "bin": {
    "pizza-hit": "src/pizza-hit.js"
  }
}
  • When installing your package globally, as in npm install -g my-package, npm will install src/pizza-hit.js as a global executable named pizza-hit.
  • When installing your package locally, as in npm install my-package, npm will install src/pizza-hit.js as an executable named pizza-hit inside node_modules/.bin.

Learn more about publishing your executable in the npm documentation.