commanderjs
Skill10 starsChanged 39 days agoMITView on GitHub
Complete Commander.js CLI framework guidance covering command structure, options, arguments, subcommands, action handlers, version management, and TypeScript integration. Use when: building CLI tools, parsing command-line arguments, implementing subcommands, handling options/flags, creating interactive CLIs, or migrating from other CLI frameworks.
In this repository81 other files it gives its agents.
- AGENTS.mdAGENTS.md
- skills/development/biome-complete/AGENTS.mdAGENTS.md
- skills/development/bun-development/AGENTS.mdAGENTS.md
- skills/development/commanderjs/AGENTS.mdAGENTS.md
- skills/documentation/markdown-authoring/AGENTS.mdAGENTS.md
- skills/package-mgmt/mise-complete/AGENTS.mdAGENTS.md
- skills/testing/bdd-testing/AGENTS.mdAGENTS.md
- agents-mdSkill
- cache-auditSkill
- context-radar-auditSkill
- create-contextSkill
- guided-interviewSkill
- handover-document-creatorSkill
- load-contextSkill
- pick-modelSkill
- pinSkill
- professional-honestySkill
- rules-managementSkill
- save-contextSkill
- session-reflectionSkill
- socratic-methodSkill
- vault-captureSkill
- vault-consolidateSkill
- vault-fetchSkill
- vault-searchSkill
- bird-fortune-political-satireSkill
- brooker-esque-media-satireSkill
- clarke-dawe-esqueSkill
- comedy-style-skill-generatorSkill
- cunk-esque-mockumentarySkill
- gervais-esque-cringe-satireSkill
- monty-python-esqueSkill
- pryor-esque-confessional-standupSkill
- rock-esque-observational-standupSkill
- biome-completeSkill
- bun-developmentSkill
- conventional-commitsSkill
- humanizerSkill
- journal-entry-importSkill
- markdown-authoringSkill
- mermaid-diagramsSkill
- plain-englishSkill
- professional-communicationSkill
- sop-structureSkill
- logql-generatorSkill
- mise-completeSkill
- context-indexSkill
- create-context-fileSkill
- follow-upSkill
- goal-trackerSkill
- nasa-pm-lessonsSkill
- plan-createSkill
- plan-executeSkill
- plan-reviewSkill
- risk-registerSkill
- tech-debtSkill
- tech-evaluationSkill
- blast-radiusSkill
- bridgeSkill
- challengeSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 5 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 28
Read individual reference files for detailed guidance:
- Distinctive: line 72
Structure commands: - Create subcommands and command hierarchies
- Distinctive: line 73
Implement actions: - Write action handlers with async/await
- Distinctive: line 74
Integrate TypeScript: - Add proper typing and type safety
- Very specific: line 75
Validate parsing: - Test with --help and invalid inputs to verify argument parsing and error handling
- Distinctive: line 203
GOOD: Always place options before positional arguments in usage examples and validate input explicitly.
- Very specific: line 209
GOOD: Use command.opts() (the action's first argument when using .action((opts) =>)) to access subcommand-specific options.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Commander.js
Complete Commander.js framework guidance for building robust command-line interfaces with proper argument parsing, subcommands, options, and TypeScript support.
Mindset
Treat Commander.js as a declarative contract, not an argv reader. Model every input the CLI accepts as a .argument(), .option(), or subcommand before writing a single line of handler logic — the declaration is what generates --help output, coerces types, and produces Commander's own validation errors for free. Never reach for process.argv[n] as a shortcut past that declaration: every value read directly from argv is a value Commander no longer validates, documents, or reports errors for consistently with the rest of the program. Keep action handlers thin. Parse into a fully typed options object first, then pass that single object into a service function — never scatter individual opts.foo, opts.bar properties across a call site, because a service that grows a fourth or fifth positional parameter loses the compiler's ability to catch an argument-order mistake. Verify subcommand option scope before trusting program.opts() inside a subcommand action: each .command() owns its own option scope, and reading the parent program's opts() from inside a child action silently returns the wrong values instead of failing loudly.
When to Use
Use this skill when building a new CLI tool with Commander.js, adding subcommands, options, or arguments to an existing Commander.js program, migrating a CLI from raw process.argv parsing or another framework (yargs, meow) onto Commander.js, or diagnosing an option/argument/action handler that is not behaving as declared (wrong scope, a missing await, argv leaking through, help text not matching actual parsing behavior).
When NOT to Use
Do not reach for this skill when the target CLI deliberately avoids third-party argument-parsing dependencies, when the runtime's own built-in flag parser is the project's stated convention, or when the task is building a terminal UI (menus, prompts, live-updating panes) rather than parsing arguments — a TUI is a different problem from argument parsing and needs different tooling.
How to Use
Read individual reference files for detailed guidance:
- Core Basics
- Options & Flags
- Commands & Structure
- Action Handlers
- TypeScript Setup
- Practices & Patterns
Each reference file contains:
- API documentation and usage patterns
- Practical code examples with TypeScript
- Common patterns and best practices
- Error handling and validation techniques
- Migration guides from other frameworks
Quick Start
import { Command } from 'commander';
const program = new Command();
program
.name('my-cli')
.description('CLI tool description')
.version('1.0.0');
program
.command('build')
.description('Build the project')
.option('-o, --output <path>', 'Output directory')
.option('-w, --watch', 'Watch for changes')
.action((options) => {
console.log('Building with options:', options);
});
await program.parseAsync(process.argv);Navigation Workflow
- Start with core - Understand program setup and basic structure
- Add options - Define flags, required options, and defaults
- Structure commands - Create subcommands and command hierarchies
- Implement actions - Write action handlers with async/await
- Integrate TypeScript - Add proper typing and type safety
- Validate parsing - Test with
--helpand invalid inputs to verify argument parsing and error handling - Apply best practices - Error handling, validation, and testing
Common Patterns
Single Command CLI
program
.argument('<source>', 'Source file')
.argument('[destination]', 'Destination file')
.option('-f, --force', 'Force overwrite')
.action((source, destination, options) => {
// implementation
});Multi-Command CLI
program
.command('init')
.description('Initialize project')
.action(() => { /* ... */ });
program
.command('deploy')
.description('Deploy application')
.option('-e, --env <name>', 'Environment')
.action((options) => { /* ... */ });Modular Subcommands with Typed Options (Recommended)
// types/build-options.ts
export interface BuildOptions {
outDir: string;
minify: boolean;
watch: boolean;
}
// services/build-service.ts
import type { BuildOptions } from '../types/build-options';
export const buildProject = (options: BuildOptions): void => {
console.log('Building to:', options.outDir);
// All options available with type safety
};
// commands/build.ts
import { Command } from 'commander';
import { buildProject } from '../services/build-service';
import type { BuildOptions } from '../types/build-options';
export const buildCommand = new Command('build')
.description('Build project')
.option('-o, --out-dir <path>', 'Output directory', 'dist')
.option('-m, --minify', 'Minify output', false)
.option('-w, --watch', 'Watch mode', false)
.action((options: BuildOptions) => {
// Pass complete typed object to service
buildProject(options);
});
// index.ts
import { buildCommand } from './commands/build';
program.addCommand(buildCommand);Do's
✓ ALWAYS pass complete typed options objects to services (never individual properties)
✓ Define TypeScript interfaces for all options (e.g., BuildOptions, DeployOptions)
✓ Export commands as Command instances from subcommand modules
✓ Use .addCommand() to attach subcommands to parent Command
✓ Use parseAsync() for async action handlers
✓ Validate options in action handlers
✓ Provide clear descriptions for all commands/options
✓ Use TypeScript for type safety
✓ Handle errors gracefully with try/catch
✓ Use kebab-case for option names
✓ Provide sensible defaults for optional options
✓ Create barrel exports for commands (commands/index.ts)
✓ Test CLI with different argument combinations
✓ Use .exitOverride() for testing
✓ Document expected argument formats
Don'ts
✗ NEVER pass individual option properties to services (pass complete typed object)
✗ DON'T pass options piecemeal (e.g., service(opts.a, opts.b, opts.c))
✗ Don't use parse() with async handlers (use parseAsync())
✗ Don't ignore error handling in action handlers
✗ Don't use camelCase in CLI flags (use kebab-case)
✗ Don't forget to specify option argument types (<required> vs [optional])
✗ Don't mix positional arguments with options ambiguously
✗ Don't forget to call program.parse() or program.parseAsync()
✗ Don't use global state in action handlers
✗ Don't suppress built-in help text without good reason
✗ Don't forget to version your CLI
✗ Don't make all options required (use sensible defaults)
Anti-Patterns
NEVER access process.argv directly when Commander.js is available
- WHY: Commander.js handles argument parsing, validation, and help generation; bypassing it for any argument creates inconsistency in error handling and help output.
- BAD:
const url = process.argv[2]alongside Commander.js commands. - GOOD: Define all arguments as Commander.js options or arguments:
program.argument('<url>', 'Target URL').
NEVER use .action() callback without handling errors
- WHY: Unhandled rejections in async action callbacks crash the process without helpful error messages.
- BAD:
program.command('fetch').action(async (opts) => { await riskyOp(); }) - GOOD: Wrap in try/catch and call
program.error(err.message)for Commander-formatted error output.
NEVER add .parseAsync() without await
- WHY: Commander.js v8+ requires
await program.parseAsync()for async actions; without await, the process exits before async actions complete. - BAD:
program.parseAsync(process.argv)without await. - GOOD:
await program.parseAsync(process.argv)inside an async IIFE or main function.
NEVER define commands with positional arguments and options that share ambiguous prefixes
- WHY: Commander.js can misparse
--optionvalues as positional arguments when options are not consumed before positional parsing. - BAD:
program.argument('<file>').option('--format <fmt>')with ambiguous ordering in usage examples. - GOOD: Always place options before positional arguments in usage examples and validate input explicitly.
NEVER use program.opts() to read option values inside a subcommand
- WHY: Each subcommand has its own option scope; reading
program.opts()in a subcommand returns the parent options, not the subcommand options. - BAD: Reading
program.opts().verboseinside aprogram.command('deploy').action(). - GOOD: Use
command.opts()(the action's first argument when using.action((opts) =>)) to access subcommand-specific options.
References
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

