Lazy Loading

Deferred command imports for fast CLI startup with large command sets.

1 min read 299 words

Lazy loading defers the import of command handler modules until the command is actually invoked. This keeps CLI startup fast even with dozens of commands that have heavy dependencies.

lazy_command

Register a command with a dotted import path instead of a function reference:

from milo import CLI

cli = CLI(name="myapp")

cli.lazy_command(
    "deploy",
    "myapp.commands.deploy:deploy_handler",
    description="Deploy to an environment",
)

The module myapp.commands.deploy is not imported until someone runs myapp deploy. All other commands start instantly.

Pre-computed schemas

By default, the schema is generated by importing the handler and inspecting its signature. To avoid even that import, provide the schema upfront:

cli.lazy_command(
    "deploy",
    "myapp.commands.deploy:deploy_handler",
    description="Deploy to an environment",
    schema={
        "type": "object",
        "properties": {
            "target": {"type": "string"},
            "dry_run": {"type": "boolean"},
        },
        "required": ["target"],
    },
)

With a pre-computed schema, --llms-txt and --mcp tools/listwork without importing any handler modules.

Lazy commands in groups

Groups support lazy loading too:

site = cli.group("site", description="Site operations")

site.lazy_command(
    "build",
    "myapp.commands.site:build_handler",
    description="Build the site",
)

How it works

LazyCommandDefstores the import path and defers resolution:

  1. On registration, only the name, description, and optional schema are stored
  2. On first invocation,resolve()imports the module and extracts the handler
  3. The result is cached as a fullCommandDef— subsequent calls skip the import

Resolution is thread-safe (uses a lock with double-check pattern).

When to use lazy loading

  • CLIs with many commands where only one runs per invocation
  • Commands that import heavy dependencies (cloud SDKs, ML libraries)
  • Plugin systems where third-party command modules may not be installed

For small CLIs with lightweight imports, the@cli.commanddecorator is simpler and equally fast.

Tip

Combine pre-computed schemas with--llms-txt and --mcpto let AI agents discover all your commands without triggering any imports.