CLI Framework (Topia)
Azu CLI is built on top of Topia, a modern, high-performance task automation framework built with Crystal. Topia provides the foundation for command parsing, task execution, and the overall CLI architecture.
Overview
Topia is a Crystal-powered task automation and build pipeline framework that transforms development workflows. It provides:
- Code over Configuration - Write workflows in pure Crystal, no complex config files 
- High Performance - Built for speed with async operations, caching, and parallelism 
- Composable - Chain tasks, plugins, and commands like building blocks 
- Type Safe - Leverage Crystal's compile-time type checking for bulletproof workflows 
- Developer Friendly - Professional CLI, interactive modes, and comprehensive debugging tools 
Core Components
Task System
Topia's task system is the foundation of Azu CLI's command execution:
# Simple command task
Topia.task("build")
  .describe("Build the application")
  .command("crystal build --release src/main.cr")
# Task with dependencies
Topia.task("test")
  .describe("Run tests")
  .depends_on("build")
  .command("crystal spec")
# Task with file watching
Topia.task("dev")
  .describe("Development server with hot reload")
  .src("./src/**/*.cr")
  .pipe(FileWatcher.new)
  .command("crystal run src/main.cr")Command Execution
Topia provides robust command execution with error handling and output management:
class Azu::Commands::Base
  include Topia::Command
  def execute_command(command : String, args : Array(String) = [] of String)
    Topia::Command.execute(command, args) do |result|
      case result
      when .success?
        Azu::Logger.info("Command executed successfully")
      when .failure?
        Azu::Logger.error("Command failed: #{result.error}")
        raise CommandError.new("Command execution failed")
      end
    end
  end
endPlugin System
Topia's plugin system allows Azu CLI to extend functionality through composable plugins:
# File processing plugin for code generation
class FileProcessor < Topia::BasePlugin
  def run(input, args)
    case input
    when Array(Topia::InputFile)
      announce "Processing #{input.size} files..."
      input.map { |file| process_file(file) }
    else
      error "Expected Array(InputFile), got #{input.class}"
      input
    end
  end
  private def process_file(file : Topia::InputFile)
    # Process file content
    file.contents = file.contents.gsub(/old/, "new")
    file
  end
endCLI Architecture
Command Parsing
Topia provides automatic command-line argument parsing:
# Azu CLI command structure
class Azu::CLI
  include Topia::CLI
  def initialize
    @parser = Topia::Parser.new do |parser|
      parser.banner = "Azu CLI - Crystal web framework command line tool"
      parser.on("new PROJECT_NAME", "Create a new Azu project") do |name|
        Azu::Commands::New.new(name).call
      end
      parser.on("generate TYPE NAME", "Generate code") do |type, name|
        Azu::Commands::Generate.new(type, name).call
      end
      parser.on("serve", "Start development server") do
        Azu::Commands::Serve.new.call
      end
    end
  end
  def run(args = ARGV)
    @parser.parse(args)
  end
endSubcommand Support
Topia enables hierarchical command structures:
# Generate command with subcommands
class Azu::Commands::Generate < Azu::Commands::Base
  def call
    case @subcommand
    when "model"
      Azu::Generators::Model.new(@name, @options).generate
    when "endpoint"
      Azu::Generators::Endpoint.new(@name, @options).generate
    when "scaffold"
      Azu::Generators::Scaffold.new(@name, @options).generate
    else
      raise ArgumentError.new("Unknown generator type: #{@subcommand}")
    end
  end
endPerformance Features
Async Operations
Topia provides non-blocking operations for better performance:
# Async file watching for development server
class Azu::Commands::Serve < Azu::Commands::Base
  def call
    Topia.task("serve")
      .src("./src/**/*.cr")
      .pipe(AsyncFileWatcher.new)
      .command("crystal run src/main.cr")
      .run
  end
end
class AsyncFileWatcher < Topia::BasePlugin
  def run(input, args)
    spawn do
      watch_files(input)
    end
    input
  end
  private def watch_files(files)
    # Non-blocking file watching
    files.each do |file|
      if file.modified?
        rebuild_application
      end
    end
  end
endIntelligent Caching
Topia provides automatic caching based on input file checksums and command signatures:
# Cached task execution
Topia.task("expensive_build")
  .src("./src/**/*.cr")
  .pipe(SlowCompiler.new)
  .dist("./build/")
  .cache(true)  # Enable caching
# First run: Full execution
# Subsequent runs: Instant cache hits (if nothing changed)Parallel Execution
Topia supports concurrent task execution for improved performance:
# Parallel test execution
Topia.task("test")
  .parallel(4)  # Run 4 tests in parallel
  .src("./spec/**/*_spec.cr")
  .pipe(TestRunner.new)
  .runConfiguration Integration
Environment Variable Support
Topia integrates with Azu CLI's configuration system:
# Configuration-aware task execution
class Azu::Commands::Database < Azu::Commands::Base
  def call
    config = Azu::Config.current
    Topia.task("database_operation")
      .env({
        "DATABASE_URL" => config.database.url,
        "DB_HOST" => config.database.host,
        "DB_PORT" => config.database.port.to_s
      })
      .command("crystal run db/migrate.cr")
      .run
  end
