Skip to content

/cli-framework-cli-commander

Node.js CLI development with Commander.js and @clack/prompts - command structure, interactive prompts, wizard state machines, config hierarchies, exit codes, cancellation handling

shell
$ npx -y skills add agents-inc/skills --skill cli-framework-cli-commander --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/cli-framework-cli-commander
How auto-invocation works

Context preview

The summary Claude sees to decide when to auto-load this skill.

Node.js CLI development with Commander.js and @clack/prompts - command structure, interactive prompts, wizard state machines, config hierarchies, exit codes, cancellation handling

SKILL.md

cli-framework-cli-commander.SKILL.md
name: cli-framework-cli-commander
description: Node.js CLI development with Commander.js and @clack/prompts - command structure, interactive prompts, wizard state machines, config hierarchies, exit codes, cancellation handling

CLI Application Development with Commander.js

> **Quick Guide:** Use Commander.js for command structure and option parsing. Use @clack/prompts for interactive UX (spinners, selects, confirms). Always handle Ctrl+C cancellation with `p.isCancel()`. Use named exit code constants. Use `parseAsync()` for async actions. Structure commands in separate files. Resolve config with precedence: flag > env > project > global > default.

---

<critical_requirements>

CRITICAL: Before Building CLI Applications

> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)

**(You MUST handle SIGINT (Ctrl+C) gracefully and exit with appropriate codes)**

**(You MUST use `p.isCancel()` to detect cancellation in ALL @clack/prompts calls and handle gracefully)**

**(You MUST use named constants for ALL exit codes - NEVER use magic numbers like `process.exit(1)`)**

**(You MUST use `parseAsync()` for async actions to properly propagate errors)**

**(You MUST stop spinners before any console output or error display)**

</critical_requirements>

---

**Auto-detection:** Commander.js, commander, @clack/prompts, picocolors, p.spinner, p.select, p.confirm, p.text, p.isCancel, p.tasks, p.multiselect, p.group, process.exit, exit codes, SIGINT handling, interactive prompts, wizard state machine, config hierarchy, CLI error handling, parseAsync, subcommand

**When to use:**

  • Building command-line tools with Node.js using Commander.js
  • Creating interactive terminal prompts and wizards with @clack/prompts
  • Implementing multi-step wizard flows with back navigation
  • Managing hierarchical configuration (flag > env > project > global)
  • Structuring CLI applications with subcommands and global options

**When NOT to use:**

  • Simple scripts with no user interaction (just use process.argv directly)
  • Web server frameworks (use your API framework skill)
  • Single-prompt scripts (use readline or raw @clack/prompts without Commander)

**Key patterns covered:**

  • CLI entry point with SIGINT handling and global options
  • Standardized exit codes with named constants
  • Command definition with typed options and subcommands
  • @clack/prompts for interactive UX (spinners, selects, confirms, text)
  • Cancellation handling (`p.isCancel()`) on every prompt
  • Wizard state machines with back navigation
  • Configuration hierarchy resolution
  • Dry-run mode implementation

**Detailed Resources:**

  • [examples/core.md](examples/core.md) - Entry point, exit codes, commands, prompts, cancellation
  • [examples/wizard-patterns.md](examples/wizard-patterns.md) - State machines, config hierarchy, dry-run mode

---

<philosophy>

Philosophy

**User experience first.** CLI tools should be intuitive, provide helpful feedback, and fail gracefully. Users should always know what's happening (spinners), what went wrong (clear errors), and how to fix it (actionable messages).

**Consistency across commands.** Every command follows the same patterns: options at top, spinner feedback, success/error messaging, and proper exit codes. This makes the CLI predictable and learnable.

**Graceful degradation.** Always handle cancellation (Ctrl+C), invalid input, and errors. Never leave users in an unknown state. Stop spinners before displaying errors.

**When to use Commander.js:**

  • Multi-command CLI tools (git-like interfaces)
  • Tools with complex option parsing and subcommands
  • Applications needing auto-generated help text
  • TypeScript-first development

**When to use @clack/prompts:**

  • Interactive setup wizards and multi-step flows
  • User confirmation before destructive actions
  • Selection from lists of options
  • Any user input beyond simple flags

</philosophy>

---

<patterns>

Core Patterns

Pattern 1: CLI Entry Point Structure

Register commands, handle SIGINT, use `parseAsync()` for async error propagation. See [examples/core.md](examples/core.md#pattern-1-cli-entry-point-structure) for full implementation.

// Handle Ctrl+C gracefully
process.on("SIGINT", () => {
  console.log(pc.yellow("\nCancelled"));
  process.exit(EXIT_CODES.CANCELLED);
});

// Use parseAsync for proper async error handling
await program.parseAsync(process.argv);

---

Pattern 2: Standardized Exit Codes

Define all exit codes as named constants. Never use magic numbers. See [examples/core.md](examples/core.md#pattern-2-standardized-exit-codes) for the full constant definition.

export const EXIT_CODES = {
  SUCCESS: 0,
  ERROR: 1,
  INVALID_ARGS: 2,
  CANCELLED: 4,
  VALIDATION_ERROR: 7,
} as const;

// GOOD: Named constant
process.exit(EXIT_CODES.VALIDATION_ERROR);

// BAD: Magic number
process.exit(1); // What does 1 mean?

---

Pattern 3: Command Definition with Options

Structure commands with typed options, descriptions for help text, and global option access. See [examples/core.md](examples/core.md#pattern-3-command-definition-with-options) for full implementation.

export const initCommand = new Command("init")
  .description("Initialize the project")
  .option("--source <url>", "Source URL")
  .option("-f, --force", "Overwrite existing files", false)
  .action(async (options, command) => {
    const globalOpts = command.optsWithGlobals();
    // ...
  });

---

Pattern 4: Interactive Prompts with Cancellation

Every @clack/prompts call must be followed by `p.isCancel()`. See [examples/core.md](examples/core.md#pattern-4-interactive-prompts-with-cancellation) for spinner, select, confirm, and text patterns.

const result = await p.select({
  message: "Select a framework:",
  options: [
    { value: "react", label: "React", hint: "recommended" },
    { value: "vue", label: "
Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withagents-inc-skills

The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Get the whole plugin, auto-invoked