@jshow/cli
v1.0.2
Published
A simple CLI tool for j-show
Downloads
194
Readme
Overview
@jshow/cli is a command line tool set for jShow, developed based on commander. It provides a powerful and extensible CLI framework with automatic command discovery, plugin system, and full TypeScript support.
The CLI automatically scans and loads command files (.cmd.ts or .cmd.js) and plugin files (.plugin.ts or .plugin.js) from your project, making it easy to build custom CLI tools with minimal configuration.
Features
| Feature | Description |
| --- | --- |
| Auto Command Discovery | Automatically scans and loads command files (.cmd.ts or .cmd.js) in the project |
| Plugin System | Support for plugins with lifecycle hooks (beforeExecute, afterExecute) |
| Command Registration | Support custom command registration for easy command extension |
| Type Safety | Full TypeScript type support |
| Commander Export | Exports the entire commander library for direct use |
| Command Base Class | Provides BaseCommand abstract base class to simplify command development |
| Command Grouping | Organize commands into groups for better help information display |
Why @jshow/cli?
- Zero Configuration – Automatically discovers and loads commands/plugins from your project without manual registration.
- Type-Safe – Full TypeScript support with comprehensive type definitions for commands, plugins, and options.
- Extensible – Plugin system allows you to add cross-cutting concerns like logging, timing, and error handling.
- Commander Integration – Built on top of Commander.js, exports the entire library for advanced use cases.
- Developer Friendly – Simple base classes and clear conventions make it easy to create and maintain commands.
- Modern Tooling – Built for modern Node.js with ESM support and TypeScript-first design.
Quick Start
Install dependencies
pnpm add @jshow/cli # or npm install @jshow/cli # or yarn add @jshow/cliCreate a command file
Create a file ending with
.cmd.tsor.cmd.jsin your project:// example.cmd.ts import { BaseCommand, CommandContext } from '@jshow/cli'; export default class ExampleCommand extends BaseCommand { static name = 'example'; static force = false; public get args() { return { name: 'example', description: 'This is an example command', aliases: ['ex', 'e'], group: 'examples', plugins: ['logger', 'timer'], // Optional: specify plugins to use options: [ { flag: '--name <value>', abbreviation: '-n', description: 'Name parameter', defaultValue: 'world', required: false, }, ], examples: [ 'jshow example', 'jshow example --name "jshow"', 'jshow ex -n "test"', ], validate: (options) => { // Optional: custom validation if (options.name && typeof options.name !== 'string') { return 'Name must be a string'; } return null; }, }; } public beforeExecute(context: CommandContext): void { console.log(`Starting command: ${context.name}`); } public execute(): void { const options = this.command.opts(); console.log(`Hello, ${options.name || 'world'}!`); } public afterExecute(context: CommandContext): void { console.log(`Command completed in ${Date.now() - context.startTime}ms`); } }Run the command
# Development mode pnpm start # Or build and run pnpm build jshow example --name "jshow"
Repository Scripts
| Command | Description |
| --- | --- |
| pnpm build | Builds the library and CLI entry point, outputs to dist/ |
| pnpm build:lib | Builds only the library package |
| pnpm build:cli | Builds only the CLI entry point |
| pnpm start | Runs the CLI in development mode using ts-node |
| pnpm clean | Removes build outputs (dist/ and out/ directories) |
Examples
The examples/ directory contains working examples:
TypeScript Examples
hello.cmd.ts– A simple Hello World command demonstrating basic command structuregreet.cmd.ts– A command with options, aliases, and validationbuild.cmd.ts– A complex command using plugins and command grouping
CommonJS Examples
hello.cmd.js– A basic command example using CommonJS syntaxbuild.cmd.js– A command with plugins example using CommonJS syntax
Plugin Examples
logger.plugin.ts– A logging plugin with lifecycle hooks (priority: 50)timer.plugin.ts– A timing plugin for performance monitoring (priority: 100)error-handler.plugin.ts– An error handling plugin example (priority: 200)
See examples/README.md for detailed usage instructions.
API Documentation
CommandProgram
Command program manager, responsible for command registration and execution.
Static Properties
version: string- CLI version numberprogram: Command- Commander program instance
Static Methods
use(command: CommandClass, force?: boolean): CommandProgram
Register a command class.
Parameters:
command: CommandClass- Command class (extendsBaseCommand)force?: boolean- Whether to force override if command already exists (default:false)
Returns: CommandProgram instance (supports chaining)
install(plugin: PluginClass, force?: boolean): CommandProgram
Install a plugin.
Parameters:
plugin: PluginClass- Plugin class (extendsBasePlugin)force?: boolean- Whether to force override if plugin already exists (default:false)
Returns: CommandProgram instance (supports chaining)
run(): void
Run the CLI program, parse command line arguments and execute the corresponding command.
CommandArgs
Command argument configuration interface.
Properties
name: string- Command name (required)description?: string- Command descriptionaliases?: string[]- Command aliasesplugins?: string[]- List of plugin names to use for this commandgroup?: string- Command group for help organizationoptions: CommandOption[]- Command options (required)examples?: string[]- Usage examplesvalidate?: (options: Record<string, unknown>) => string | null- Optional validation function that returns an error message or null
CommandOption
Command option configuration interface.
Properties
flag: string- Option flag (e.g.,'--name <value>'or'--verbose')abbreviation?: string- Option abbreviation (e.g.,'-n')description?: string- Option descriptiondefaultValue?: T- Default value for the optionrequired?: boolean- Whether the option is required (default:false)
BaseCommand
Command base class. All custom commands should extend this class.
Static Properties
name: string- Command name (required)force: boolean- Whether to force override if command with same name exists (default:false)
Instance Properties
name: string- Get command name (read-only)command: Command- Commander command instance (protected)
Abstract Methods
execute(): void
Command execution logic. Subclasses must implement this method.
Protected Methods
get args(): CommandArgs
Get command argument configuration. Subclasses must implement this getter.
The CommandArgs interface includes:
name: string- Command namedescription?: string- Command descriptionaliases?: string[]- Command aliasesplugins?: string[]- List of plugin names to use for this commandgroup?: string- Command group for help organizationoptions: CommandOption[]- Command optionsexamples?: string[]- Usage examplesvalidate?: (options: Record<string, unknown>) => string | null- Optional validation function
beforeExecute?(context: CommandContext): void
Lifecycle hook executed before command execution.
afterExecute?(context: CommandContext): void
Lifecycle hook executed after command execution.
onError(error: Error, context: CommandContext): boolean
Error handling hook. Returns true if error is handled, false otherwise.
BasePlugin
Plugin base class. All custom plugins should extend this class.
Static Properties
name: string- Plugin name (required)force: boolean- Whether to force override if plugin with same name exists (default:false)
Instance Properties
name: string- Get plugin name (read-only)priority: number- Plugin priority (default: 100, lower number = higher priority)
Methods
beforeExecute?(context: CommandContext): void
Lifecycle hook executed before command execution.
afterExecute?(context: CommandContext): void
Lifecycle hook executed after command execution.
File Naming Conventions
Command Files
TypeScript Files
- File naming: Must end with
.cmd.ts - Default export: Must use
export defaultto export the command class - Extend base class: Command class must extend
BaseCommand - Static properties: Must set
static nameproperty - Implement methods: Must implement
execute()method andargsgetter
CommonJS Files
- File naming: Must end with
.cmd.js - Import dependencies: Use
require()to import:const { BaseCommand } = require('@jshow/cli'); - Export class: Use
module.exportsto export class (Node.js automatically treats it as default export) - Extend base class: Command class must extend
BaseCommand - Static properties: Must set
static nameproperty - Implement methods: Must implement
execute()method andargsgetter
Plugin Files
TypeScript Files
- File naming: Must end with
.plugin.ts - Default export: Must use
export defaultto export the plugin class - Extend base class: Plugin class must extend
BasePlugin - Static properties: Must set
static nameproperty
CommonJS Files
- File naming: Must end with
.plugin.js - Import dependencies: Use
require()to import:const { BasePlugin } = require('@jshow/cli'); - Export class: Use
module.exportsto export class (Node.js automatically treats it as default export) - Extend base class: Plugin class must extend
BasePlugin - Static properties: Must set
static nameproperty
Auto Discovery
The CLI automatically scans the current working directory and its subdirectories, finds all .cmd.ts, .cmd.js, .plugin.ts, or .plugin.js files and loads them automatically.
Scanning Rules:
- Recursively scan from
process.cwd() - Only load files ending with
.cmd.ts,.cmd.js,.plugin.ts, or.plugin.js - Automatically extract command/plugin name from filename (remove
.cmdor.pluginsuffix)
Development Workflow
pnpm install– Install dependencies- Create command files (
.cmd.tsor.cmd.js) or plugin files (.plugin.tsor.plugin.js) in your project pnpm start– Run in development modepnpm build– Build for production- Test your commands with
jshow <command>
Directory Layout
├── src/
│ ├── cli.ts # CLI entry point
│ ├── command.ts # Command base class and types
│ ├── plugin.ts # Plugin base class and types
│ ├── program.ts # Command program manager
│ └── index.ts # Main export
├── examples/ # Example commands and plugins
├── scripts/ # Build scripts
├── dist/ # Build outputs (gitignored)
└── ...License
MIT © jShow
Questions or issues? Open an issue at https://github.com/j-show/cli/issues.
