CLI reference¶
Installing cliffy adds two identical entry points, cli and cliffy. This page uses cli.
It is generated from the command definitions in cliffy/cli.py and cliffy/ai.py, so the
arguments, options and defaults below are the ones the installed version accepts.
Commands at a glance¶
| Command | Description |
|---|---|
cli ai |
AI-powered commands. generate and ask require the ai extra: pip install 'cliffy[ai]' |
cli blueprint |
Work with blueprints: custom YAML specs that map onto a CLI |
cli build |
Build a CLI manifest or a loaded CLI into a single file to hand to someone else |
cli dev |
Start hot-reloader for a manifest for active development. |
cli docs |
Generate documentation for a CLI |
cli info |
Display CLI info |
cli init |
Generate a CLI manifest template |
cli list |
List all CLIs loaded |
cli load |
Load CLI for given manifest(s) |
cli remove |
Remove a loaded CLI by name |
cli remove-all |
Remove all loaded CLIs |
cli render |
Render the CLI manifest generation as code |
cli run |
Run CLI for a manifest |
cli test |
Run tests defined in a manifest |
cli update |
Reloads CLI by name |
cli validate |
Validate a CLI manifest: its structure, its requirements and the code generated from it |
Global options¶
| Option | Description |
|---|---|
--version |
Print the version and exit. |
--aliases |
List the command aliases and exit. |
-h, --help |
Show help. Every command accepts this option. |
Aliases¶
Aliases are hidden from cli --help. cli --aliases prints this list.
| Alias | Command |
|---|---|
cli ls |
cli list |
cli add |
cli load |
cli reload |
cli update |
cli rm |
cli remove |
cli rm-all |
cli remove-all |
cli rmall |
cli remove-all |
cli blueprints |
cli blueprint list |
cli ai¶
AI-powered commands. generate and ask require the ai extra: pip install 'cliffy[ai]'
generate and ask need the ai extra (pip install "cliffy[ai]"). Both send the manifest JSON
schema to the model as part of the prompt and print token usage when they finish. llms-txt needs no
extra and calls no model.
Model names use the pydantic-ai provider:model form, and the API key of that provider must be set in
the environment. Without --model, the CLIFFY_AI_MODEL environment variable is used, then a default
for the first provider that has an API key set. See AI commands.
cli ai ask¶
Ask a question about cliffy or a specific CLI manifest.
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
PROMPT |
text | yes | Your question. | |
--preview |
flag | no | Print the prompt instead of sending it. Needs no model. | |
--max-tokens |
integer range | no | Maximum number of tokens in a model response. | |
-m, --model |
text | no | Model to use, as provider:model. See https://pydantic.dev/docs/ai/models/overview/. Defaults to a model of the first provider with an API key set, else google:gemini-flash-latest. |
|
--cli |
file | no | Loaded CLI or manifest to include in the prompt as reference. |
--preview prints the prompt and exits without calling a model.
cli ai generate¶
Generate a CLI manifest based on a description.
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
CLI_NAME |
text | yes | Name of the CLI. The manifest is written to <cli_name>.yaml. |
|
DESCRIPTION |
text | yes | Plain-language description of the CLI you want. | |
--preview |
flag | no | Print the prompt instead of sending it. Needs no model. | |
--max-tokens |
integer range | no | Maximum number of tokens in a model response. | |
-m, --model |
text | no | Model to use, as provider:model. See https://pydantic.dev/docs/ai/models/overview/. Defaults to a model of the first provider with an API key set, else google:gemini-flash-latest. |
|
--retries |
integer range | no | 2 |
How often to send an invalid manifest back to the model to be fixed. |
-f, --force |
flag | no | Overwrite the manifest file if it exists. | |
-o, --output-dir |
directory | no | . |
Output directory |
The reply of the model is validated before the manifest is written, and sent back with the reason when
it is not a manifest cliffy can load. --preview prints the prompt and exits without calling a model.
cli ai llms-txt¶
Print the bundled cliffy documentation as llms.txt. Needs no model.
Prints the documentation that is bundled with the installed cliffy as one text file, in the
llms.txt layout. It needs no model, no API key and no ai extra, so it works
offline and always matches the installed version.
Give the output to a coding agent, or add it to a project's context, so that it can write manifests without looking anything up.
cli blueprint¶
Work with blueprints: custom YAML specs that map onto a CLI
A blueprint lets a YAML file use its own keys instead of commands and params, and maps them onto a
CLI. See Blueprints.
cli blueprint list¶
List the blueprints provided by installed packages
Alias: cli blueprints
Lists the blueprints that installed packages register under the cliffy.blueprints entry point group.
A blueprint in a .py file or referenced as module:Class works without being listed.
$ cli blueprint list
No blueprints installed. Use a .py file or module:Class reference, or install a blueprint package.
cli blueprint schema¶
Print the JSON schema of a blueprint's spec, for validation and editor completion
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
BLUEPRINT |
text | yes | Blueprint reference: a .py file, module:Class or the name of an installed blueprint. |
|
-o, --output |
file | no | Write the schema to a file |
Point a # yaml-language-server: $schema= comment at the file to get completion and validation for
files written in the blueprint's spec.
cli build¶
Build a CLI manifest or a loaded CLI into a single file to hand to someone else
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
[CLI_OR_MANIFESTS]... |
file | no | Manifest files (paths ending in yaml) or names of loaded CLIs. |
|
-t, --target |
zipapp | script | native |
no | zipapp |
What to build: zipapp is a zipapp with its dependencies bundled, which needs a compatible Python; script is a .py script that declares its dependencies inline, which needs uv or an environment with them; native is a compiled executable that brings its own Python and needs nothing installed (built with cargo and uv). |
-o, --output-dir |
directory | no | Output dir | |
-p, --python |
text | no | Interpreter for the #! line of a zipapp or a script, added after the #!. [default: /usr/bin/env python3 for a zipapp, /usr/bin/env -S uv run --script for a script] | |
-b, --blueprint |
text | no | Blueprint that maps a custom YAML spec onto a CLI: a .py file, module:Class or an installed blueprint name. Overrides the blueprint: key of the file. |
Builds one file to hand to someone else. --target chooses what kind:
| Target | What you get | Needs on the other machine |
|---|---|---|
zipapp |
hello, a zipapp built with shiv that contains the dependencies |
A compatible Python |
script |
hello.py, a script with its dependencies declared inline |
uv, or Python with the dependencies installed |
native |
hello, a compiled executable with its own Python |
Nothing |
Every target ships the generated CLI, the framework it imports (Typer, or rich-click with
use_click) and every package listed under requires. Without --output-dir the file is written
to the current directory.
$ cli build hello.yaml -o dist
+ hello built ๐ฆ
dist/hello (single file, needs Python >=3.10, 1.8 MB)
run it with: ./dist/hello
$ ./dist/hello greet Ada
Hello, Ada!
$ cli build hello.yaml -o dist --target script
+ hello built ๐ฆ
dist/hello.py (single file, needs uv, or Python >=3.11 with typer==0.27.3 installed, 1.3 kB)
run it with: ./dist/hello.py (or: uv run dist/hello.py)
uv downloads the dependencies the first time the script runs
The native target needs cargo and uv on the machine that builds. When a build fails, the
reason is printed and the exit code is 1. With --blueprint, or a blueprint: key in the file,
the blueprint is applied at build time and is not needed to run the result.
See Building executables.
cli dev¶
Start hot-reloader for a manifest for active development.
Examples:
-
cli dev examples/hello.yaml
-
cli dev examples/hello.yaml --run-cli -- -h
-
cli dev examples/hello.yaml --run-cli python
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
MANIFEST |
file | yes | Manifest file to watch. | |
[RUN_CLI_ARGS]... |
text | no | Arguments for the generated CLI when --run-cli is set. |
|
--run-cli |
flag | no | If passed, runs CLI on each reload. Useful for syntax checks or testing command execution on each reload | |
-b, --blueprint |
text | no | Blueprint that maps a custom YAML spec onto a CLI: a .py file, module:Class or an installed blueprint name. Overrides the blueprint: key of the file. |
Nothing is loaded when the command starts. The CLI is loaded the first time the file changes and again on every later change. The manifests it includes and the Python file of its blueprint are watched too. Stop with Ctrl+C.
With --run-cli, the remaining arguments are passed to the freshly generated CLI after each reload.
Put -- before them when they include options.
See Hot-reload dev loop.
cli docs¶
Generate documentation for a CLI
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
CLI_OR_MANIFEST |
file | yes | Manifest file (a path ending in yaml) or the name of a loaded CLI. |
|
-f, --format |
md | rst | html |
no | md |
Output format. |
-o, --output-dir |
directory | no | Output directory | |
-b, --blueprint |
text | no | Blueprint that maps a custom YAML spec onto a CLI: a .py file, module:Class or an installed blueprint name. Overrides the blueprint: key of the file. |
Writes <name>.md, <name>.rst or <name>.html to the output directory, or to the current directory
when --output-dir is not given. The output directory must exist.
A loaded CLI is documented from the manifest path recorded by cli load.
See Generating docs.
cli info¶
Display CLI info
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
CLI_NAME |
text | yes | Name of a loaded CLI. |
Prints the name, version, requirements, blueprint (when one was used), age and stored manifest of a loaded CLI.
cli init¶
Generate a CLI manifest template
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
[CLI_NAME] |
text | no | mycli |
Name of the CLI. The manifest is written to <cli_name>.yaml. |
--render |
flag | no | Print template to terminal directly | |
--raw |
flag | no | Raw template without boilerplate helpers and examples. | |
--json-schema |
flag | no | Write JSON schema (cliffy_schema.json) file to the current directory. Useful for development. |
--raw writes a skeleton with every top-level key, one hello command and one test. Without --raw
the manifest is a commented tour of the format with example commands. Both run and pass cli test as
written.
--json-schema also writes cliffy_schema.json and adds a # yaml-language-server comment that points
at it. See Editor setup.
cli list¶
List all CLIs loaded
Alias: cli ls
$ cli list
โโโโโโโโโณโโโโโโโโโโณโโโโโโณโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Name โ Version โ Age โ Manifest โ
โกโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฉ
โ hello โ 0.1.0 โ 5s โ /home/ada/hello.yaml โ
โโโโโโโโโดโโโโโโโโโโดโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโ
cli load¶
Load CLI for given manifest(s)
Alias: cli add
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
[MANIFESTS]... |
file | no | One or more manifest files to load. | |
-b, --blueprint |
text | no | Blueprint that maps a custom YAML spec onto a CLI: a .py file, module:Class or an installed blueprint name. Overrides the blueprint: key of the file. |
Loading does three things:
- generates the CLI code and writes it to
cliffy/clis/<name>.pyinside the installed cliffy package, - writes a launcher script called
<name>into thebindirectory of the Python environment cliffy is installed in, - records the manifest path and contents so that
cli list,cli infoandcli updatecan find it.
The CLI is therefore available wherever that environment is active. Packages listed under requires
must already be installed, otherwise loading stops with missing requirement.
A file written in a blueprint's spec is loaded the same way. The blueprint comes from
--blueprint or from the file's blueprint: key and is remembered, so cli update applies it again.
See Hot-reload dev loop.
cli remove¶
Remove a loaded CLI by name
Alias: cli rm
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
[CLI_NAMES]... |
text | no | Names of loaded CLIs to remove. |
Deletes the launcher script, the generated module and the stored metadata.
cli remove-all¶
Remove all loaded CLIs
Aliases: cli rm-all, cli rmall
cli render¶
Render the CLI manifest generation as code
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
MANIFEST |
file | yes | Manifest file to render. | |
-b, --blueprint |
text | no | Blueprint that maps a custom YAML spec onto a CLI: a .py file, module:Class or an installed blueprint name. Overrides the blueprint: key of the file. |
Prints the Python module cliffy generates, without loading or running it. Use it to see exactly how params, shell lines and templates are translated.
cli run¶
Run CLI for a manifest
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
MANIFEST |
file | yes | Manifest file to run. | |
[CLI_ARGS]... |
text | no | Arguments passed to the generated CLI. Put -- first when they include options. |
|
-b, --blueprint |
text | no | Blueprint that maps a custom YAML spec onto a CLI: a .py file, module:Class or an installed blueprint name. Overrides the blueprint: key of the file. |
Generates the CLI in a temporary file and runs it once, without loading it. Options meant for your
CLI must come after --, otherwise cli run tries to parse them itself:
$ cli run hello.yaml greet Ada
Hello, Ada!
$ cli run hello.yaml -- greet Ada --shout
HELLO, ADA!
$ cli run hello.yaml -- --help
Help output shows the temporary file name instead of the CLI name.
cli test¶
Run tests defined in a manifest
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
MANIFEST |
file | yes | Manifest file whose tests section should run. |
|
-x, --exitfirst |
flag | no | exit instantly on first error or failed test. | |
--traceback |
flag | no | Also print the full Python traceback of a command that raises. | |
-b, --blueprint |
text | no | Blueprint that maps a custom YAML spec onto a CLI: a .py file, module:Class or an installed blueprint name. Overrides the blueprint: key of the file. |
Runs the tests section of a manifest and prints each command, its output and the result. The exit
code is 0 only when every test passes. It is 1 when a test fails or when the manifest has no tests.
See Testing manifests.
cli update¶
Reloads CLI by name
Alias: cli reload
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
[CLI_NAMES]... |
text | no | Names of loaded CLIs to regenerate from their manifests. |
update re-reads the manifest from the path recorded by cli load, so it only works while the manifest
is still at that location.
cli validate¶
Validate a CLI manifest: its structure, its requirements and the code generated from it
| Argument or option | Type | Required | Default | Description |
|---|---|---|---|---|
MANIFEST |
file | yes | Manifest file to validate. | |
-b, --blueprint |
text | no | Blueprint that maps a custom YAML spec onto a CLI: a .py file, module:Class or an installed blueprint name. Overrides the blueprint: key of the file. |
Checks that the file is valid YAML, matches the manifest schema, that its requires are installed and
that the generated code works. Scripts are checked while the code is generated, as they are by every
other command. validate then compiles and imports the generated code, which defines the commands
without running any of them. The code in imports and functions and the expressions in vars do run.
An error in a script is reported with its command, line and column. A problem that only shows when the code is imported, such as a type that does not exist, is reported against the command it comes from:
$ cli validate broken.yaml
~ error in broken.yaml: command `db.create`, run, line 2, column 7: not valid Python: '(' was never closed
print((
^ ๐
$ cli validate other.yaml
Manifest other.yaml is invalid: the generated code does not work
command `db.create`: NameError: name 'Table' is not defined
def db_create(table: Table = typer.Argument(...)): ๐