Skip to content
Content
Skill

/cli-extensions

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

BOOST
From plugin
webiny-js
8k76 skills3 MCP
Install
$ npx -y skills add webiny/webiny-js --skill cli-extensions --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/cli-extensions

Context preview

The summary Claude sees to decide when to auto-load this skill.

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

SKILL.md

cli-extensions.SKILL.md
name: webiny-cli-extensions
description: >
  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>.

CLI Extensions

TL;DR

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>`.

The CliCommandFactory Pattern

// 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):

<Cli.Command src={"/extensions/MyCustomCommand.ts"} />

Run it:

yarn webiny my-custom-command "World"

Command Definition Properties

| 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 |

Parameter Definition

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 |

The `Ui` Service

Inject `Ui` for formatted terminal output:

import { 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 |

Use Cases

  • **Data migrations** -- Scripts to migrate or seed CMS data
  • **Code generators** -- Generate boilerplate extension files
  • **Deployment scripts** -- Custom deployment workflows
  • **Data exports** -- Export CMS content to files
  • **Health checks** -- Verify infrastructure or API status

Quick Reference

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]

Related Skills

  • `webiny-dependency-injection` -- The `createImplementation` pattern and available injectable services
  • `webiny-project-structure` -- How to register CLI commands in `webiny.config.tsx`
  • `webiny-full-stack-architect` -- Full-stack extensions that may include CLI commands alongside API and Admin
Read more
Ships withwebiny-js

Open-source content platform. Self-hosted on AWS serverless. Built as a TypeScript framework you extend with code, not a closed product you configure through a UI. Runs on Lambda, DynamoDB, S3, and CloudFront inside your own AWS account. Scales automatically.

Get the whole plugin
Stats
8,048
Stars
682
Forks
Active
Maintenance
TypeScript
Language
2h ago
Last commit
8y ago
Created
9h ago
Added

Repo: webiny/webiny-js

Other skills on webiny-js.