CLI Architecture¶
This article documents the architectural design of Hatch's command-line interface, which underwent a significant refactoring from a monolithic structure to a modular, handler-based architecture.
Overview¶
The Hatch CLI provides a comprehensive interface for managing MCP server packages, environments, and host configurations. The architecture emphasizes:
- Modularity: Commands organized into focused handler modules
- Consistency: Unified output formatting across all commands
- Extensibility: Easy addition of new commands and features
- Testability: Clear separation of concerns for unit testing
Architecture Components¶
Entry Point (hatch/cli/__main__.py)¶
The entry point module serves as the routing layer:
- Argument Parsing: Uses
argparsewith customHatchArgumentParserfor formatted error messages - Manager Initialization: Creates shared
HatchEnvironmentManagerandMCPHostConfigurationManagerinstances - Manager Attachment: Attaches managers to the
argsnamespace for handler access - Command Routing: Routes parsed commands to appropriate handler modules
Key Pattern:
# Managers initialized once and shared across handlers
env_manager = HatchEnvironmentManager(...)
mcp_manager = MCPHostConfigurationManager()
# Attached to args for handler access
args.env_manager = env_manager
args.mcp_manager = mcp_manager
# Routed to handlers
return _route_env_command(args)
Handler Modules¶
Commands are organized into four domain-specific handler modules:
cli_env.py - Environment Management¶
Handles environment lifecycle and Python environment operations:
- handle_env_create(): Create new environments
- handle_env_remove(): Remove environments with confirmation
- handle_env_list(): List environments with table output
- handle_env_use(): Set current environment
- handle_env_current(): Show current environment
- handle_env_show(): Detailed hierarchical environment view
- handle_env_list_hosts(): Environment/host/server deployments
- handle_env_list_servers(): Environment/server/host deployments
- handle_env_python_*(): Python environment operations
cli_package.py - Package Management¶
Handles package installation and synchronization:
- handle_package_add(): Add packages to environments
- handle_package_remove(): Remove packages with confirmation
- handle_package_list(): List packages (deprecated - use env list)
- handle_package_sync(): Synchronize package MCP servers to hosts
- _configure_packages_on_hosts(): Shared configuration logic
cli_mcp.py - MCP Host Configuration¶
Handles MCP host platform configuration and backup:
- handle_mcp_discover_hosts(): Detect available host platforms
- handle_mcp_list_hosts(): Host-centric server listing
- handle_mcp_list_servers(): Server-centric host listing
- handle_mcp_show_hosts(): Detailed host configurations
- handle_mcp_show_servers(): Detailed server configurations
- handle_mcp_configure(): Configure servers on hosts
- handle_mcp_backup_*(): Backup management operations
- handle_mcp_remove_*(): Server and host removal
- handle_mcp_sync(): Synchronize configurations
cli_system.py - System Operations¶
Handles package creation and validation:
- handle_create(): Generate package templates
- handle_validate(): Validate package structure
Shared Utilities (cli_utils.py)¶
The utilities module provides infrastructure used across all handlers:
Color System¶
Colorenum: HCL color palette with true color support and 16-color fallback- Dual-tense colors: Dim colors for prompts (present tense), bright colors for results (past tense)
- Semantic mapping: Colors mapped to action categories (green=constructive, red=destructive, etc.)
_colors_enabled(): RespectsNO_COLORenvironment variable and TTY detection
ConsequenceType System¶
ConsequenceTypeenum: Action types with dual-tense labels- Prompt labels: Present tense for confirmation (e.g., "CREATE")
- Result labels: Past tense for execution (e.g., "CREATED")
- Color association: Each type has prompt and result colors
- Categories: Constructive, Recovery, Destructive, Modification, Transfer, Informational, No-op
ResultReporter¶
Unified rendering system for all CLI output:
Key Features: - Tracks consequences (actions to be performed) - Generates confirmation prompts (present tense, dim colors) - Reports execution results (past tense, bright colors) - Supports nested consequences (resource → field level) - Handles dry-run mode with suffix labels - Provides error and partial success reporting
Usage Pattern:
reporter = ResultReporter("hatch env create", dry_run=False)
reporter.add(ConsequenceType.CREATE, "Environment 'dev'")
reporter.add(ConsequenceType.CREATE, "Python environment (3.11)")
# Show prompt and get confirmation
prompt = reporter.report_prompt()
if prompt:
print(prompt)
if not request_confirmation("Proceed?"):
return EXIT_SUCCESS
# Execute operation...
# Report results
reporter.report_result()
TableFormatter¶
Aligned table output for list commands:
Features: - Fixed and auto-calculated column widths - Left/right/center alignment support - Automatic truncation with ellipsis - Consistent header and separator rendering
Usage Pattern:
columns = [
ColumnDef(name="Name", width=20),
ColumnDef(name="Status", width=10),
ColumnDef(name="Count", width="auto", align="right"),
]
formatter = TableFormatter(columns)
formatter.add_row(["my-env", "active", "5"])
print(formatter.render())
Error Formatting¶
ValidationError: Structured validation errors with field and suggestionformat_validation_error(): Formatted error output with colorformat_info(): Info messages with [INFO] prefixformat_warning(): Warning messages with [WARNING] prefix
Parsing Utilities¶
parse_env_vars(): Parse KEY=VALUE environment variablesparse_header(): Parse KEY=VALUE HTTP headersparse_input(): Parse VS Code input variable definitionsparse_host_list(): Parse comma-separated hosts or 'all'get_package_mcp_server_config(): Extract MCP config from package metadata
Handler Signature Convention¶
All handlers follow a consistent signature:
def handle_command(args: Namespace) -> int:
"""Handle 'hatch command' command.
Args:
args: Namespace with:
- env_manager: HatchEnvironmentManager instance
- mcp_manager: MCPHostConfigurationManager instance (if needed)
- <command-specific arguments>
Returns:
Exit code (0 for success, 1 for error)
"""
Key Invariants:
- Managers accessed via args.env_manager and args.mcp_manager
- Return EXIT_SUCCESS (0) on success, EXIT_ERROR (1) on failure
- Use ResultReporter for unified output
- Handle dry-run mode consistently
- Request confirmation for destructive operations
Output Formatting Standards¶
Mutation Commands¶
Commands that modify state follow this pattern:
- Build consequences: Add all actions to
ResultReporter - Show prompt: Display present-tense preview with dim colors
- Request confirmation: Use
request_confirmation()unless auto-approved - Execute: Perform the actual operations
- Report results: Display past-tense results with bright colors
List Commands¶
Commands that display data use TableFormatter:
- Define columns: Specify widths and alignment
- Add rows: Populate with data
- Render: Print formatted table with headers and separator
Show Commands¶
Commands that display detailed views use hierarchical output:
- Header: Entity name with
highlight()for emphasis - Metadata: Key-value pairs with indentation
- Sections: Grouped related information
- Separators: Use
═for visual separation between entities
Exit Code Standards¶
EXIT_SUCCESS(0): Operation completed successfullyEXIT_ERROR(1): Operation failed or validation error- Partial success: Return
EXIT_ERRORbut usereport_partial_success()
Design Principles¶
Separation of Concerns¶
- Routing:
__main__.pyhandles argument parsing and routing only - Business logic: Handler modules implement command logic
- Presentation:
cli_utils.pyprovides formatting infrastructure - Domain logic: Managers (
HatchEnvironmentManager,MCPHostConfigurationManager) handle state
DRY (Don't Repeat Yourself)¶
- Shared utilities in
cli_utils.pyeliminate duplication ResultReporterprovides consistent output across all commandsTableFormatterstandardizes list output- Parsing utilities handle common argument formats
Consistency¶
- All handlers follow the same signature pattern
- All mutation commands use
ResultReporter - All list commands use
TableFormatter - All errors use structured formatting
Testability¶
- Handlers are pure functions (input → output)
- Managers injected via
argsnamespace (dependency injection) - Clear separation between CLI and business logic
- Utilities are independently testable
Command Organization¶
Namespace Structure¶
hatch
├── create <name> # System: Package template creation
├── validate <path> # System: Package validation
├── env # Environment management
│ ├── create <name>
│ ├── remove <name>
│ ├── list [hosts|servers]
│ ├── use <name>
│ ├── current
│ ├── show <name>
│ └── python
│ ├── init
│ ├── info
│ ├── remove
│ ├── shell
│ └── add-hatch-mcp
├── package # Package management
│ ├── add <name>
│ ├── remove <name>
│ ├── list (deprecated)
│ └── sync <name>
└── mcp # MCP host configuration
├── discover
│ ├── hosts
│ └── servers
├── list
│ ├── hosts
│ └── servers
├── show
│ ├── hosts
│ └── servers
├── configure <host> <server>
├── remove
│ ├── server <name>
│ └── host <name>
├── sync
└── backup
├── restore <host>
├── list <host>
└── clean <host>
Related Documentation¶
- Adding CLI Commands: Step-by-step guide for adding new commands
- Component Architecture: Overall system architecture
- CLI Reference: User-facing command documentation