CLI Overview
The Ascender Framework provides a powerful and flexible Command Line Interface (CLI) system that allows you to create custom commands for your application. The CLI system supports two distinct command patterns to handle different use cases and integrates seamlessly with the framework's dependency injection system.
Features
- Type-Safe Commands: Automatic type detection and validation
- Decorator-Based: Clean, intuitive command definition using
@Commandand@Handlerdecorators - Dual Command Types: Support for both single commands (BasicCLI) and command groups (GenericCLI)
- Beautiful Error Messages: Rich, colorful error panels powered by rich-argparse
- Async Support: Full support for async/await in command handlers
- Class-Attribute Parameters: Define arguments as class attributes using
Parameter()for BasicCLI - Handler Parameters: Use method parameters for GenericCLI subcommands
- Dependency Injection: Commands are automatically registered via
useCLIprovider - Automatic Help Generation: Built-in help system with beautiful formatting
- Flexible Arguments: Support for positional, optional, boolean flags, and more
- Extensible: Easy to add new commands and extend functionality
Command Types
The CLI engine supports two fundamental command types:
BasicCLI Commands
Single-action commands that execute one specific task. Perfect for standalone operations like displaying version information, building applications, or running initialization scripts.
Pattern: ascender <command> [options]
GenericCLI Commands
Multi-command groups that contain related subcommands. Ideal for organizing related functionality like code generation, database operations, or testing workflows.
Pattern: ascender <group> <subcommand> [options]
Running Commands
There are two ways to invoke CLI in Ascender:
- Global CLI (tooling):
- Pattern:
ascender [command] -
Examples:
ascender new --name myapp --orm-mode tortoiseascender serve
-
Local project wrapper (short form):
- Pattern:
ascender run [command] - Purpose: wraps local project entrypoints and CLI scripts (shorter than
poetry run python src/main.py) - Examples:
ascender run serveascender run testsascender run tests init(planned scaffolder: createssrc/tests/samples andpytest.ini)
Getting Started
To create your first command, you'll need to:
- Import the necessary classes and decorators
- Choose between BasicCLI or GenericCLI based on your needs
- Define parameters appropriately for each type
- Implement the required methods
- Register your command using the
useCLIprovider
from ascender.core.cli_engine import Command, Handler, BasicCLI, GenericCLI, Parameter, useCLI
# BasicCLI: Parameters are class attributes
@Command(name="hello", description="Say hello to the world")
class HelloCommand(BasicCLI):
name: str = Parameter(
"World",
description="Name to greet",
names=["--name", "-n"]
)
def execute(self) -> None:
print(f"Hello, {self.name}!")
# GenericCLI: Parameters are method arguments
@Command(name="greet", description="Greeting commands")
class GreetCommand(GenericCLI):
@Handler("morning", description="Morning greeting")
def morning(self, name: str = "World", **kwargs) -> None:
print(f"Good morning, {name}!")
@Handler("evening", description="Evening greeting")
async def evening(self, name: str = "World", **kwargs) -> None:
print(f"Good evening, {name}!")
# Register commands using useCLI provider
providers = [
useCLI(HelloCommand),
useCLI(GreetCommand),
]
Architecture
The CLI system uses a modular, DI-integrated architecture:
- Command Decorator (
@Command): Handles command metadata and type detection - Handler Decorator (
@Handler): Registers GenericCLI subcommands with async support - useCLI Provider: Registers commands with the framework's DI system
- Application Integration: CLI engine is automatically configured in the Application
- Command Protocols: Define the interface for BasicCLI and GenericCLI
- Parameter System: Class attributes (BasicCLI) or method parameters (GenericCLI)
- Rich Formatting: Beautiful help messages and error panels using rich-argparse
- Type Detection: Automatic identification of command types
This design ensures that commands are easy to create, maintain, and extend while providing a consistent developer experience and seamless integration with the framework's dependency injection system.
Next Steps
- Learn about Command Types to understand the differences between BasicCLI and GenericCLI
- Follow the Creating Commands guide to build your first command
- Explore Examples to see real-world command implementations