### Full Example: Greet Command with Configuration Source: https://github.com/thatxliner/xclif/blob/main/docs/config.md Demonstrates a complete example of a 'greet' command that utilizes `WithConfig` for parameters and shows how to initialize the `Cli` with a local configuration file. ```python # routes/greet.py from xclif import WithConfig, command @command() def _(name: WithConfig[str] = "", template: WithConfig[str] = "Hello, {}!") -> None: """Greet someone by name.""" if not name: print("Error: provide a name or set one with `myapp config set name `") return print(template.format(name)) ``` ```python # __main__.py from xclif import Cli from . import routes cli = Cli.from_routes(routes, local_config=".myapp.toml") if __name__ == "__main__": cli() ``` -------------------------------- ### Route Discovery Example Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Illustrates route discovery using `pkgutil.walk_packages` to find modules exporting a `Command`. ```python # pkgutil.walk_packages finds modules under a routes package; each module exports one Command ``` -------------------------------- ### Execute Poetry Commands via Xclif Source: https://github.com/thatxliner/xclif/blob/main/examples/poetry-clone/README.md Examples of how to invoke various Poetry commands through the Xclif-based clone. These commands demonstrate environment activation, updating Poetry, and listing installed plugins. ```bash python -m poetry env use 3.11 ``` ```bash python -m poetry self update ``` ```bash python -m poetry self update --preview ``` ```bash python -m poetry self show plugins ``` -------------------------------- ### Example Usage of Variadic Arguments Source: https://github.com/thatxliner/xclif/blob/main/docs/options.md Shows how to invoke a command that accepts multiple variadic arguments. ```default myapp add file1.py file2.py file3.py ``` -------------------------------- ### Interspersed Options CLI Example Source: https://github.com/thatxliner/xclif/blob/main/docs/design/option-system.md Shows that options and positional arguments can be in any order at the same command level. Both examples are valid. ```bash myapp greet --template "Hi, {}!" Alice ``` ```bash myapp greet Alice --template "Hi, {}!" # both valid ``` -------------------------------- ### Run Framework Benchmarks Source: https://github.com/thatxliner/xclif/blob/main/README.md Execute this bash script to reproduce the startup time benchmarks. Requires the `hyperfine` tool to be installed. ```bash bash benchmarks/bench_frameworks.sh ``` -------------------------------- ### Example Usage of Positional Arguments Source: https://github.com/thatxliner/xclif/blob/main/docs/options.md Demonstrates how to call a command with defined positional arguments. ```default myapp copy file.txt /tmp/ ``` -------------------------------- ### Example Usage of Options Source: https://github.com/thatxliner/xclif/blob/main/docs/options.md Illustrates calling a command with and without providing an optional argument, and using its short alias. ```default myapp greet Alice myapp greet Alice --template "Hi, {}!" myapp greet Alice -t "Hi, {}!" # auto-generated short alias ``` -------------------------------- ### Install Xclif Source: https://context7.com/thatxliner/xclif/llms.txt Install the Xclif package using pip or uv. Requires Python 3.12+. ```bash pip install xclif # or uv add xclif ``` -------------------------------- ### Example Usage of Interspersed Options and Arguments Source: https://github.com/thatxliner/xclif/blob/main/docs/options.md Illustrates that options and positional arguments can be provided in any order. ```default myapp greet --template "Hi!" Alice myapp greet Alice --template "Hi!" # both valid ``` -------------------------------- ### Example Usage of Repeatable Options Source: https://github.com/thatxliner/xclif/blob/main/docs/options.md Shows how to use a repeatable option multiple times to provide a list of values. ```default myapp publish --tag latest --tag stable # tag = ["latest", "stable"] ``` -------------------------------- ### Configuration priority examples Source: https://context7.com/thatxliner/xclif/llms.txt Illustrates the priority order for configuration values: CLI flag, environment variable, local config file, and user config file. ```bash # Priority 1 — CLI flag (always wins) myapp greet --name Alice # Priority 2 — environment variable export MYAPP_NAME=Alice myapp greet # Priority 3 — local config file (cwd/.myapp.toml) echo 'name = "Alice"' > .myapp.toml myapp greet # Priority 4 — user config file (OS config dir) myapp config set name Alice # writes ~/.config/myapp/config.toml myapp greet # Inspect config myapp config get # print all config values myapp config get name # print one key myapp config path # print config directory ``` -------------------------------- ### TOML User Configuration Example Source: https://github.com/thatxliner/xclif/blob/main/docs/config.md Example of a TOML configuration file used for global settings. Xclif looks for this file in the OS-appropriate config directory. ```toml name = "Alice" template = "Hello, {}!" ``` -------------------------------- ### Route Discovery Example Source: https://github.com/thatxliner/xclif/blob/main/ARCHITECTURE.md Illustrates how the module path determines the command tree structure. Intermediate namespace commands are auto-created with a default action. ```text routes/__init__.py → root command routes/greet.py → root.subcommands["greet"] routes/config/__init__.py → root.subcommands["config"] (namespace) routes/config/set.py → root.subcommands["config"].subcommands["set"] ``` -------------------------------- ### Install Xclif with uv Source: https://github.com/thatxliner/xclif/blob/main/docs/getting-started.md Use this command to install the Xclif package using uv. Requires Python 3.12 or later. ```bash uv add xclif ``` -------------------------------- ### Dispatch Example Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Illustrates the dispatch mechanism, handling implicit options, context cascading, recursion, and leaf execution. ```python # handles implicit options (help/version/verbose), cascading context, subcommand recursion, then leaf execution ``` -------------------------------- ### Initialize Xclif Application Entry Point Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md Construct the main entry point for an Xclif application. Typically created using from_routes() or from_manifest() for easier setup. ```python class Cli(root_command, version=None, env_prefix=None, config_name=None, local_config=None, config_command=True): pass ``` -------------------------------- ### Configuration Loading Priority Examples Source: https://github.com/thatxliner/xclif/blob/main/docs/config.md Illustrates the different ways to provide configuration values to an Xclif application, showing the priority order from highest (CLI flag) to lowest (default value). ```bash # CLI flag (highest priority) myapp greet --name Alice # Environment variable export MYAPP_NAME=Alice myapp greet # Local config file (.myapp.toml in cwd) echo 'name = "Alice"' > .myapp.toml myapp greet # User config file (OS config directory) myapp config set name Alice myapp greet # Check config myapp config get myapp config path ``` -------------------------------- ### Install Xclif with pip Source: https://github.com/thatxliner/xclif/blob/main/docs/getting-started.md Use this command to install the Xclif package using pip. Requires Python 3.12 or later. ```bash pip install xclif ``` -------------------------------- ### Example Usage of Constrained Choices Source: https://github.com/thatxliner/xclif/blob/main/docs/options.md Demonstrates valid and invalid inputs for a command with a constrained choice parameter. ```default myapp completions bash # ok myapp completions nushell # error: expected one of: bash|zsh|fish ``` -------------------------------- ### Xclif Command Structure Example Source: https://github.com/thatxliner/xclif/blob/main/MANIFESTO.md Illustrates how Xclif uses a directory structure to define CLI commands, mirroring web framework routing. No explicit registration is needed; the file system defines the command hierarchy. ```tree myapp/ └── routes/ ├── __init__.py → myapp ├── greet.py → myapp greet └── server/ ├── __init__.py → myapp server ├── start.py → myapp server start └── stop.py → myapp server stop ``` -------------------------------- ### Greeter Experiment Fixture Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Notes that the greeter experiment in `experiments/greeter/` serves as both an example and an integration test fixture, with `conftest.py` adding it to `sys.path`. ```python # The greeter experiment (experiments/greeter/) is both an example and integration test fixture; conftest.py adds it to sys.path ``` -------------------------------- ### Command Construction Example Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Demonstrates command construction using the `@command()` decorator to introspect function signatures via `inspect.signature`. ```python # @command() decorator introspects function signatures via inspect.signature to build Argument/Option lists ``` -------------------------------- ### Build Command Tree Imperatively with Flat API Source: https://github.com/thatxliner/xclif/blob/main/docs/flat-api.md This example demonstrates how to build a command tree imperatively using the flat API. It defines a root command and then adds subcommands and groups using decorators. This approach is useful for migrating existing applications or for specific performance optimizations. ```python from xclif import Cli from xclif.command import Command root = Command("myapp", lambda: None) cli = Cli(root_command=root) @root.command() def greet(name: str, greeting: str = "Hello") -> None: """Greet someone.""" print(f"{greeting}, {name}!") server = root.group("server") @server.command() def start(host: str = "localhost", port: int = 8080) -> None: """Start the server.""" print(f"Starting on {host}:{port}") @server.command() def stop() -> None: """Stop the server.""" print("Stopping server") if __name__ == "__main__": cli() ``` -------------------------------- ### get(key, default=None) Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md Retrieves a configuration value by its key, returning a default value if the key is not found. ```APIDOC #### get(key, default=None) Return the value for *key*, or *default* if not set. * **Parameters:** * **key** (*str*) * **default** (*object*) * **Return type:** object ``` -------------------------------- ### Run Tests with pytest Source: https://github.com/thatxliner/xclif/blob/main/CONTRIBUTING.md Execute the project's tests using the uv and pytest tools. Ensure you have them installed. ```bash uv run pytest ``` -------------------------------- ### Agent-Optimized Help Output Example Source: https://github.com/thatxliner/xclif/blob/main/docs/commands.md When help output is not a TTY, Xclif automatically switches to a compact, plain-text format suitable for LLM agents and scripts. This format flattens the command tree, strips Rich formatting, omits framework options, and shows only user-defined options. ```text myapp: My application. greet NAME - Greet someone. Options: --template STR (default: 'Hello, {}!') config get - Print the current config. config set KEY VALUE - Set config values. ``` -------------------------------- ### Variadic Positional Argument CLI Example Source: https://github.com/thatxliner/xclif/blob/main/docs/design/option-system.md Illustrates the command-line invocation for a function with a variadic positional argument, showing how multiple file names are passed. ```bash myapp add file1.py file2.py file3.py # files = ("file1.py", "file2.py", "file3.py") ``` -------------------------------- ### Run Parsing Latency Benchmarks Source: https://github.com/thatxliner/xclif/blob/main/README.md Use this command to run the in-process parsing and dispatch latency benchmarks. Requires `uv` to be installed. ```bash uv run python benchmarks/bench_parsing.py ``` -------------------------------- ### Route Discovery Flow Source: https://github.com/thatxliner/xclif/blob/main/docs/architecture.md Visualizes the process of route discovery, starting from the routes package and culminating in a Command tree. ```default routes/ package → importer.get_modules() → inspect.getmembers() → Command tree ``` -------------------------------- ### Example Usage of Boolean Flags Source: https://github.com/thatxliner/xclif/blob/main/docs/options.md Demonstrates how to call a command with a boolean flag set to its default (False) and toggled to True. ```default myapp build # release = False myapp build --release # release = True ``` -------------------------------- ### Token Parsing Example Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Shows token parsing with a single left-to-right pass scanner that handles options, separators, and subcommand detection. ```python # single left-to-right pass scanner; handles long/short options, -- separator, interspersed positionals, subcommand detection ``` -------------------------------- ### Define a simple command with Xclif Source: https://github.com/thatxliner/xclif/blob/main/README.md Define a command using the `@command()` decorator. Function arguments become CLI arguments or options. Docstrings are used as help text. This example defines a 'greet' command that takes a 'name' and an optional 'template'. ```python # routes/greet.py from xclif import command @command() def _(name: str, template: str = "Hello, {}!") -> None: """Greet someone by name.""" print(template.format(name)) ``` -------------------------------- ### Option-Value Disambiguation CLI Example Source: https://github.com/thatxliner/xclif/blob/main/docs/design/option-system.md Demonstrates how options are greedy and consume the next token as their value, even if it's a valid subcommand name. The subcommand is not invoked in the first case. ```bash myapp server --format json # json is the value of --format ``` ```bash myapp server --format json json # json is the value of --format; the second json invokes the subcommand ``` -------------------------------- ### Environment Variable Naming Convention Source: https://github.com/thatxliner/xclif/blob/main/docs/config.md By default, environment variables follow the pattern `_`, where `PREFIX` is the uppercased app name. This example shows how to set the `name` parameter for an app named 'greeter'. ```bash # For an app named "greeter", the param "name" maps to: export GREETER_NAME=Alice greeter greet # uses "Alice" from env ``` -------------------------------- ### Long Option Syntax Reference Source: https://github.com/thatxliner/xclif/blob/main/docs/design/option-system.md Provides examples of long option syntax, including boolean flags and value options using space or equals separation. ```plaintext --flag # boolean flag → True --name value # value option, space-separated --name=value # value option, = form ``` -------------------------------- ### Lexical Scoping Example with Subcommands Source: https://github.com/thatxliner/xclif/blob/main/docs/design/option-system.md Illustrates how options are scoped to the command level where they are declared. Options parsed at a parent level are not passed as kwargs to child commands' run functions. ```default myapp --verbose server --format json start KEY VALUE ↑ ↑ ↑ root-level server-level start-level option option (positional args) ``` -------------------------------- ### Configure and Greet Source: https://github.com/thatxliner/xclif/blob/main/examples/greeter/README.md Illustrates setting a custom template and then using it for a greeting. ```bash python -m greeter config set --name Bob --template "Hey, {}!" python -m greeter greet # Hey, Bob! ``` -------------------------------- ### Set up CLI Entry Point Source: https://github.com/thatxliner/xclif/blob/main/docs/routing.md The entry point script uses `Cli.from_routes()` to discover and wire commands from the specified routes package. ```python # __main__.py from xclif import Cli from . import routes cli = Cli.from_routes(routes) if __name__ == "__main__": cli() ``` -------------------------------- ### Build Documentation Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Build the project's documentation using `uv run` and `sphinx-build`. ```bash uv run sphinx-build docs docs/_build/html ``` -------------------------------- ### Minimal Xclif Entry Point Source: https://github.com/thatxliner/xclif/blob/main/docs/manifesto.md Initialize an Xclif application with minimal boilerplate. The `Cli.from_routes(routes)` method sets up the CLI to discover commands from the specified routes directory. ```python from xclif import Cli routes = "myapp/routes" app = Cli.from_routes(routes) if __name__ == "__main__": app() ``` -------------------------------- ### Build CLI from Pre-compiled Manifest Source: https://context7.com/thatxliner/xclif/llms.txt Use Cli.from_manifest() for production entry points to load a pre-built manifest, skipping filesystem traversal for faster startup. ```python # myapp/__main__.py — production entry point from xclif import Cli from myapp import _xclif_manifest cli = Cli.from_manifest( _xclif_manifest, env_prefix="MYAPP", local_config=".myapp.toml", ) if __name__ == "__main__": cli() # _xclif_manifest.py (generated — do not edit): # # def _build_cli(version=None, env_prefix=None, ...) -> Cli: # from myapp.routes import _ as _root # from myapp.routes.greet import _ as _greet # from myapp.routes.server.start import _ as _start # ... # cli = Cli(root_command=_root, ...) # cli.add_command(['greet'], _greet) # cli.add_command(['server', 'start'], _start) # cli._finalize() # return cli ``` -------------------------------- ### Load Manifest at Runtime Source: https://github.com/thatxliner/xclif/blob/main/docs/compiler.md Replace `Cli.from_routes()` with `Cli.from_manifest()` in your application's entry point to use the pre-compiled manifest for faster startup. ```python # myapp/__main__.py from xclif import Cli from myapp import _xclif_manifest cli = Cli.from_manifest(_xclif_manifest) if __name__ == "__main__": cli() ``` -------------------------------- ### Basic Greeting Source: https://github.com/thatxliner/xclif/blob/main/examples/greeter/README.md Demonstrates how to perform a basic greeting using the CLI. ```bash python -m greeter greet --name Alice # Hello, Alice! ``` -------------------------------- ### Initialize Xclif CLI from routes Source: https://github.com/thatxliner/xclif/blob/main/README.md Create a main CLI application instance by loading commands from a specified routes module. This code should be placed in your project's main entry point (__main__.py). ```python # __main__.py from xclif import Cli from . import routes cli = Cli.from_routes(routes) if __name__ == "__main__": cli() ``` -------------------------------- ### Get Verbosity Level from Context Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md Access the verbosity level, ranging from 0 to 3, which corresponds to the number of '-v' flags used. ```python ctx.verbosity ``` -------------------------------- ### Raising a UsageError Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md Use `UsageError` to signal user-facing CLI invocation problems. This exception can optionally include a hint to guide the user. ```python raise UsageError("Invalid input provided", hint="Please check the documentation for correct usage.") ``` -------------------------------- ### Create CLI from Pre-compiled Manifest Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md Load a pre-compiled manifest for faster CLI startup. This bypasses runtime filesystem scanning, requiring a prior 'xclif compile' step. ```python def from_manifest(manifest, version=None, env_prefix=None, config_name=None, local_config=None): pass ``` -------------------------------- ### Compile Manifest from Command Line Source: https://github.com/thatxliner/xclif/blob/main/docs/compiler.md Use this command to generate the `_xclif_manifest.py` file. Specify an output directory with `--output` if needed. ```bash python -m xclif compile myapp.routes ``` ```bash python -m xclif compile myapp.routes --output src/myapp ``` -------------------------------- ### Create CLI by Walking Routes Package Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md Build a CLI by dynamically scanning a Python package for command modules at runtime. The package structure defines the command hierarchy. ```python def from_routes(routes, version=None, env_prefix=None, config_name=None, local_config=None): pass ``` -------------------------------- ### Print Agent-Friendly Help Summary Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md The `print_agent_help` method generates a concise help summary suitable for LLM agents. It flattens the command tree and filters out framework-specific options. ```default command.print_agent_help() ``` -------------------------------- ### Greeting with Custom Template Source: https://github.com/thatxliner/xclif/blob/main/examples/greeter/README.md Shows how to use a custom template for greetings. ```bash python -m greeter greet --name Alice --template "Hi there, {}!" # Hi there, Alice! ``` -------------------------------- ### Command Tree Structure Source: https://github.com/thatxliner/xclif/blob/main/docs/architecture.md Demonstrates how module paths map to the command tree structure, including root, subcommands, and namespace commands. ```default routes/__init__.py → root command routes/greet.py → root.subcommands["greet"] routes/config/__init__.py → root.subcommands["config"] (namespace) routes/config/set.py → root.subcommands["config"].subcommands["set"] ``` -------------------------------- ### Get Current Command Dispatch Context Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md Call `xclif.get_context()` to retrieve the `Context` object for the currently executing command. This function raises a `RuntimeError` if called outside of a command dispatch. ```default xclif.get_context() ``` -------------------------------- ### Xclif Entry Point Boilerplate Source: https://github.com/thatxliner/xclif/blob/main/MANIFESTO.md Demonstrates the minimal boilerplate required for an Xclif application's entry point. The `Cli.from_routes` method automatically discovers and loads commands based on the defined structure. ```python from xclif import Cli routes = __import__("myapp.routes").myapp.routes cli = Cli.from_routes(routes) if __name__ == "__main__": cli() ``` -------------------------------- ### Load Pre-built Manifest with Xclif Source: https://github.com/thatxliner/xclif/blob/main/README.md Use this snippet to load a pre-compiled manifest for faster startup times, especially in large codebases. Ensure the manifest file is generated using `xclif compile`. ```python # __main__.py — manifest variant from xclif import Cli from myapp import _xclif_manifest cli = Cli.from_manifest(_xclif_manifest) if __name__ == "__main__": cli() ``` -------------------------------- ### Build Distribution Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Build the project's distribution packages using the `uv build` command. ```bash uv build ``` -------------------------------- ### Cli.from_routes Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md Builds a `Cli` instance by walking a routes package at runtime, using the package structure to determine the command hierarchy. ```APIDOC ## classmethod from_routes(routes, version=None, env_prefix=None, config_name=None, local_config=None) ### Description Build a [`Cli`](#xclif.Cli) by walking a routes package at runtime. Each module in *routes* that exports a `Command` becomes a subcommand. The package structure determines the command hierarchy — see [File-Based Routing](routing.md) for details. ### Parameters * **routes** (*ModuleType*) – The routes package module (e.g. `import myapp.routes as routes`). * **version** (*str* *|* *None*) – Explicit version string. When *None*, auto-detected from the top-level package of *routes*. * **env_prefix** (*str* *|* *None*) – Prefix for env-var overrides. Defaults to the uppercased root command name. * **config_name** (*str* *|* *None*) – App name for config directory resolution. Defaults to the root command name. * **note::** ( *..*) – For production CLIs, prefer [`from_manifest()`](#xclif.Cli.from_manifest) to avoid the `pkgutil.walk_packages` overhead on every invocation. * **local_config** (*str* *|* *None*) ### Return type *Self* ``` -------------------------------- ### Basic Configuration with WithConfig Source: https://github.com/thatxliner/xclif/blob/main/docs/config.md Annotate parameters with `WithConfig[T]` to enable resolution from config files and environment variables. This allows parameters to be set via CLI, environment, or config without changing command logic. ```python from xclif import WithConfig, command @command() def _(name: WithConfig[str], template: WithConfig[str] = "Hello, {}!") -> None: """Greet someone by name.""" print(template.format(name)) ``` -------------------------------- ### Combine Metadata with Config-Backed Parameters Source: https://github.com/thatxliner/xclif/blob/main/docs/options.md When combining `WithConfig` with `Arg` or `Option`, use the full `Annotated` form. This allows specifying descriptions, custom names, and config backing simultaneously. ```python from typing import Annotated from xclif import Arg, Option, WithConfig, command @command() def _( name: Annotated[str, Arg(description="Person to greet"), WithConfig()] ) -> None: ... ``` -------------------------------- ### Compiler Module Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Describes the `compiler.py` module, which pre-builds a static manifest to optimize startup by skipping route-walking. ```python # pre-builds a static manifest to skip route-walking at startup ``` -------------------------------- ### Print Short Help Summary Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md The `print_short_help` method displays a compact help summary for a command. It can be forced to use rich or plain text output. ```default command.print_short_help() ``` -------------------------------- ### Define a simple command with configuration support Source: https://context7.com/thatxliner/xclif/llms.txt Defines a command that accepts a name and a template, with configuration values prioritized from CLI flags, environment variables, local config, and user config. ```python from xclif import WithConfig, command @command() def _(name: WithConfig[str] = "", template: WithConfig[str] = "Hello, {}!") -> None: """Greet someone by name.""" if not name: print("Error: provide a name or set one via `myapp config set name `") return print(template.format(name)) ``` -------------------------------- ### Loading Local Configuration File Source: https://github.com/thatxliner/xclif/blob/main/docs/config.md Enable loading a configuration file from the current working directory by setting the `local_config` parameter to a filename. This is useful for per-project settings. ```python cli = Cli.from_routes(routes, local_config=".myapp.toml") ``` -------------------------------- ### Data Flow: Route Discovery Source: https://github.com/thatxliner/xclif/blob/main/ARCHITECTURE.md Shows the flow from routes package to Command tree using pkgutil.walk_packages for module discovery. ```text routes/ package → importer.get_modules() → inspect.getmembers() → Command tree ``` -------------------------------- ### Build System Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Indicates that the project uses `hatchling` as its build system. ```python # Build system: hatchling ``` -------------------------------- ### Compile Routes to Manifest Source: https://context7.com/thatxliner/xclif/llms.txt Generate a static route map using `xclif compile` for faster startup. Commit the generated manifest file to version control. ```bash # Generate once; commit to version control python -m xclif compile myapp.routes # or python -m xclif compile myapp.routes --output src/myapp ``` -------------------------------- ### xclif.Cli Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md The entry point for an Xclif-powered CLI application. Typically constructed via `from_routes()` or `from_manifest()`. ```APIDOC ## class xclif.Cli(root_command, version=None, env_prefix=None, config_name=None, local_config=None, config_command=True) ### Description Entry point for an Xclif-powered CLI application. Typically constructed via [`from_routes()`](#xclif.Cli.from_routes) (file-based routing) or [`from_manifest()`](#xclif.Cli.from_manifest) (pre-compiled manifest for fast startup). Direct construction is only needed when using the flat decorator API. ### Parameters * **root_command** (*xclif.command.Command*) – The root `Command` of the CLI tree. * **version** (*str* *|* *None*) – Version string shown by `--version`. Auto-detected from package metadata when *None*. * **env_prefix** (*str* *|* *None*) – Prefix for environment-variable overrides (e.g. `"MYAPP"` → `MYAPP_FOO`). Defaults to the uppercased root command name. * **config_name** (*str* *|* *None*) – App name used to locate the config directory via `platformdirs`. Defaults to the root command name. * **local_config** (*str* *|* *None*) – Filename to look for in the current working directory as a local config file (e.g. `".myapp.toml"`). When set, the file is loaded and its values take priority over the user-level config but are still overridden by env vars and CLI flags. Supports `.toml` and `.json` extensions. *None* (the default) disables local config. * **config_command** (*bool*) – Whether to auto-inject the `config` subcommand when any parameter uses `WithConfig`. *True* (the default) keeps the current behaviour; set to *False* to suppress it. ``` -------------------------------- ### Define Config-Backed Parameters Source: https://github.com/thatxliner/xclif/blob/main/docs/options.md Parameters annotated with `WithConfig[T]` can fall back to environment variables or config files if not provided on the CLI. This allows for flexible configuration management. ```python from xclif import WithConfig, command @command() def _(name: WithConfig[str], greeting: WithConfig[str] = "Hello") -> None: ... ``` -------------------------------- ### Cli.from_manifest Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md Loads a pre-compiled manifest produced by `xclif compile`, offering a faster alternative to `from_routes()` by skipping filesystem scans. ```APIDOC ## classmethod from_manifest(manifest, version=None, env_prefix=None, config_name=None, local_config=None) ### Description Load a pre-compiled manifest produced by `xclif compile`. This is a faster alternative to [`from_routes()`](#xclif.Cli.from_routes) — it skips the `pkgutil.walk_packages` + `inspect.getmembers` filesystem scan at the cost of a one-time `xclif compile` build step. ### Parameters * **manifest** (*ModuleType*) – The generated manifest module (typically `myapp._xclif_manifest`). * **version** (*str* *|* *None*) – Explicit version string. When *None*, auto-detected from the top-level package of *manifest* (same behaviour as [`from_routes()`](#xclif.Cli.from_routes)). * **local_config** (*str* *|* *None*) – Filename for cwd-based local config. See [`Cli`](#xclif.Cli). * **env_prefix** (*str* *|* *None*) * **config_name** (*str* *|* *None*) ### Return type *Self* ``` -------------------------------- ### Build CLI from Routes Package Source: https://context7.com/thatxliner/xclif/llms.txt Use Cli.from_routes() to build a CLI by walking a Python package at runtime. This method discovers commands based on the package hierarchy. ```python # myapp/__main__.py from xclif import Cli from . import routes cli = Cli.from_routes( routes, version="1.2.0", # explicit version (auto-detected from package metadata if omitted) env_prefix="MYAPP", # env vars: MYAPP_NAME, MYAPP_TEMPLATE, … config_name="my-app", # platformdirs config dir name local_config=".myapp.toml" # also load from cwd/.myapp.toml ) if __name__ == "__main__": cli() # Routes package layout → command tree: # # myapp/routes/ # ├── __init__.py → myapp # ├── greet.py → myapp greet # └── server/ # ├── __init__.py → myapp server # ├── start.py → myapp server start # └── stop.py → myapp server stop ``` -------------------------------- ### Compile Xclif Routes Manifest Source: https://github.com/thatxliner/xclif/blob/main/README.md Run this command to generate a static manifest file from your routes. This is necessary when adding or removing routes to ensure the manifest is up-to-date. ```bash # regenerate after adding or removing routes xclif compile myapp.routes ``` -------------------------------- ### xclif.compiler.compile_routes Source: https://github.com/thatxliner/xclif/blob/main/docs/compiler.md Walks a routes package and writes a manifest file (`_xclif_manifest.py`) to optimize runtime loading. ```APIDOC ## xclif.compiler.compile_routes(routes, output_dir=None) ### Description Walk *routes* and write a manifest file. ### Parameters #### Path Parameters - **routes** (*ModuleType*) – Required - The routes package module (e.g. `import myapp.routes as routes`). - **output_dir** (*Path* *|* *None*) – Optional - Directory to write `_xclif_manifest.py` into. Defaults to the directory containing the routes package itself (i.e. sits next to it). ### Returns The path of the written manifest file. ### Return type Path ``` -------------------------------- ### Print Full Help Page Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md The `print_long_help` method displays the complete help page, including the long description. It supports forcing rich or plain text output. ```default command.print_long_help() ``` -------------------------------- ### Execute Command with Provided Arguments Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md Use the `execute` method on a `Command` object to parse arguments and run the appropriate subcommand. Pass an explicit list of arguments for testing purposes. ```default assert my_command.execute(["greet", "Alice"]) == 0 ``` -------------------------------- ### Run Xclif CLI Commands Source: https://github.com/thatxliner/xclif/blob/main/docs/quickstart.md Execute your Xclif CLI application from the command line using `python -m `. Arguments and options are passed directly. ```bash python -m myapp greet Alice # Hello, Alice! python -m myapp greet Alice --template "Hi, {}!" # Hi, Alice! python -m myapp --help ``` -------------------------------- ### Config Module Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Explains the `config.py` and `config_commands.py` modules, featuring `WithConfig[T]` for resolving configuration from files and environment variables. ```python # WithConfig[T] for config file/env var resolution ``` -------------------------------- ### Compile Routes from Command Line Source: https://github.com/thatxliner/xclif/blob/main/docs/compiler.md Use this command to compile routes from your application's route package. ```bash python -m xclif compile myapp.routes ``` -------------------------------- ### Implicit vs User Options Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Highlights the architectural boundary between framework-owned implicit options (e.g., `--help`) and user-defined options from function signatures. ```python # implicit options (framework-owned: --help, --verbose, --colors) vs user options (from function signature) # Implicit options are handled before dispatch and never passed to run() ``` -------------------------------- ### Variadic Positional Arguments in Python Source: https://github.com/thatxliner/xclif/blob/main/docs/design/option-system.md Demonstrates how to define a variadic positional argument in Python using `*args`. This parameter consumes all remaining non-option tokens. ```python import argparse @command() def add(*files: str) -> None: """Stage files for commit.""" for f in files: stage(f) ``` -------------------------------- ### Define command with Arg and Option metadata Source: https://context7.com/thatxliner/xclif/llms.txt Uses Annotated with Arg and Option to provide descriptions, override display names, and set default values for command parameters. ```python from typing import Annotated from xclif import Arg, Option, WithConfig, command @command() def deploy( target: Annotated[str, Arg(description="Deployment target (staging|production)", name="TARGET")], dry_run: Annotated[bool, Option(description="Print actions without executing", name="dry-run")] = False, tag: Annotated[list[str], Option(description="Docker image tags")] = [], env: Annotated[WithConfig[str], Arg(description="Environment name"), WithConfig()] = "staging", ) -> None: """Deploy the application.""" print(f"Deploying to {target} (env={env}, dry_run={dry_run}, tags={tag})") ``` ```bash # myapp deploy production --dry-run --tag latest --tag v1.2 # Deploying to production (env=staging, dry_run=True, tags=['latest', 'v1.2']) # # Help output: # Usage: deploy [OPTIONS] TARGET # Arguments: # TARGET Deployment target (staging|production) # Options: # --dry-run, -d Print actions without executing # --tag, -t Docker image tags (repeatable) ``` -------------------------------- ### Use Just Task Runner Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Execute project tasks defined in the `Justfile` using the `just` command. ```bash just test just cov just docs ``` -------------------------------- ### Command with Markdown Descriptions Source: https://github.com/thatxliner/xclif/blob/main/docs/commands.md Utilize Markdown in docstrings for rich help text. The first line serves as a short description, while the rest is rendered with Markdown support. ```python @command() def deploy(target: str, dry_run: bool = False) -> None: """Deploy the application. Pushes the current build to the specified **target** environment. Supported targets: - `staging` — deploy to the staging cluster - `production` — deploy to prod (requires `--confirm`) > Note: runs `preflight_checks()` before deploying. """ ... ``` -------------------------------- ### Mark Parameter for Config File or Environment Variable Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md Use `WithConfig` to indicate that a parameter can be read from a config file or environment variable. The priority order is CLI flag > env var > config file > default. ```default name: WithConfig[str] ``` -------------------------------- ### xclif.WithConfig Class Source: https://github.com/thatxliner/xclif/blob/main/docs/api.md Marker for parameters that can be read from a config file or environment variable. Defines priority order for configuration sources. ```APIDOC ### *class* xclif.WithConfig Bases: `object` Marker for parameters that can be read from a config file or env var. `name: WithConfig[str]` is sugar for `Annotated[str, WithConfig()]`. Priority order: CLI flag > env var > config file > default. Env var: `_` Config key: the parameter name as-is. ``` -------------------------------- ### Programmatic Manifest Generation with `compile_routes()` Source: https://context7.com/thatxliner/xclif/llms.txt The `compile_routes()` function generates a `_xclif_manifest.py` file by walking a routes package. This is useful for custom build scripts, Makefiles, or hatch build hooks, and can be used to switch the CLI entry point to `from_manifest()` for performance. ```python # build_manifest.py from xclif.compiler import compile_routes import myapp.routes as routes from pathlib import Path path = compile_routes(routes) print(f"Manifest written to: {path}") # Manifest written to: /src/myapp/_xclif_manifest.py # Custom output directory path = compile_routes(routes, output_dir=Path("src/myapp")) # In pyproject.toml with hatch: # [tool.hatch.build.hooks.custom] # runs `python -m xclif compile myapp.routes` before building wheel # Makefile: # manifest: # python -m xclif compile myapp.routes ``` -------------------------------- ### Integration Testing Execution Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Explains integration testing methodology using `root.execute([...])` with explicit argument lists, avoiding `sys.argv`. ```python # Integration tests use root.execute([...]) with explicit arg lists (not sys.argv) ``` -------------------------------- ### Define Group Command Source: https://github.com/thatxliner/xclif/blob/main/docs/routing.md A directory containing an `__init__.py` file is treated as a group command. This `__init__.py` defines the group's help text and can handle invocations without subcommands. ```python # routes/server/__init__.py from xclif import command @command() def _() -> None: """Manage the server.""" # Called when user types `myapp server` with no subcommand. # Default behaviour: print help. ``` -------------------------------- ### Short Alias Syntax Reference Source: https://github.com/thatxliner/xclif/blob/main/docs/design/option-system.md Illustrates the syntax for short option aliases, including single-character boolean flags and value options. ```plaintext -v # single-char boolean flag -n value # single-char value option ``` -------------------------------- ### Script Execution with uv run Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Emphasizes using `uv run` for executing scripts and tests to ensure the correct virtual environment is utilized. ```python # Always use uv run to execute scripts/tests (ensures correct virtualenv) ``` -------------------------------- ### Unit Testing Commands Source: https://github.com/thatxliner/xclif/blob/main/CLAUDE.md Describes unit testing practices where `Command` objects are constructed directly, with `test_cli.py` being an exception that tests the `Cli` class. ```python # Unit tests construct Command objects directly; only test_cli.py goes through Cli ```