# Lazy Loading

URL: /milo-cli/docs/build-clis/lazy/
Section: build-clis
Description: Deferred command imports for fast CLI startup with large command sets.

---

> For a complete page index, fetch /milo-cli/llms.txt.

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:

```python
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:

```python
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/list` work without importing any handler modules.

## Lazy commands in groups

Groups support lazy loading too:

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

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

## How it works

`LazyCommandDef` stores 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 full `CommandDef` — 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.command` decorator is simpler and equally fast.

:::{tip}
Combine pre-computed schemas with `--llms-txt` and `--mcp` to let AI agents discover all your commands without triggering any imports.
:::
