/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
$ npx -y skills add agents-inc/skills --skill cli-framework-cli-commander --agent claude-codeHow 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
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.mdname: 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
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: "Showing the first part of this file.
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?
Repo: agents-inc/skills
Other skills on agents-inc-skills.
- /ai-infrastructure-huggingface-inference
Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation, audio transcription, translation, summarization, and Inference Endpoints
Open skill - /ai-infrastructure-litellm
LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production deployment
Open skill - /ai-infrastructure-modal
Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns
Open skill - /ai-infrastructure-ollama
Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint
Open skill - /ai-infrastructure-replicate
Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training
Open skill - /ai-infrastructure-together-ai
Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation, fine-tuning, and OpenAI-compatible endpoints
Open skill

