Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Adding custom commands to the Webiny CLI using CliCommandFactory. Use this skill when the developer wants to create a custom CLI command, add a data migration script, build a code generator, create deployment scripts, export CMS content, or add health check commands. Covers CliCommandFactory.Interface, command definition, typed parameters, the Ui service for terminal output, and registration via <Cli.Command>.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | -9% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 2% | 0% |
| case-07 | ✗→✓ | ▲ Improved | -5% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 17% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 4% | 0% |
Add custom commands to the Webiny CLI using the CliCommandFactory pattern. Define a class implementing CliCommandFactory.Interface<TParams>, specify command name, description, params, and handler, then export with CliCommandFactory.createImplementation(). Register in webiny.config.tsx via <Cli.Command>.
typescript// extensions/MyCustomCommand.ts import { Ui } from "webiny/cli"; import { CliCommandFactory } from "webiny/cli/command"; export interface IMyCustomCommandParams { name: string; } class MyCustomCommandImpl implements CliCommandFactory.Interface<IMyCustomCommandParams> { constructor(private ui: Ui.Interface) {} execute(): CliCommandFactory.CommandDefinition<IMyCustomCommandParams> { return { name: "my-custom-command", description: "This is my custom command", examples: ["$0 my-custom-command test1", "$0 my-custom-command test2"], params: [ { name: "name", description: "Your name", type: "string" } ], handler: async params => { this.ui.info("Starting my custom command..."); this.ui.emptyLine(); this.ui.success(`Hello, ${params.name}! This is my custom command.`); } }; } } export default CliCommandFactory.createImplementation({ implementation: MyCustomCommandImpl, dependencies: [Ui] });
Register in webiny.config.tsx (YOU MUST include the .ts file extension in the src prop — omitting it will cause a build failure):
tsx<Cli.Command src={"/extensions/MyCustomCommand.ts"} />
Run it:
bashyarn webiny my-custom-command "World"
| Property | Type | Description | | ------------- | ------------------------------------ | -------------------------------------------------------------- | | name | string | The command name used on the CLI (e.g., "my-custom-command") | | description | string | Help text shown when listing commands | | examples | string[] | Usage examples ($0 is replaced with the CLI binary name) | | params | ParamDefinition[] | Positional parameters and options | | handler | (params: TParams) => Promise<void> | The function that executes the command |
Each param in the params array:
| Property | Type | Description | | ------------- | ----------------------------------- | ------------------------------------------------------------ | | name | string | Parameter name (matches the key in your TParams interface) | | description | string | Help text for this parameter | | type | "string" \| "number" \| "boolean" | Parameter value type |
Ui ServiceInject Ui for formatted terminal output:
typescriptimport { Ui } from "webiny/cli";
| Method | Description | | ---------------------------- | -------------------------------- | | this.ui.info("message") | Print an info message (blue) | | this.ui.success("message") | Print a success message (green) | | this.ui.warning("message") | Print a warning message (yellow) | | this.ui.error("message") | Print an error message (red) | | this.ui.emptyLine() | Print a blank line for spacing |
Import: import { CliCommandFactory } from "webiny/cli/command";
Ui import: import { Ui } from "webiny/cli";
Interface: CliCommandFactory.Interface<TParams>
Definition: CliCommandFactory.CommandDefinition<TParams>
Export: CliCommandFactory.createImplementation({ implementation, dependencies })
Register: <Cli.Command src={"/extensions/MyCommand.ts"} />
Run: yarn webiny <command-name> [args]webiny-dependency-injection -- The createImplementation pattern and available injectable serviceswebiny-project-structure -- How to register CLI commands in webiny.config.tsxwebiny-full-stack-architect -- Full-stack extensions that may include CLI commands alongside API and AdminOther measured skills in the registry, with their headline benchmark lift.