Plugin Development Guide
RouteRTL uses Python entry points to discover and load external CLI
plugins. Any installed package can extend the routertl CLI with
new commands.
How It Works
At startup, routertl calls:
importlib.metadata.entry_points(group="routertl.plugins")
Each entry point must resolve to a Click command or group. The entry point's name becomes the CLI subcommand name.
Quickstart
1. Create Your Plugin Package
my-routertl-plugin/ ├── pyproject.toml └── my_plugin/ ├── __init__.py └── cli.py
2. Define a Click Command
# my_plugin/cli.py
import click
@click.command()
@click.argument("name")
def greet(name):
"""Say hello from a plugin."""
click.echo(f"Hello, {name}! 👋 (from my-routertl-plugin)")
3. Register the Entry Point
In your pyproject.toml:
[project]
name = "my-routertl-plugin"
version = "0.1.0"
[project.entry-points."routertl.plugins"]
greet = "my_plugin.cli:greet"
4. Install & Use
pip install -e ./my-routertl-plugin
routertl greet World
# Hello, World! 👋 (from my-routertl-plugin)
Plugin Contract
| Requirement | Details |
|---|---|
| Entry point group | routertl.plugins |
| Return type | click.BaseCommand (command or group) |
| Naming | Entry point name = CLI subcommand name |
| Failures | Logged as warnings; never crash the CLI |
Advanced: Plugin Groups
You can expose an entire command group:
# my_plugin/cli.py
import click
@click.group()
def tools():
"""My custom tool suite."""
@tools.command()
def lint():
"""Custom linting."""
click.echo("Running custom lint...")
@tools.command()
def report():
"""Custom report."""
click.echo("Running custom report...")
[project.entry-points."routertl.plugins"]
tools = "my_plugin.cli:tools"
This creates routertl tools lint and routertl tools report.
Debugging
Run with --verbose to see plugin loading diagnostics:
routertl --verbose greet World
Failed plugins emit a warning but never prevent the CLI from starting.
Compatibility
- Python ≥ 3.10
- Click ≥ 8.0
- Works with both
pip install -e .and regularpip install