Beam commands

Beam is the command-line interface (CLI) tool that comes bundled with Expanse. It makes it esy to write console commands to help you manage and maintain your Expanse applications.

All commands are accessible via the beam script located in the root of your project, and every Expanse application comes with a set of built-in commands to help you get started. To list all available commands, you can run:

python ./beam list
# or uv run python ./beam list

You can also get help on a specific command by running:

python ./beam help <command-name>
# or uv run python ./beam help <command-name>

Creating commands

In addition to the built-in commands, you can also create your own custom commands to extend the functionality of Beam. To create a new command, you need to create a new Python file in the app/console/commands folder of your project. For example, to create a command called mail send, you would create a file called mail/send.py in that folder.

from expanse.console.commands.command import Command


class MailSendCommand(Command):
    name = "mail send"
    description = "Send a test email"

    def handle(self) -> None:
        # Your command logic goes here
        self.line("Sending test email...")

All your logic should go inside the handle method. The handle method can be synchronous or asynchronous, depending on your needs, and supports dependency injection just like controllers. For instance, if the email are sent via a service, you can inject it directly into the method:

from expanse.console.commands.command import Command
from app.services.email_service import EmailService


class MailSendCommand(Command):
    name = "mail send"
    description = "Send a test email"

    def handle(self, email_service: EmailService) -> None:
        email_service.send_test_email()
        self.success("Test email sent successfully!")
from expanse.console.commands.command import Command
from app.services.email_service import AsyncEmailService


class MailSendCommand(Command):
    name = "mail send"
    description = "Send a test email"

    async def handle(self, email_service: AsyncEmailService) -> None:
        await email_service.send_test_email()
        self.success("Test email sent successfully!")

Declaring command arguments and options

Most commands require additional input to function properly, either through arguments or options. Beam allows you to declare these inputs directly in your command class using the arguments and options attributes.

Arguments

Arguments are positional inputs that are required for the command to execute.

from cleo.helpers import argument
from expanse.console.commands.command import Command

class MailSendCommand(Command):
    name = "mail send"
    description = "Send a test email"

    arguments = [
        argument("user", "The user to send the email to")
    ]

Arguments can be accessed using the argument method:

def handle(self) -> None:
    user = self.argument("user")

You may also declare optional arguments by setting the optional parameter to True:

from cleo.helpers import argument

argument("user", "The user to send the email to", optional=True)

If an optional argument is not provided, its value will be None unless you specify a default value.

from cleo.helpers import argument

argument("user", "The user to send the email to", optional=True, default="admin")

Options

Options are named inputs that are typically prefixed with -- when used in the command line. They can be either required or optional.

from cleo.helpers import option
from expanse.console.commands.command import Command

class MailSendCommand(Command):
    name = "mail send"
    description = "Send a test email"

    options = [
        option("secure", description="Whether to use a secure connection")
    ]
python ./beam mail send --secure

By default, options are considered flags which means they do not require a value. If the option is provided in the command line, its value will be True, otherwise it will be False.

If you want to specify a value for an option, you can set the flag parameter to False:

from cleo.helpers import option

option("subject", description="The subject of the email", flag=False)
python ./beam mail send --subject "Welcome to Expanse"

Also, if you want to assign a one-letter shortcut to an option, you can use the shortcut parameter:

from cleo.helpers import option

option("subject", "s", description="The subject of the email", flag=False)
python ./beam mail send -s "Welcome to Expanse"