endYAML Configuration
Topia supports YAML-based configuration:
# topia.yml
tasks:
  build:
    command: "crystal build --release src/main.cr"
    description: "Build the application"
  test:
    command: "crystal spec"
    description: "Run tests"
    depends_on: ["build"]
  serve:
    command: "crystal run src/main.cr"
    description: "Start development server"
    watch: ["src/**/*.cr"]Debugging and Monitoring
Enhanced Debugging
Topia provides comprehensive debugging capabilities:
# Debug mode with detailed logging
Topia.debug = true
# CLI debugging options
./azu_cli -d task_name                    # Debug mode with detailed logging
./azu_cli --verbose --stats task_name     # Verbose output with performance stats
./azu_cli --profile task_name             # Performance profiling
./azu_cli --dependencies task_name        # Analyze task dependencies
./azu_cli --where task_name               # Find task source location
./azu_cli --dry-run task_name             # Preview execution without runningPerformance Metrics
Topia provides detailed performance insights:
# Performance profiling
Topia.task("monitored")
  .describe("Task with rich monitoring")
  .command("long_running_process")
  .profile(true)  # Enable performance profiling
# Automatically tracks:
# - Execution time
# - Success/failure rates
# - Cache hits
# - Memory usage
# - CPU utilizationLifecycle Hooks
Plugin Lifecycle
Topia provides lifecycle hooks for plugins:
class Azu::Generators::Base < Topia::BasePlugin
  def on(event : String)
    case event
    when "pre_run"
      setup_environment
    when "after_run"
      cleanup_resources
    when "error"
      handle_error
    end
  end
  private def setup_environment
    Azu::Logger.info("Setting up generator environment")
    # Initialize generator state
  end
  private def cleanup_resources
    Azu::Logger.info("Cleaning up generator resources")
    # Clean up temporary files
  end
  private def handle_error
    Azu::Logger.error("Generator encountered an error")
    # Error recovery logic
  end
endIntegration with Azu CLI
Command Structure
Azu CLI uses Topia's command system for all CLI operations:
# Main CLI entry point
class Azu::CLI
  include Topia::CLI
  def initialize
    setup_commands
    setup_middleware
  end
  private def setup_commands
    # Project management commands
    register_command("new", Azu::Commands::New)
    register_command("init", Azu::Commands::Init)
    # Code generation commands
    register_command("generate", Azu::Commands::Generate)
    # Database commands
    register_command("db", Azu::Commands::Database)
    # Development commands
    register_command("serve", Azu::Commands::Serve)
    register_command("dev", Azu::Commands::Dev)
  end
  private def setup_middleware
    # Add middleware for logging, error handling, etc.
    use(Azu::Middleware::Logging)
    use(Azu::Middleware::ErrorHandler)
  end
endError Handling
Topia provides robust error handling for Azu CLI:
class Azu::Middleware::ErrorHandler < Topia::Middleware
  def call(context : Topia::Context) : Topia::Context
    begin
      call_next(context)
    rescue ex : Azu::Error
      Azu::Logger.error("Azu CLI error: #{ex.message}")
      context.exit_code = 1
    rescue ex : Exception
      Azu::Logger.error("Unexpected error: #{ex.message}")
      Azu::Logger.debug(ex.backtrace.join("\n"))
      context.exit_code = 1
    end
    context
  end
endPerformance Benefits
Before Topia Integration
- Build time: 45s 
- CPU usage: 15% (spinner) 
- Memory: Growing over time 
- Cache hits: 0% 
After Topia Integration
- Build time: 12s (with parallelism + caching) 
- CPU usage: <1% (async spinner) 
- Memory: Stable with cleanup 
- Cache hits: 85%+ 
Real-World Results
- Medium project (50 files): 40s → 8s (5x faster) 
- Large project (200+ files): 3min → 45s (4x faster) 
- CI pipeline: 8min → 2min (4x faster) 
Best Practices
Task Design
- Keep tasks focused: Each task should have a single responsibility 
- Use dependencies: Leverage Topia's dependency system for proper ordering 
- Enable caching: Use caching for expensive operations 
- Profile performance: Use Topia's profiling tools to identify bottlenecks 
Plugin Development
- Follow the interface: Implement - Topia::BasePlugincorrectly
- Handle errors gracefully: Provide meaningful error messages 
- Use lifecycle hooks: Implement proper setup and cleanup 
- Document your plugin: Provide clear documentation for users 
Configuration
- Use environment variables: For sensitive configuration 
- Provide defaults: Always provide sensible default values 
- Validate configuration: Use Topia's validation features 
- Keep it simple: Avoid overly complex configuration structures 
Related Documentation
- Topia Repository - Official Topia documentation 
- Architecture Overview - Overall Azu CLI architecture 
- Generator System - Code generation architecture 
- Configuration System - Configuration management 
- Plugin System - Plugin development guide 
Last updated