Files
skills/docs/devtools/tooling/cli/src/command/command.md
2026-05-29 08:20:56 +01:00

4.5 KiB

command

(no submodules)

Purpose

Command is the core routing primitive for @suaveplan/cli. It models a single CLI command that can carry options, positional arguments, and an action handler, or act as a router that delegates to named sub-commands. Every App is backed by a root Command.

The class exposes a fluent builder API: chain .description(), .option(), .argument(), .command(), and .action() calls before calling .execute() at runtime. Sub-commands are registered via .command(name) which returns the child Command, enabling identical fluent chaining for nested hierarchies.

Features

  • Fluent builder: .description(), .option(), .argument(), .action(), .command(), .alias(), .hidden(), .example()
  • Sub-command routing: first non-flag token in argv is matched against registered names and aliases
  • Option parsing delegated to parseArgs — inherits full flag semantics (boolean, string, number, --no-*, short flags, = syntax, -- rest)
  • OTel span on every execute() call: span name cli.command.execute, attribute cli.command set to the full qualified name
  • CliError(CLI_CODES.COMMAND.NO_ACTION) when no action is registered and no sub-command is found
  • CliError(CLI_CODES.COMMAND.UNKNOWN_SUBCOMMAND) when an unknown first token is provided and sub-commands are registered
  • Automatic --help / -h handling: prints helpText() and returns without error
  • helpText(parentName?) generates a formatted usage block with options and sub-command listing

Usage: Basic Example

import { Command } from "@suaveplan/cli/command/command";

const cmd = new Command("greet")
  .description("Greet a user")
  .option("--name <name>", "Name to greet", "World")
  .action(async (ctx) => {
    console.log(`Hello, ${ctx.options.name}!`);
  });

await cmd.execute(["--name", "Alice"]);
// → Hello, Alice!

Usage: Advanced Example

import { Command } from "@suaveplan/cli/command/command";

const root = new Command("deploy")
  .description("Deployment toolkit");

root
  .command("up")
  .description("Bring services up")
  .option("--env <env>", "Target environment", "staging")
  .action(async (ctx) => {
    console.log(`Deploying to ${ctx.options.env}`);
  });

root
  .command("down")
  .alias("d")
  .description("Tear services down")
  .action(async () => {
    console.log("Tearing down...");
  });

// Route: "deploy up --env production"
await root.execute(["up", "--env", "production"]);

// Route by alias: "deploy d"
await root.execute(["d"]);

API Reference

new Command(name: string)

Creates a new command with the given name.

.description(text: string): this

Sets the human-readable description shown in help text.

.option(flags: string, description?: string, defaultValue?: unknown): this

Registers an option. flags follows parseOptionFlags syntax: "--name <value>", "-v, --verbose".

.argument(spec: string, description?: string): this

Registers a positional argument. spec follows parseArgumentSpec syntax: "<file>", "[file]", "<files...>".

.action(fn: ActionFn): this

Sets the action handler. fn receives an ActionContext with options, args (positionals), rest, and command info.

.command(name: string): Command

Registers a named sub-command and returns it for further chaining.

.alias(name: string): this

Adds an alias for this command, recognised during routing.

.hidden(): this

Marks the command as hidden — it is excluded from help text listings.

.example(text: string): this

Adds an example line shown in help text.

.helpText(parentName?: string): string

Returns formatted multi-line help text including usage, options, sub-commands, and examples.

.getParserConfig(): ParserConfig

Returns the ParserConfig derived from registered options and arguments. Used internally by execute().

.execute(argv: string[], parentName?: string): Promise<void>

Parses argv, routes to sub-commands or calls the action. Wraps the execution in an OTel span. Throws CliError on routing or parse failures.

Implementation Notes

Sub-command alias resolution scans all registered sub-commands for an _aliases entry matching the first token. An OTel span covers the full execute() lifecycle including sub-command delegation — the span status is set to ERROR if any exception propagates. The --help / -h shortcut is handled before sub-command routing and before the action call, so it always works even if no action is registered.