Tempest is still a work in progress. Visit our GitHub or Discord


tempest/console has support for middleware, a well known concept within the context of web applications, which also makes building a lot of console features easier.

Console middleware can be applied both globally (to all console commands), or on a per-command basis.

The global middleware stack is defined within ConsoleConfig. Note that the default stack is provided out of the box, you only need to add a custom config file if you want to change this stack.

// Config/console.php

use Tempest\Console\ConsoleConfig;

return new ConsoleConfig(
    // …
    middleware: [

Individual middleware can be added on top of this stack by passing it into the #[ConsoleCommand] attribute:

final readonly class ForceCommand
        middleware: [ForceMiddleware::class]
    public function __invoke(): void { /* … */ }

Let's take a look at the built-in middleware that Tempest provides.


Renders the console command overview when no specific command is provided.



 install [--force=false] - Interactively install Tempest in your project
 routes - List all registered routes
 serve [host='localhost:8000'] [publicDir='public/'] - Start a PHP development server

/* … */


Shows a list of similar commands when you mistyped a command:

./tempest migrate

Command migrate not found 
Did you mean to run one of these? 
[x] migrate:down
[ ] migrate:up

Press enter to confirm, ctrl+c to cancel


Handles exceptions that while running a console command.

./tempest fail

A message from the exception default 

18 }
20 function failingFunction(string $string)
21 {
22     throw new Exception("A message from the exception {$string}"); < 
23 }



Adds the global --help and -h flags to all commands.

./tempest serve --help  
Usage serve [host='localhost:8000'] [publicDir='public/'] - Start a PHP development server


Adds the global --force and -f flags to all commands. Using these flags will cause tempest to skip all $console->confirm() calls.

    middleware: [ForceMiddleware::class]
public function __invoke(): void
    // This part will be skipped when the `-f` flag is applied
    if (! $this->console->confirm('continue?')) {



Adds a warning before running the command in production or staging.

    middleware: [CautionMiddleware::class]
public function __invoke(): void
    $this->console->error('something cautionous');
Caution! Do you wish to continue? [yes/no] 
something cautionous 

Building your own middleware

You can create your own middleware by implementing the ConsoleMiddleware interface:

use Tempest\Console\ConsoleMiddleware;

final readonly class HelloWorldMiddleware implements ConsoleMiddleware
    public function __construct(private Console $console)

    public function __invoke(Invocation $invocation, callable $next): ExitCode
        if ($invocation->argumentBag->get('hello')) {
            $this->console->writeln('Hello world!')

        return $next($invocation);

Middleware classes will be autowired by the container, so you can use the constructor to inject any dependency you'd like. The Invocation object contains everything you need about the context for the current console command invocation:

  • $invocation->argumentBag contains the argument bag with all the input provided by the user.
  • $invocation->consoleCommand an instance of the #[ConsoleCommand] attribute for the matched console command. This property will be null if you're not using ResolveOrRescueMiddleware or if your middleware runs before it.