Console Commands

Plugins and modules can add additional console commands to Craft, which will be available via the craft executable in the terminal.

Console commands are implemented very similarly to controllers, except that they should live within a console/controllers/ folder within your plugin or module’s base source folder, and they should extend craft\console\Controller (opens new window) (rather than craft\web\Controller (opens new window)).

For the most part, writing console commands for Craft is identical to writing console commands for Yii, so be sure to read the Yii documentation (opens new window) as a starting point.

# Module Setup

If you are adding console commands to a custom module, make sure that your module class defines its root controllerNamespace for console requests:














 
 










<?php
namespace acme;

use Craft;

class Module extends \yii\base\Module
{
    public function init()
    {
        // Define a custom alias named after the namespace
        Craft::setAlias('@acme', __DIR__);

        // Set the controllerNamespace based on whether this is a console or web request
        if (Craft::$app->getRequest()->getIsConsoleRequest()) {
            $this->controllerNamespace = 'acme\\console\\controllers';
        } else {
            $this->controllerNamespace = 'acme\\controllers';
        }

        parent::init();

        // Custom initialization code goes here...
    }
}

You’ll also need to make sure your module is getting bootstrapped (opens new window) from config/app.php (or config/app.console.php):


 





return [
    'bootstrap' => ['acme'],
    'modules' => [
        'acme' => acme\Module::class,
    ],
];

# Adding a Controller

Any classes within the folder corresponding to your controllerNamespace setting will be automatically discovered when the console application initializes. Every controller has a default action (run when an action is not specified), and supports options (opens new window).

Create GreetController.php in modules/console/controllers/, with this content:

<?php

namespace modules\console\controllers;

use craft\console\Controller;
use craft\helpers\Console;
use yii\console\ExitCode;

/**
 * Greet Controller
 */
class GreetController extends Controller
{
    public $defaultAction = 'developer';

    /**
     * @var string|null The name used when referring to the runner.
     */
    public ?string $who = null;

    public function options($actionID): array
    {
        $options = parent::options($actionID);

        // Always allow a --who flag:
        $options[] = 'who';

        switch ($actionID) {
            case 'developer':
                // Action-specific arguments:
                // $options[] = '...';
                break;
        }

        return $options;
    }

    /**
     * Issues a greeting to new Craft developers.
     */
    public function actionDeveloper(): int
    {
        $who = $this->who ?? 'world';

        $this->stdout("Hello, {$who}!", Console::FG_GREEN);

        return ExitCode::OK;
    }
}

# Running Actions

Supposing your module ID or plugin handle was acme, you would access your controller like this:

# Run the "default action":
php craft acme/greet
# -> Hello, world!

# Run the developer-specific greeting:
php craft acme/greet/developer
# -> Hello, world!

# Pass a name:
php craft acme/greet/developer --who="Marvin"
# -> Hello, Marvin!

# Arguments

Actions can declare arguments that will be processed from the command’s input. Arguments are separated by spaces, and the values are processed according to their declared types:

public function actionDeveloper(string $emotion, ?int $days = null): int
{
    $who = $this->who ?? 'world';

    if ($days >= 500) {
        $this->stderr("Sorry, I don’t remember you, {$who}!", Console::FG_YELLOW);

        return ExitCode::TEMPFAIL;
    }

    $this->stdout("Hello, {$who}! I am {$emotion} to see you!", Console::FG_GREEN);

    return ExitCode::OK;
}

Read more about passing arguments (opens new window) to console commands.

# Help Text

To assist CLI users, Yii automatically parses docblocks from your controller’s action methods (as well as any public properties matching options you’ve registered) and displays them when running php craft help.

php craft help acme/greet
# -> List of actions

php craft help acme/greet/developer
# -> Action description, list of available --options

php craft acme/greet --help
# This works the same way as the main `help` command!

# Registering Custom Console Commands

You can register custom console commands on Craft’s own controllers, or plugin-supplied controllers, so long as they extend craft\console\Controller (opens new window). For example, plugins that supply custom element types can add their own actions to the resave (opens new window) controller.

To do that, use the craft\console\Controller::EVENT_DEFINE_ACTIONS (opens new window) event.

use craft\events\DefineConsoleActionsEvent;
use craft\console\Controller;
use craft\console\controllers\ResaveController;
use yii\base\Event;

Event::on(
    ResaveController::class,
    Controller::EVENT_DEFINE_ACTIONS,
    function(DefineConsoleActionsEvent $event) {
        $event->actions['products'] = [
            'options' => ['type'],
            'helpSummary' => 'Re-saves products.',
            'action' => function($params): int {
                /** @var ResaveController $controller */
                $controller = Craft::$app->controller;
                $query = Product::find();
                if ($controller->type) {
                    $query->type(explode(',', $controller->type));
                }
                return $controller->saveElements($query);
            }
        ];
    }
);

# Output Helpers

Internally, Craft keeps console feedback consistent with a suite of helper methods 4.0.0+ provided by craft\console\ControllerTrait (opens new window).

  • Success — Output a message with a ✅ icon: $this->success('Done!');
  • Failure — Output a message prefixed with an X: $this->failure('Something went wrong.');
  • Tips — Output a message with a 💡 icon: $this->tip('Try this, next!');
  • Warning — Output a message with a ⚠️ icon: $this->warning('Check your input and try again.');
  • Generic “Note” — Output a message with a custom icon or prefix: $this->note('Eat your vegetables!', '🥬 ');

The above methods run the $note argument through craft\console\ControllerTrait::markdownToAnsi() (opens new window), which provides some basic formatting for long messages. All methods write to stdout—use $this->stderr() if you need to target a particular output stream.

You can also format messages directly, using yii\console\Controller::stdout() (opens new window). Additional craft\helpers\Console (opens new window) constants can be passed after the first argument (the message itself) to decorate the text output:

use craft\helpers\Console;

$this->stdout(
    'This message will be bold and vibrant!',
    Console::FG_RED,
    Console::BG_YELLOW,
    Console::BOLD,
    // ...
);