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. Keywords: Commander.js, CLI, command-line, arguments, options, flags, subcommands, action handlers, version, help text, TypeScript, yargs, meow, program, parseAsync, opts, args, variadic, required options, default values, custom help, error handling
Overall
score
99%
Does it follow best practices?
Validation for skill structure
Complete Commander.js framework guidance for building robust command-line interfaces with proper argument parsing, subcommands, options, and TypeScript support.
Read individual reference files for detailed guidance:
Each reference file contains:
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);--help and invalid inputs to verify argument parsing and error handlingprogram
.argument('<source>', 'Source file')
.argument('[destination]', 'Destination file')
.option('-f, --force', 'Force overwrite')
.action((source, destination, options) => {
// implementation
});program
.command('init')
.description('Initialize project')
.action(() => { /* ... */ });
program
.command('deploy')
.description('Deploy application')
.option('-e, --env <name>', 'Environment')
.action((options) => { /* ... */ });// 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);✓ 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
✗ 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)
Install with Tessl CLI
npx tessl i pantheon-ai/commanderjs@0.1.1