CLI command plugins - Betty documentation

Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
View this page
Toggle table of contents sidebar

# CLI command plugins

Type | `betty.cli.commands.Command`
Repository | `betty.cli.commands.COMMAND_REPOSITORY`

Betty’s Command Line Interface allows you to run Betty by invoking commands. These commands are built using Click.

## Creating a command

1. Create a new class that extends `betty.cli.commands.Command` and implements the abstract methods, for example:

       from typing import override
       from betty.cli.commands import Command
       from betty.machine_name import MachineName

       class MyCommand(Command):
         @override
         @classmethod
         def plugin_id(cls) -> MachineName:
             return "my-module-my-command"

         # Implement remaining abstract methods...
         ...

2. Tell Betty about your command by registering it as an entry point. Given the command above in a module `my_package.my_module`, add the following to your Python package:

   pyproject.toml

       [project.entry-points.'betty.command']
       'my-module-my-command' = 'my_package.my_module.MyCommand'

   setup.py

       SETUP = {
           'entry_points': {
               'betty.command': [
                   'my-module-my-command=my_package.my_module.MyCommand',
               ],
           },
       }
       if __name__ == '__main__':
           setup(**SETUP)

3. Build the Click command, decorated with `betty.cli.commands.command()` (which works almost identically to `asyncclick.command()`), by returning it from your `betty.cli.commands.Command.click_command()` implementation:

       from typing import override
       import click
       from betty.cli.commands import Command, command
       from betty.machine_name import MachineName

       class MyCommand(Command):
         @override
         async def click_command(self) -> click.Command:
             @command
             def my_command() -> Any:
               # Implement your Click command.
               ...
             return my_command

         # Implement remaining abstract methods...
         ...

   Building your Click command in your Command plugin allows you to access to all of Betty’s `async` functionality.

### Project-specific commands

To make your command use a specific Betty project, use the `betty.cli.commands.project_option()` decorator:

    from betty.project import Project
    from betty.cli.commands import command, project_option

    @command
    @project_option
    async def my_command(project: Project) -> None:
      # Do what your command needs to do here...
      ...

This also gives you access to the Betty application through `betty.project.Project.app`.

### Accessing the application

Access the currently running `betty.app.App` anywhere in your `Command` plugin via `self._app`.

## See also

Read more about how to use the Command Line Interface and Betty’s built-in commands at The command line.