Documentation
Help

Help

In this guide, we will be creating a command-line interface that provides different help mechanisms for end-users.

Help option

The most straightforward way to provide help for your CLI is by declaring a help option. In its simplest form, it has the following definition:

import { type Options } from 'tsargp';
export default {
  help: {
    type: 'help',
    names: ['--help'],
    desc: 'Prints this help message.',
  },
} as const satisfies Options;

You can increment it with an introduction, usage and footer:

import { type Options, style, fg } from 'tsargp';
export default {
  help: {
    // ...
    sections: [
      {
        type: 'text',
        text: 'A command-line interface for <purpose>.',
      },
      {
        type: 'usage',
      },
      {
        type: 'groups',
        title: 'Options:', // heading for the default option group
        style: style(tf.underlined), // underlined option group headings
      },
      {
        type: 'text',
        text: `Refer to ${style(fg.brightBlack)}<website>${style(fg.default)} for support.`,
      },
    ],
  },
} as const satisfies Options;

You may also want to customize the formatter configuration, e.g.:

import { type Options, HelpItem, style, tf } from 'tsargp';
export default {
  help: {
    // ...
    config: {
      names: { indent: 4 }, // indent option names by 4 spaces
      descr: { breaks: 1 }, // line feed before option descriptions
      param: { hidden: true }, // hide option parameter/examples
      items: [HelpItem.desc, HelpItem.required, HelpItem.deprecated],
      phrases: {
        [HelpItem.desc]: '💡 %t', // option synopsis with emoji
      },
    },
    styles: {
      descr: style(tf.italic), // italic description for this option
    },
  },
} as const satisfies Options;

Which, when invoked with --help, would render something like:

A command-line interface for <purpose>.
 
cli [--help]
 
Options:
 
    --help
              💡 Prints this help message.
 
Refer to <website> for support.

Help command

💡

Since this guide was written, the enable nested attribute for help options has been introduced. It supersedes help commands and offers a more convenient way to achieve what is described below. However, if you need an enumeration constraint for the available command names, then what follows might still be relevant.

Another way to offer help is by defining a "help" command. This method still uses the help option from the previous example, but increments it by providing a new syntax to obtain help for nested commands. For example, to present help for a nested command called cmd, the following invocations would be equivalent:

cli help cmd
cli cmd --help

To achieve this, we have to define a command option. We can start with the definitions for the nested commands' options:

import type { Options } from 'tsargp';
 
const cmd1Opts = {
  // option definitions for cmd1, including its 'help'...
} as const satisfies Options;
 
const cmd2Opts = {
  // option definitions for cmd2, including its 'help'...
} as const satisfies Options;
 
const helpOpts = {
  name: {
    type: 'string',
    desc: 'The name of the nested command.',
    enums: ['cmd1', 'cmd2'], // the names of nested commands
    preferredName: 'command name', // appears in error messages
    positional: true,
    required: true, // error if called without a command name
  },
} as const satisfies Options;

Now we can define the main command options:

import type { Options, OptionValues } from 'tsargp';
import { ArgumentParser } from 'tsargp';
export default {
  cmd1: {
    type: 'command',
    names: ['cmd1'],
    options: cmd1Opts,
    // ...
  },
  cmd2: {
    type: 'command',
    names: ['cmd2'],
    options: cmd2Opts,
    // ...
  },
  help: {
    type: 'command',
    names: ['help'],
    desc: 'Prints the help message of a nested command.',
    options: helpOpts,
    async exec({ param }) {
      const vals = param as OptionValues<typeof helpOpts>;
      const opts = vals.name === 'cmd1' ? cmd1Opts : cmd2Opts;
      // this will throw the help message
      await new ArgumentParser(opts).parse(['--help'], { progName: '' });
    },
  },
} as const satisfies Options;

The progName configuration flag is set in order to avoid appending the script name twice to the process title.

Keep in mind that, when word completion is in effect, the command callback will not be called. Thus, if the callback does get executed, you need not worry about the compIndex flag for the delegated parse call.