Skip to main content
The @talosjs/command component is a small CLI command framework. Each command implements the ICommand interface (getName, getDescription, and run) and registers itself with @decorator.command(). The run() entry point parses Bun.argv, resolves the matching command from the container by name, and executes it with fully typed options. Commands are resolved through @talosjs/container, so they support dependency injection and the full range of scopes.

What it gives you

@decorator.command() registers a class with the DI container and the global command registry in one step. The generic ICommand<Options> interface carries your option type through run(), and run() itself parses named options, booleans, and positionals from Bun.argv before forwarding them to the command. Because commands resolve through @talosjs/container, they work with the Singleton, Request, and Transient scopes. Failures throw a CommandException that carries a machine-readable key, a message, and a data object, and it is logged automatically. For scaffolding, commandCreate writes a command class, its test stub, and a barrel export from the bundled templates.

How it works

You implement ICommand, register it with @decorator.command(), then import the file so the decorator runs before you call run(). The entry point reads the command name from the third positional argument, looks it up by getName(), and invokes run() with the parsed options. The runtime pieces fit together as follows: When no command matches the requested name, or the command throws, run() logs the error via TerminalLogger and exits with code 1.

Decorator and usage

@decorator.command()

Registers a command class with the container and pushes it onto the global COMMANDS_CONTAINER. It accepts an optional EContainerScope (defaults to Singleton). Implement ICommand and register the class:
Pass a scope when you need a fresh instance per resolution:

Running the entry point

Call run() in your CLI entry file. Import the files that register commands first so their decorators execute:
Invoke it from the terminal, where the command name is the third positional argument:

Resolving a command manually

getCommand() returns a registered command by name, or null when none matches:

Injecting dependencies

Because commands resolve through @talosjs/container, you can inject services in the constructor:

Exceptions

The component throws CommandException for command-related errors. It extends Exception from @talosjs/exception, carries a machine-readable key, a human-readable message, and a data object, and reports an InternalServerError HTTP status. You supply the key at throw time, so choose a stable, descriptive value per failure.
Throw it from run() with a stable key and contextual data:
Catch it to inspect the structured fields:
When run() catches an exception it logs it via TerminalLogger and exits with code 1, so uncaught CommandExceptions surface automatically.

Guidance

Name commands namespace:action, with a colon-separated scheme like db:migrate or user:import, so related commands group naturally. Type your options by passing an options type to ICommand<Options> and defining every flag it takes, rather than leaning on Record<string, unknown>. Decorators only register a command when its module is loaded, so keep a barrel file and import it before you call run(). Resolve services through the container constructor instead of constructing them, which keeps commands testable. When you throw CommandException, keep the key constant per failure and put the variable detail in data. A good run() validates its options up front, fails fast with a clear exception, and then does the work. Default to Singleton scope; reach for Transient only when a command must not share state across resolutions.

CLI command

Scaffold a command class and its test file with the generator. It writes the class under modules/<module>/src/commands/<Name>Command.ts, a test under modules/<module>/tests/commands/<Name>Command.spec.ts, updates the commands.ts barrel export, and creates bin/command/run.ts for the module if it is missing.
The generated class is a registered ICommand stub, ready for you to define its options and implement run():
Run a generated command from its module by its getName() value — extra arguments are forwarded to the command:
command:run scans every module under modules/ for a bin/command/run.ts, locates the command whose getName() matches, and spawns it. It exits with code 1 when the command is not found in any module or when it fails. See command:create and command:run for the full command references.

Use with Claude and Codex

The generator ships a matching command:create skill. It runs the scaffold and then guides your AI agent through completing the command: defining the options type and implementing run(). Initialize the skills once for your agent:
Then ask Claude in natural language. It maps the request to the generator, runs it, and fills in the implementation:
Prompt
For example, the prompt above maps to command:create --name=ImportUser, then implements the run() method to read the CSV and persist the users.