API

class cyclopts.App(name: str | Iterable[str] | None = None, help: str | None = None, usage: str | None = None, *, alias: str | Iterable[str] | None = None, default_command: Callable[[...], Any] | None = None, default_parameter: Parameter | None = None, config: _ConfigCallable | Iterable[_ConfigCallable] | None = None, version: None | str | Callable[[...], str] | Callable[[...], Coroutine[Any, Any, str]] = None, version_flags: str | Iterable[str] | None = ['--version'], show: bool = True, console: Console | None = None, error_console: Console | None = None, help_flags: str | Iterable[str] | None = ['--help', '-h'], help_format: Literal['markdown', 'md', 'plaintext', 'restructuredtext', 'rst', 'rich'] | None = None, help_on_error: bool | None = None, help_prologue: str | None = None, help_epilogue: str | None = None, version_format: Literal['markdown', 'md', 'plaintext', 'restructuredtext', 'rst', 'rich'] | None = None, group: Group | str | Iterable[Group | str] | None = None, group_arguments: None | str | Group = None, group_parameters: None | str | Group = None, group_commands: None | str | Group = None, validator: Callable[[...], Any] | Iterable[Callable[[...], Any]] | None = None, name_transform: Callable[[str], str] | None = None, sort_key: Any = None, end_of_options_delimiter: str | None = None, print_error: bool | None = None, exit_on_error: bool | None = None, verbose: bool | None = None, suppress_keyboard_interrupt: bool = True, backend: Literal['asyncio', 'trio'] | None = None, help_formatter: None | Literal['default', 'plain'] | HelpFormatter = None, error_formatter: Callable[[CycloptsError], Any] | None = None, result_action: ResultAction | ResultActionSingle | None = None)

Cyclopts Application.

name: str | Iterable[str] | None = None

Name of application, or subcommand if registering to another application. Name resolution order:

  1. User specified name parameter.

  2. If a default function has been registered, the name of that function.

  3. If the module name is __main__.py, the name of the encompassing package.

  4. The value of sys.argv[0]; i.e. the name of the python script.

Multiple names can be provided in the case of a subcommand, but this is relatively unusual.

Special value "*" can be used when registering sub-apps with command() to flatten all commands from the sub-app into the parent app. See Flattening SubCommands for details.

Example:

from cyclopts import App

app = App()
app.command(App(name="foo"))

@app["foo"].command
def bar():
    print("Running bar.")

app()
$ my-script foo bar
Running bar.
alias: str | Iterable[str] | None = None

Extends name with additional names. Unlike name, this does not override Cyclopts-derived names.

from cyclopts import App

app = App()

@app.command(alias="bar")
def foo():
    print("Running foo.")

app()
$ my-script foo
Running bar.

$ my-script bar
Running bar.
help: str | None = None

Text to display on help screen. If not supplied, fallbacks to parsing the docstring of function registered with App.default().

from cyclopts import App

app = App(help="This is my help string.")
app()
$ my-script --help
Usage: scratch.py COMMAND

This is my help string.

╭─ Commands ────────────────────────────────────────────────────────────╮
│ --help -h  Display this message and exit.                             │
│ --version  Display application version.                               │
╰───────────────────────────────────────────────────────────────────────╯
help_flags: str | Iterable[str] = ("--help", "-h")

CLI flags that trigger help_print(). Set to an empty list to disable this feature. Defaults to ["--help", "-h"].

help_format: Literal['plaintext', 'markdown', 'md', 'restructuredtext', 'rst'] | None = None

The markup language used in function docstring. If None, fallback to parenting help_format. If no help_format is defined, falls back to "markdown".

help_formatter: None | Literal['default', 'plain'] | HelpFormatter = None

Help formatter to use for rendering help panels.

Example:

from cyclopts import App
from cyclopts.help import DefaultFormatter, PlainFormatter, PanelSpec

# Use plain text formatter
app = App(help_formatter="plain")

# Use default formatter with customization
app = App(help_formatter=DefaultFormatter(
    panel_spec=PanelSpec(border_style="blue")
))

See Help Customization for detailed examples and advanced usage.

help_prologue: str | None = None

Text to display at the beginning of the help screen, before the usage section. If None, no prologue is displayed. If not set, attempts to inherit from parenting App.

The prologue supports the same formatting as help based on help_format (markdown, plaintext, restructuredtext, or rich).

Example:

from cyclopts import App

app = App(
    name="myapp",
    help="My application help.",
    help_prologue=f"myapp, v1.0.0 (http://example.myapp.com)"
)
app()
$ my-script --help
myapp, v1.0.0 (http://example.myapp.com)

Usage: myapp COMMAND

My application help.

╭─ Commands ────────────────────────────────────────────────────────────╮
│ --help -h  Display this message and exit.                             │
│ --version  Display application version.                               │
╰───────────────────────────────────────────────────────────────────────╯
help_epilogue: str | None = None

Text to display at the end of the help screen, after all help panels. Commonly used for version information, contact details, or additional notes. If None, no epilogue is displayed. If not set, attempts to inherit from parenting App.

The epilogue supports the same formatting as help based on help_format (markdown, plaintext, restructuredtext, or rich).

Example:

from cyclopts import App

app = App(
    name="myapp",
    help="My application help.",
    help_epilogue="Support: support@example.com"
)
app()
$ my-script --help
Usage: myapp COMMAND

My application help.

╭─ Commands ────────────────────────────────────────────────────────────╮
│ --help -h  Display this message and exit.                             │
│ --version  Display application version.                               │
╰───────────────────────────────────────────────────────────────────────╯

Support: support@example.com
help_on_error: bool | None = None

Prints the help-page before printing an error. If not set, attempts to inherit from parenting App, eventually defaulting to False.

print_error: bool | None = None

Print a rich-formatted error on error. If not set, attempts to inherit from parenting App, eventually defaulting to True.

exit_on_error: bool | None = None

If there is an error parsing the CLI tokens, invoke sys.exit(1). Otherwise, continue to raise the exception. If not set, attempts to inherit from parenting App, eventually defaulting to True.

verbose: bool | None = None

Populate exception strings with more information intended for developers. If not set, attempts to inherit from parenting App, eventually defaulting to False.

error_formatter: Callable[[CycloptsError], Any] | None = None

A callable that formats CycloptsError exceptions for display. The callable receives the exception and should return any Rich-printable object (string, Text, Panel, etc.). If not set, attempts to inherit from parenting App, eventually defaulting to CycloptsPanel().

See Custom Error Formatting for examples.

version_format: Literal['plaintext', 'markdown', 'md', 'restructuredtext', 'rst'] | None = None

The markup language used in the version string. If None, fallback to parenting version_format. If no version_format is defined, falls back to resolved help_format.

usage: str | None = None

Text to be displayed in lieue of the default Usage: app COMMAND ... at the beginning of the help-page. Set to an empty-string "" to disable showing the default usage.

show: bool = True

Show this command on the help screen. Hidden commands (show=False) are still executable.

from cyclopts import App
app = App()

@app.command
def foo():
   print("Running foo.")

@app.command(show=False)
def bar():
   print("Running bar.")

app()
$ my-script foo
Running foo.

$ my-script bar
Running bar.

$ my-script --help
Usage: scratch.py COMMAND

╭─ Commands ─────────────────────────────────────────────────╮
│ foo                                                        │
│ --help -h  Display this message and exit.                  │
│ --version  Display application version.                    │
╰────────────────────────────────────────────────────────────╯
sort_key: Any = None

Modifies command display order on the help-page.

  1. If sort_key is a generator, it will be consumed immediately with next() to get the actual value.

  2. If sort_key, or any of it's contents, are Callable, then invoke it sort_key(app) and apply the returned value to (3) if None, (4) otherwise.

  3. For all commands with sort_key==None (default value), sort them alphabetically. These sorted commands will be displayed after sort_key != None list (see 4).

  4. For all commands with sort_key!=None, sort them by (sort_key, app.name). It is the user's responsibility that sort_key s are comparable.

Example usage:

from cyclopts import App

app = App()

@app.command  # sort_key not specified; will be sorted AFTER bob/charlie.
def alice():
    """Alice help description."""

@app.command(sort_key=2)
def bob():
    """Bob help description."""

@app.command(sort_key=1)
def charlie():
    """Charlie help description."""

app()

Resulting help-page:

Usage: demo.py COMMAND

╭─ Commands ──────────────────────────────────────────────────╮
│ charlie    Charlie help description.                        │
│ bob        Bob help description.                            │
│ alice      Alice help description.                          │
│ --help -h  Display this message and exit.                   │
│ --version  Display application version.                     │
╰─────────────────────────────────────────────────────────────╯

Using generators (e.g., itertools.count()):

import itertools
from cyclopts import App

app = App()
counter = itertools.count()

@app.command(sort_key=counter)
def beta():
    """Beta help description."""

@app.command(sort_key=counter)
def alpha():
    """Alpha help description."""

app()
Usage: demo.py COMMAND

╭─ Commands ──────────────────────────────────────────────────╮
│ beta       Beta help description.                           │
│ alpha      Alpha help description.                          │
│ --help -h  Display this message and exit.                   │
│ --version  Display application version.                     │
╰─────────────────────────────────────────────────────────────╯
version: None | str | Callable = None

Version to be displayed when a version_flags is parsed. Defaults to the version of the package instantiating App. If a Callable, it will be invoked with no arguments when version is queried.

version_flags: str | Iterable[str] = ("--version",)

Token(s) that trigger version_print(). Set to an empty list to disable version feature. Defaults to ["--version"].

console: Console = None

Default Console to use when displaying runtime messages. Cyclopts console resolution is as follows:

  1. Any explicitly passed in console to methods like App.__call__(), App.parse_args(), etc.

  2. The relevant subcommand's App.console attribute, if not None.

  3. The parenting App.console (and so on), if not None.

  4. If all values are None, then the default Console is used.

error_console: Console = None

Default Console to use when displaying error messages. Cyclopts error_console resolution is as follows:

  1. Any explicitly passed in error_console to methods like App.__call__(), App.parse_args(), etc.

  2. The relevant subcommand's App.error_console attribute, if not None.

  3. The parenting App.error_console (and so on), if not None.

  4. If all values are None, then a default Console with stderr=True is used.

This separation of error output from normal output follows Unix conventions, allowing users to redirect error messages independently from normal output (e.g., program > output.txt 2> errors.txt).

default_parameter: Parameter = None

Default Parameter configuration. Unspecified values of command-annotated Parameter will inherit these values. See Default Parameter for more details.

group: None | str | Group | Iterable[str | Group] = None

The group(s) that default_command belongs to.

  • If None, defaults to the "Commands" group.

  • If str, use an existing Group (from neighboring sub-commands) with name, or create a Group with provided name if it does not exist.

  • If Group, directly use it.

group_commands: Group = Group("Commands")

The default Group that sub-commands are assigned to.

group_arguments: Group = Group("Arguments")

The default Group that positional-only parameters are assigned to.

group_parameters: Group = Group("Parameters")

The default Group that non-positional-only parameters are assigned to.

validator: None | Callable | list[Callable] = []

A function (or list of functions) where all the converted CLI-provided variables will be keyword-unpacked, regardless of their positional/keyword-type in the command function signature. The python variable names will be used, which may differ from their CLI names.

Example usage:

def validator(**kwargs):
    "Raise an exception if something is invalid."

This validator runs after Parameter and Group validators.

name_transform: Callable[[str], str] | None = None

A function that converts function names to their CLI command counterparts.

The function must have signature:

def name_transform(s: str) -> str:
    ...

The returned string should be without a leading --. If None (default value), uses default_name_transform(). Subapps inherit from the first non-None parent name_transform.

config: None | Callable | Iterable[Callable] = None

A function or list of functions that are consecutively executed after parsing CLI tokens and environment variables. These function(s) are called before any conversion and validation. Each config function must have signature:

def config(app: "App", commands: Tuple[str, ...], arguments: ArgumentCollection):
    """Modifies given mapping inplace with some injected values.

    Parameters
    ----------
    app: App
       The current command app being executed.
    commands: Tuple[str, ...]
       The CLI strings that led to the current command function.
    arguments: ArgumentCollection
       Complete ArgumentCollection for the app.
       Modify this collection inplace to influence values provided to the function.
    """

The intended use-case of this feature is to allow users to specify functions that can load defaults from some external configuration. See cyclopts.config for useful builtins and Config Files for examples.

end_of_options_delimiter: str | None = None

All tokens after this delimiter will be force-interpreted as positional arguments. If not set, attempts to inherit from parenting App, eventually defaulting to POSIX-standard "--". Set to an empty string to disable.

suppress_keyboard_interrupt: bool = True

If the application receives a keyboard interrupt (Ctrl-C), suppress the error message and exit gracefully. Set to False to let KeyboardInterrupt propagate normally.

backend: Literal['asyncio', 'trio'] | None = None

The async backend to use when executing async commands. If not set, attempts to inherit from parenting App, eventually defaulting to "asyncio".

Example:

from cyclopts import App

app = App(backend="asyncio")

@app.default
async def main():
    await some_async_operation()

app()

The backend can also be overridden on a per-call basis:

app(backend="trio")  # Override the app's backend for this call
result_action: Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any] | Iterable[Literal[...] | Callable[[Any], Any]] | None = None

Controls how App.__call__() and App.run_async() handle command return values. By default ("print_non_int_sys_exit"), the app will call sys.exit() with an appropriate exit code. This default was chosen for consistent functionality between standalone scripts, and console entrypoints.

Can be a predefined literal string, a custom callable that takes the result and returns a processed value, or a sequence of actions to be applied left-to-right in a pipeline.

Each predefined mode's exact behavior is shown below:

"print_non_int_sys_exit" (default)

The default CLI mode. Prints non-int values to stdout, then calls sys.exit() with the appropriate exit code.

if isinstance(result, bool):
    sys.exit(0 if result else 1)  # i.e. True is success
elif isinstance(result, int):
    sys.exit(result)
elif result is not None:
    print(result)
    sys.exit(0)
else:
    sys.exit(0)

"return_value"

Returns the command's value unchanged. Use for embedding Cyclopts in other Python code or testing.

return result

"call_if_callable"

Calls the result if it's callable (with no arguments), otherwise returns it unchanged. Useful for the dataclass command pattern where commands return class instances with __call__ methods. Intended to be used in composition with other result actions (e.g., ["call_if_callable", "print_non_int_sys_exit"]).

return result() if callable(result) else result

See Dataclass Commands for usage examples.

"sys_exit"

Never prints output. Calls sys.exit() with the appropriate exit code. Useful for CLI apps that handle their own output and just need exit code handling.

if isinstance(result, bool):
    sys.exit(0 if result else 1)  # i.e. True is success
elif isinstance(result, int):
    sys.exit(result)
else:
    sys.exit(0)

"print_non_int_return_int_as_exit_code"

Prints non-int values, returns int/bool as exit codes. Useful for testing and embedding.

if isinstance(result, bool):
    return 0 if result else 1  # i.e. True is success
elif isinstance(result, int):
    return result
elif result is not None:
    print(result)
    return 0
else:
    return 0

"print_str_return_int_as_exit_code"

Only prints string return values. Returns int/bool as exit codes, silently returns 0 for other types.

if isinstance(result, str):
    print(result)
    return 0
elif isinstance(result, bool):
    return 0 if result else 1  # i.e. True is success
elif isinstance(result, int):
    return result
else:
    return 0

"print_str_return_zero"

Only prints string return values, always returns 0. Useful for simple output-only CLIs.

if isinstance(result, str):
    print(result)
return 0

"print_non_none_return_int_as_exit_code"

Prints all non-None values (including ints), returns int/bool as exit codes.

if result is not None:
    print(result)
if isinstance(result, bool):
    return 0 if result else 1  # i.e. True is success
elif isinstance(result, int):
    return result
return 0

"print_non_none_return_zero"

Prints all non-None values (including ints), always returns 0.

if result is not None:
    print(result)
return 0

"return_int_as_exit_code_else_zero"

Never prints output. Returns int/bool as exit codes, 0 for all other types. Useful for silent CLIs.

if isinstance(result, bool):
    return 0 if result else 1  # i.e. True is success
elif isinstance(result, int):
    return result
else:
    return 0

"return_none"

Always returns None, regardless of the command's return value.

return None

"return_zero"

Always returns 0, regardless of the command's return value.

return 0

"print_return_zero"

Always prints the result (even None), then always returns 0.

print(result)
return 0

"sys_exit_zero"

Always calls sys.exit(0), regardless of the command's return value.

sys.exit(0)

"print_sys_exit_zero"

Always prints the result (even None), then calls sys.exit(0).

print(result)
sys.exit(0)

Custom Callable

Provide a function for fully custom result handling. Receives the command's return value and returns a processed value.

def custom_handler(result):
    if result is None:
        return 0
    elif isinstance(result, str):
        print(f"[OUTPUT] {result}")
        return 0
    return result

app = App(result_action=custom_handler)

Sequence of Actions

Provide a sequence (list or tuple) of actions to create a result-processing pipeline. Actions are applied left-to-right, with each action receiving the result of the previous action.

def uppercase(result):
    return result.upper() if isinstance(result, str) else result

def add_prefix(result):
    return f"[OUTPUT] {result}" if isinstance(result, str) else result

# Pipeline: result → uppercase → add_prefix → return
app = App(result_action=[uppercase, add_prefix, "return_value"])

@app.command
def greet(name: str) -> str:
    return f"hello {name}"

result = app(["greet", "world"])
# result == "[OUTPUT] HELLO WORLD"

Actions in a sequence can be any combination of predefined literal strings and custom callables. Empty sequences raise a ValueError at app initialization.

Example:

from cyclopts import App

# For CLI applications with console_scripts entry points
app = App(result_action="print_non_int_return_int_as_exit_code")

@app.command
def greet(name: str) -> str:
    return f"Hello {name}!"

app()

See Result Action for detailed examples and usage patterns.

version_print(console: Annotated[Console | None, Parameter(parse=False)] = None) None

Print the application version.

Parameters:

console (Console) -- Console to print version string to. If not provided, follows the resolution order defined in App.console.

__getitem__(key: str) App

Get the subapp from a command string.

All commands get registered to Cyclopts as subapps. The actual function handler is at app[key].default_command.

If the command was registered via lazy loading (import path string), it will be imported and resolved on first access.

Example usage:

from cyclopts import App

app = App()
app.command(App(name="foo"))


@app["foo"].command
def bar():
    print("Running bar.")


app()
__iter__() Iterator[str]

Iterate over command & meta command names.

Example usage:

from cyclopts import App

app = App()


@app.command
def foo():
    pass


@app.command
def bar():
    pass


# help and version flags are treated as commands.
assert list(app) == ["--help", "-h", "--version", "foo", "bar"]
parse_commands(tokens: None | str | Iterable[str] = None, *, include_parent_meta=True) tuple[tuple[str, ...], tuple[App, ...], list[str]]

Extract out the command tokens from a command.

You are probably actually looking for parse_args().

Parameters:
  • tokens (None | str | Iterable[str]) -- Either a string, or a list of strings to launch a command. Defaults to sys.argv[1:]

  • include_parent_meta (bool) --

    Controls whether parent meta apps are included in the execution path.

    When True (default): - Parent meta apps (i.e. the "normal" app ) are added to the apps list. - Meta app options are consumed while parsing commands. - Used for getting the inheritance hierarchy.

    When False: - Meta app options are treated as regular arguments. - Used for getting the execution hierarchy.

    This parameter is primarily for internal use.

Returns:

  • tuple[str, ...] -- Strings that are interpreted as a valid command chain.

  • tuple[App, ...] -- The execution path - apps that will be invoked in order.

  • list[str] -- The remaining non-command tokens.

command(obj: T, name: None | str | Iterable[str] = None, *, alias: None | str | Iterable[str] = None, **kwargs: object) T
command(obj: None = None, name: None | str | Iterable[str] = None, *, alias: None | str | Iterable[str] = None, **kwargs: object) Callable[[T], T]
command(obj: str, name: None | str | Iterable[str] = None, *, alias: None | str | Iterable[str] = None, **kwargs: object) None

Decorator to register a function as a CLI command.

Example usage:

from cyclopts import App

app = App()

@app.command
def foo():
    print("foo!")

@app.command(name="buzz")
def bar():
    print("bar!")

# Lazy loading via import path
app.command("myapp.commands:create_user", name="create")

app()
$ my-script foo
foo!

$ my-script buzz
bar!

$ my-script create
# Imports and runs myapp.commands:create_user
Parameters:
  • obj (Callable | App | str | None) -- Function, App, or import path string to be registered as a command. For lazy loading, provide a string in format "module.path:function_or_app_name".

  • name (None | str | Iterable[str]) --

    Name(s) to register the command to. If not provided, defaults to:

    • If registering an App, then the app's name.

    • If registering a function, then the function's name after applying name_transform.

    • If registering via import path, then the attribute name after applying name_transform.

    Special value "*" flattens all sub-App commands into this app (App instances only). See Flattening SubCommands for details.

  • **kwargs -- Any argument that App can take.

default(obj: T, *, validator: Callable[[...], Any] | None = None) T
default(obj: None = None, *, validator: Callable[[...], Any] | None = None) Callable[[T], T]

Decorator to register a function as the default action handler.

Example usage:

from cyclopts import App

app = App()


@app.default
def main():
    print("Hello world!")


app()
$ my-script
Hello world!
assemble_argument_collection(*, default_parameter: Parameter | None = None, parse_docstring: bool = False) ArgumentCollection

Assemble the argument collection for this app.

Parameters:
  • default_parameter (Parameter | None) -- Default parameter with highest priority.

  • parse_docstring (bool) -- Parse the docstring of default_command. Set to True if we need help strings, otherwise set to False for performance reasons.

Returns:

All arguments for this app.

Return type:

ArgumentCollection

parse_known_args(tokens: None | str | Iterable[str] = None, *, console: Console | None = None, error_console: Console | None = None, end_of_options_delimiter: str | None = None) tuple[Callable[[...], Any], BoundArguments, list[str], dict[str, Any]]

Interpret arguments into a registered function, BoundArguments, and any remaining unknown tokens.

Parameters:
  • tokens (None | str | Iterable[str]) -- Either a string, or a list of strings to launch a command. Defaults to sys.argv[1:]

  • console (Console) -- Console to print help and runtime Cyclopts errors. If not provided, follows the resolution order defined in App.console.

  • error_console (Console) -- Console to print error messages. If not provided, follows the resolution order defined in App.error_console.

  • end_of_options_delimiter (str | None) -- All tokens after this delimiter will be force-interpreted as positional arguments. If None, inherits from App.end_of_options_delimiter, eventually defaulting to POSIX-standard "--". Set to an empty string to disable.

Returns:

  • command (Callable) -- Bare function to execute.

  • bound (inspect.BoundArguments) -- Bound arguments for command.

  • unused_tokens (list[str]) -- Any remaining CLI tokens that didn't get parsed for command.

  • ignored (dict[str, Any]) -- A mapping of python-variable-name to annotated type of any parameter with annotation parse=False. Annotated will be resolved. Intended to simplify meta apps.

parse_args(tokens: None | str | Iterable[str] = None, *, console: Console | None = None, error_console: Console | None = None, print_error: bool | None = None, exit_on_error: bool | None = None, help_on_error: bool | None = None, verbose: bool | None = None, end_of_options_delimiter: str | None = None, error_formatter: Callable[[CycloptsError], Any] | None = None) tuple[Callable[[...], Any], BoundArguments, dict[str, Any]]

Interpret arguments into a function and BoundArguments.

Raises:

UnusedCliTokensError -- If any tokens remain after parsing.

Parameters:
  • tokens (None | str | Iterable[str]) -- Either a string, or a list of strings to launch a command. Defaults to sys.argv[1:].

  • console (Console) -- Console to print help and runtime Cyclopts errors. If not provided, follows the resolution order defined in App.console.

  • error_console (Console) -- Console to print error messages. If not provided, follows the resolution order defined in App.error_console.

  • print_error (bool | None) -- Print a rich-formatted error on error. If None, inherits from App.print_error, eventually defaulting to True.

  • exit_on_error (bool | None) -- If there is an error parsing the CLI tokens invoke sys.exit(1). Otherwise, continue to raise the exception. If None, inherits from App.exit_on_error, eventually defaulting to True.

  • help_on_error (bool | None) -- Prints the help-page before printing an error. If None, inherits from App.help_on_error, eventually defaulting to False.

  • verbose (bool | None) -- Populate exception strings with more information intended for developers. If None, inherits from App.verbose, eventually defaulting to False.

  • end_of_options_delimiter (str | None) -- All tokens after this delimiter will be force-interpreted as positional arguments. If None, inherits from App.end_of_options_delimiter, eventually defaulting to POSIX-standard "--". Set to an empty string to disable.

Returns:

  • command (Callable) -- Function associated with command action.

  • bound (inspect.BoundArguments) -- Parsed and converted args and kwargs to be used when calling command.

  • ignored (dict[str, Any]) -- A mapping of python-variable-name to type-hint of any parameter with annotation parse=False. Annotated will be resolved. Intended to simplify meta apps.

__call__(tokens: None | str | Iterable[str] = None, *, console: Console | None = None, error_console: Console | None = None, print_error: bool | None = None, exit_on_error: bool | None = None, help_on_error: bool | None = None, verbose: bool | None = None, end_of_options_delimiter: str | None = None, backend: Literal['asyncio', 'trio'] | None = None, result_action: Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any] | Iterable[Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any]] | None = None, error_formatter: Callable[[CycloptsError], Any] | None = None) Any

Interprets and executes a command.

Parameters:
  • tokens (None | str | Iterable[str]) -- Either a string, or a list of strings to launch a command. Defaults to sys.argv[1:].

  • console (Console) -- Console to print help and runtime Cyclopts errors. If not provided, follows the resolution order defined in App.console.

  • error_console (Console) -- Console to print error messages. If not provided, follows the resolution order defined in App.error_console.

  • print_error (bool | None) -- Print a rich-formatted error on error. If None, inherits from App.print_error, eventually defaulting to True.

  • exit_on_error (bool | None) -- If there is an error parsing the CLI tokens invoke sys.exit(1). Otherwise, continue to raise the exception. If None, inherits from App.exit_on_error, eventually defaulting to True.

  • help_on_error (bool | None) -- Prints the help-page before printing an error. If None, inherits from App.help_on_error, eventually defaulting to False.

  • verbose (bool | None) -- Populate exception strings with more information intended for developers. If None, inherits from App.verbose, eventually defaulting to False.

  • end_of_options_delimiter (str | None) -- All tokens after this delimiter will be force-interpreted as positional arguments. If None, inherits from App.end_of_options_delimiter, eventually defaulting to POSIX-standard "--". Set to an empty string to disable.

  • backend (Literal["asyncio", "trio"] | None) -- Override the async backend to use (if an async command is invoked). If None, inherits from App.backend, eventually defaulting to "asyncio". If passing backend="trio", ensure trio is installed via the extra: cyclopts[trio].

  • result_action (ResultAction | None) -- Controls how command return values are handled. Can be a predefined literal string or a custom callable that takes the result and returns a processed value. If None, inherits from App.result_action, eventually defaulting to "print_non_int_return_int_as_exit_code". See App.result_action for available modes.

Returns:

return_value -- The value the command function returns.

Return type:

Any

async run_async(tokens: None | str | Iterable[str] = None, *, console: Console | None = None, error_console: Console | None = None, print_error: bool | None = None, exit_on_error: bool | None = None, help_on_error: bool | None = None, verbose: bool | None = None, end_of_options_delimiter: str | None = None, backend: Literal['asyncio', 'trio'] | None = None, result_action: Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any] | Iterable[Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any]] | None = None, error_formatter: Callable[[CycloptsError], Any] | None = None) Any

Async equivalent of __call__() for use within existing event loops.

This method should be used when you're already in an async context (e.g., Jupyter notebooks, existing async applications) and need to execute a Cyclopts command without creating a new event loop.

Parameters:
  • tokens (None | str | Iterable[str]) -- Either a string, or a list of strings to launch a command. Defaults to sys.argv[1:].

  • console (Console) -- Console to print help and runtime Cyclopts errors. If not provided, follows the resolution order defined in App.console.

  • error_console (Console) -- Console to print error messages. If not provided, follows the resolution order defined in App.error_console.

  • print_error (bool | None) -- Print a rich-formatted error on error. If None, inherits from App.print_error, eventually defaulting to True.

  • exit_on_error (bool | None) -- If there is an error parsing the CLI tokens invoke sys.exit(1). Otherwise, continue to raise the exception. If None, inherits from App.exit_on_error, eventually defaulting to True.

  • help_on_error (bool | None) -- Prints the help-page before printing an error. If None, inherits from App.help_on_error, eventually defaulting to False.

  • verbose (bool | None) -- Populate exception strings with more information intended for developers. If None, inherits from App.verbose, eventually defaulting to False.

  • end_of_options_delimiter (str | None) -- All tokens after this delimiter will be force-interpreted as positional arguments. If None, inherits from App.end_of_options_delimiter, eventually defaulting to POSIX-standard "--". Set to an empty string to disable.

  • backend (Literal["asyncio", "trio"] | None) -- Override the async backend to use (if an async command is invoked). If None, inherits from App.backend, eventually defaulting to "asyncio". If passing backend="trio", ensure trio is installed via the extra: cyclopts[trio].

  • result_action (ResultAction | None) -- Controls how command return values are handled. Can be a predefined literal string or a custom callable that takes the result and returns a processed value. If None, inherits from App.result_action, eventually defaulting to "print_non_int_return_int_as_exit_code". See App.result_action for available modes.

Returns:

return_value -- The value the command function returns.

Return type:

Any

Examples

import asyncio
from cyclopts import App

app = App()

@app.command
async def my_async_command():
    await asyncio.sleep(1)
    return "Done!"


# In an async context (e.g., Jupyter notebook or existing async app):
async def main():
    result = await app.run_async(["my-async-command"])
    print(result)  # Prints: Done!


asyncio.run(main())
help_print(tokens: Annotated[None | str | Iterable[str], Parameter(show=False)] = None, *, console: Annotated[Console | None, Parameter(parse=False)] = None) None

Print the help page.

Parameters:
  • tokens (None | str | Iterable[str]) -- Tokens to interpret for traversing the application command structure. If not provided, defaults to sys.argv.

  • console (Console) -- Console to print help and runtime Cyclopts errors. If not provided, follows the resolution order defined in App.console.

generate_docs(output_format: DocFormat = 'markdown', recursive: bool = True, include_hidden: bool = False, heading_level: int = 1, max_heading_level: int = 6, flatten_commands: bool = False, usage_name: str | None = None) str

Generate documentation for this CLI application.

Parameters:
  • output_format (DocFormat) -- Output format for the documentation. Accepts "markdown"/"md", "html"/"htm", or "rst"/"rest"/"restructuredtext". Default is "markdown".

  • recursive (bool) -- If True, generate documentation for all subcommands recursively. Default is True.

  • include_hidden (bool) -- If True, include hidden commands/parameters in documentation. Default is False.

  • heading_level (int) -- Starting heading level for the main application title. Default is 1 (single # for markdown, = for RST).

  • max_heading_level (int) -- Maximum heading level to use. Headings deeper than this will be capped at this level. Standard Markdown and HTML support levels 1-6. Default is 6.

  • flatten_commands (bool) -- If True, generate all commands at the same heading level instead of nested. Default is False.

  • usage_name (str | None) -- Optional replacement for the root app name shown in Usage: lines of the generated documentation. Useful when the runtime invocation differs from the app's configured name — for example, an app named "cli" that is typically invoked as uv run cli. Only the Usage: lines change; document titles, section headings, and table-of-contents anchors continue to use app.name[0]. Default is None (use app.name[0]).

Returns:

The generated documentation.

Return type:

str

Raises:

ValueError -- If an unsupported output format is specified.

Examples

>>> app = App(name="myapp", help="My CLI Application")
>>> docs = app.generate_docs()  # Generate markdown as string
>>> html_docs = app.generate_docs(output_format="html")  # Generate HTML
>>> rst_docs = app.generate_docs(output_format="rst")  # Generate RST
>>> # To write to file, caller can do:
>>> # Path("docs/cli.md").write_text(docs)
>>> # Override the invocation shown in Usage: lines (e.g., uv run cli)
>>> docs = app.generate_docs(usage_name="uv run cli")
generate_completion(*, prog_name: str | None = None, shell: Literal['zsh', 'bash', 'fish'] | None = None) str

Generate shell completion script for this application.

Parameters:
  • prog_name (str | None) -- Program name for completion. If None, uses first name from app.name.

  • shell (Literal["zsh", "bash", "fish"] | None) -- Shell type. If None, automatically detects current shell. Supported shells: "zsh", "bash", "fish".

Returns:

Complete shell completion script.

Return type:

str

Examples

Auto-detect shell and generate completion:

>>> app = App(name="myapp")
>>> script = app.generate_completion()
>>> Path("_myapp").write_text(script)

Explicitly specify shell type:

>>> script = app.generate_completion(shell="zsh")
Raises:
  • ValueError -- If app has no name or shell type is unsupported.

  • ShellDetectionError -- If shell is None and auto-detection fails.

install_completion(*, shell: Literal['zsh', 'bash', 'fish'] | None = None, output: Path | None = None, add_to_startup: bool = True) Path

Install shell completion script to appropriate location.

Generates and writes the completion script to a shell-specific location.

Parameters:
  • shell (Literal["zsh", "bash", "fish"] | None) -- Shell type for completion. If not specified, attempts to auto-detect current shell.

  • output (Path | None) -- Output path for the completion script. If not specified, uses shell-specific default: - zsh: ~/.zsh/completions/_<prog_name> (or $ZSH_CUSTOM/completions/_<prog_name> with oh-my-zsh) - bash: ~/.local/share/bash-completion/completions/<prog_name> - fish: ~/.config/fish/completions/<prog_name>.fish

  • add_to_startup (bool) -- If True (default), adds source line to shell RC file to ensure completion is loaded. Set to False if completions are already configured to auto-load.

Returns:

Path where the completion script was installed.

Return type:

Path

Examples

Auto-detect shell and install:

>>> app = App(name="myapp")
>>> path = app.install_completion()

Install for specific shell:

>>> path = app.install_completion(shell="zsh")

Install to custom path:

>>> path = app.install_completion(output=Path("/custom/path"))

Install without modifying RC files:

>>> path = app.install_completion(shell="bash", add_to_startup=False)
Raises:
  • ShellDetectionError -- If shell is None and auto-detection fails.

  • ValueError -- If shell type is unsupported.

register_install_completion_command(name: str | Iterable[str] = '--install-completion', add_to_startup: bool = True, **kwargs) None

Register a command for installing shell completion.

This is a convenience method that creates a command which calls install_completion(). For more control over the command implementation, users can manually define their own command.

Parameters:
  • name (str | Iterable[str]) -- Command name(s) for the install completion command. Defaults to "--install-completion".

  • add_to_startup (bool) -- If True (default), adds source line to shell RC file to ensure completion is loaded. Set to False if completions are already configured to auto-load.

  • **kwargs -- Additional keyword arguments to pass to command(). Can be used to customize the command registration (e.g., help, group, help_flags, version_flags).

Examples

Register install-completion command:

>>> app = App(name="myapp")
>>> app.register_install_completion_command()
>>> app()  # Now responds to: myapp --install-completion

Use a custom command name:

>>> app.register_install_completion_command(name="--setup-completion")

Customize help text:

>>> app.register_install_completion_command(help="Install shell completion for myapp.")

Customize command registration:

>>> app.register_install_completion_command(group="Setup", help_flags=[])

Install without modifying RC files:

>>> app.register_install_completion_command(add_to_startup=False)

See also

install_completion

The underlying method that performs the installation.

interactive_shell(prompt: str = '$ ', quit: None | str | Iterable[str] = None, dispatcher: Dispatcher | None = None, console: Console | None = None, exit_on_error: bool = False, result_action: Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any] | Iterable[Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any]] | None = None, **kwargs) None

Create a blocking, interactive shell.

All registered commands can be executed in the shell.

Parameters:
  • prompt (str) -- Shell prompt. Defaults to "$ ".

  • quit (str | Iterable[str]) -- String or list of strings that will cause the shell to exit and this method to return. Defaults to ["q", "quit"].

  • dispatcher (Dispatcher | None) --

    Optional function that subsequently invokes the command. The dispatcher function must have signature:

    def dispatcher(command: Callable, bound: inspect.BoundArguments, ignored: dict[str, Any]) -> Any:
        return command(*bound.args, **bound.kwargs)
    

    The above is the default dispatcher implementation.

  • console (Console | None) -- Rich Console to use for output. If None, uses App.console.

  • exit_on_error (bool) -- Whether to call sys.exit on parsing errors. Defaults to False.

  • result_action (ResultAction | None) -- How to handle command return values in the interactive shell. Defaults to "print_non_int_return_int_as_exit_code" which prints non-int results and returns int/bool as exit codes without calling sys.exit. If None, inherits from App.result_action.

  • **kwargs -- Get passed along to parse_args().

update(app: App)

Copy over all commands from another App.

Commands from the meta app will not be copied over.

Parameters:

app (cyclopts.App) -- All commands from this application will be copied over.

class cyclopts.Parameter(name: str | ~collections.abc.Iterable[str] | None = None, *, converter: ~collections.abc.Callable[[...], ~typing.Any] | str | None = None, validator: ~collections.abc.Callable[[~typing.Any, ~typing.Any], ~typing.Any] | ~collections.abc.Iterable[~collections.abc.Callable[[~typing.Any, ~typing.Any], ~typing.Any]] | None = (), alias: str | ~collections.abc.Iterable[str] | None = None, negative: bool | str | ~collections.abc.Iterable[str] | None = None, group: None | ~cyclopts.group.Group | str | ~collections.abc.Iterable[~cyclopts.group.Group | str] = None, parse: bool | ~re.Pattern[str] | str | None = None, show: bool | None = None, show_default: None | bool | ~collections.abc.Callable[[~typing.Any], ~typing.Any] = None, show_choices: bool | None = None, help: str | None = None, show_env_var: bool | None = None, env_var: str | ~collections.abc.Iterable[str] | None = None, env_var_split: ~collections.abc.Callable[[...], ~typing.Any] = <function env_var_split>, negative_bool: str | ~collections.abc.Iterable[str] | None = None, negative_iterable: str | ~collections.abc.Iterable[str] | None = None, negative_none: str | ~collections.abc.Iterable[str] | None = None, required: bool | None = None, allow_leading_hyphen: bool = False, requires_equals: bool = False, name_transform: ~collections.abc.Callable[[str], str] | None = None, accepts_keys: bool | None = None, consume_multiple: bool | int | ~collections.abc.Sequence[int] | tuple[int, int | None] | None = None, json_dict: bool | None = None, json_list: bool | None = None, count: bool | None = None, allow_repeating: bool | None = None, n_tokens: int | None = None)

Cyclopts configuration for individual function parameters with Annotated.

Example usage:

from cyclopts import app, Parameter
from typing import Annotated

app = App()


@app.default
def main(foo: Annotated[int, Parameter(name="bar")]):
    print(foo)


app()
$ my-script 100
100

$ my-script --bar 100
100
name: None | str | Iterable[str] = None

Name(s) to expose to the CLI. If not specified, cyclopts will apply name_transform to the python parameter name.

from cyclopts import App, Parameter
from typing import Annotated

app = App()

@app.default
def main(foo: Annotated[int, Parameter(name=("bar", "-b"))]):
   print(f"{foo=}")

app()
$ my-script --help
Usage: main COMMAND [ARGS] [OPTIONS]

╭─ Commands ─────────────────────────────────────────────────────╮
│ --help -h  Display this message and exit.                      │
│ --version  Display application version.                        │
╰────────────────────────────────────────────────────────────────╯
╭─ Parameters ───────────────────────────────────────────────────╮
│ *  BAR --bar  -b  [required]                                   │
╰────────────────────────────────────────────────────────────────╯

$ my-script --bar 100
foo=100

$ my-script -b 100
foo=100

If specifying name in a nested data structure (e.g. a dataclass), beginning the name with a hyphen - will override any hierarchical dot-notation.

from cyclopts import App, Parameter
from dataclasses import dataclass
from typing import Annotated

app = App()

@dataclass
class User:
   id: int  # default behavior
   email: Annotated[str, Parameter(name="--email")]  # overrides
   pwd: Annotated[str, Parameter(name="password")]  # dot-notation with parent

@app.command
def create(user: User):
   print(f"Creating {user=}")

app()
$ my-script create --help
Usage: scratch.py create [ARGS] [OPTIONS]

╭─ Parameters ───────────────────────────────────────────────────╮
│ *  USER.ID --user.id  [required]                               │
│ *  EMAIL --email      [required]                               │
│ *  USER.PASSWORD      [required]                               │
│      --user.password                                           │
╰────────────────────────────────────────────────────────────────╯
alias: None | str | Iterable[str] = None

Additional name(s) to expose to the CLI. Unlike name, this does not override Cyclopts-derived names.

The following two examples are functionally equivalent:

@app.default
def main(foo: Annotated[int, Parameter(name=["--foo", "-f"])]):
    pass
@app.default
def main(foo: Annotated[int, Parameter(alias="-f")]):
    pass
converter: Callable | None = None

A function that converts tokens into an object. The converter should have signature:

def converter(type_, tokens) -> Any:
    pass

Where type_ is the parameter's type hint, and tokens is either:

  • A list[cyclopts.Token] of CLI tokens (most commonly).

    from cyclopts import App, Parameter
    from typing import Annotated
    
    app = App()
    
    def converter(type_, tokens):
       assert type_ == tuple[int, int]
       return tuple(2 * int(x.value) for x in tokens)
    
    @app.default
    def main(coordinates: Annotated[tuple[int, int], Parameter(converter=converter)]):
       print(f"{coordinates=}")
    
    app()
    
    $ python my-script.py 7 12
    coordinates=(14, 24)
    
  • A dict of Token if keys are specified in the CLI. E.g.

    $ python my-script.py --foo.key1=val1
    

    would be parsed into:

    tokens = {
       "key1": ["val1"],
    }
    

If not provided, defaults to Cyclopts's internal coercion engine. If a pydantic type-hint is provided, Cyclopts will disable its internal coercion engine (including this converter argument) and leave the coercion to pydantic.

The number of tokens passed to the converter is inferred from the type hint by default, but can be explicitly controlled with n_tokens. This is useful when the type signature doesn't match the desired CLI token consumption. When loading complex objects with multiple fields, it may also be useful to combine with accepts_keys.

Decorating Converters: Converter functions can be decorated with Parameter to define reusable conversion behavior:

@Parameter(n_tokens=1, accepts_keys=False)
def load_from_id(type_, tokens):
    """Load object from database by ID."""
    return fetch_from_db(tokens[0].value)

@app.default
def main(obj: Annotated[MyType, Parameter(converter=load_from_id)]):
    # Automatically inherits n_tokens=1 and accepts_keys=False
    pass

Classmethod Support: Converters can be classmethods. Use string references for class decoration or direct references in annotations. Classmethod signature should be (cls, tokens) instead of (type_, tokens):

@Parameter(converter="from_env")
class Config:
    @Parameter(n_tokens=1, accepts_keys=False)
    @classmethod
    def from_env(cls, tokens):
        env = tokens[0].value
        configs = {"dev": ("localhost", 8080), "prod": ("api.example.com", 443)}
        return cls(*configs[env])
validator: None | Callable | Iterable[Callable] = None

A function (or list of functions) that validates data returned by the converter.

def validator(type_, value: Any) -> None:
    pass  # Raise a TypeError, ValueError, or AssertionError here if data is invalid.
group: None | str | Group | Iterable[str | Group] = None

The group(s) that this parameter belongs to. This can be used to better organize the help-page, and/or to add additional conversion/validation logic (such as ensuring mutually-exclusive arguments).

If None, defaults to one of the following groups:

  1. Parenting App.group_arguments if the parameter is POSITIONAL_ONLY. By default, this is Group("Arguments").

  2. Parenting App.group_parameters otherwise. By default, this is Group("Parameters").

See Groups for examples.

negative: None | str | Iterable[str] = None

Name(s) for empty iterables or false boolean flags.

Set to an empty list or string to disable the creation of negative flags.

Example usage:

from cyclopts import App, Parameter
from typing import Annotated

app = App()

@app.default
def main(*, verbose: Annotated[bool, Parameter(negative="--quiet")] = False):
   print(f"{verbose=}")

app()
$ my-script --help
Usage: main COMMAND [ARGS] [OPTIONS]

╭─ Commands ─────────────────────────────────────────────────────╮
│ --help -h  Display this message and exit.                      │
│ --version  Display application version.                        │
╰────────────────────────────────────────────────────────────────╯
╭─ Parameters ───────────────────────────────────────────────────╮
│ --verbose --quiet  [default: False]                            │
╰────────────────────────────────────────────────────────────────╯
negative_bool: str | None = None

Prefix for negative boolean flags. Defaults to "no-".

negative_iterable: str | None = None

Prefix for empty iterables (like lists and sets) flags. Defaults to "empty-".

negative_none: str | None = None

Prefix for setting optional parameters to None. Not enabled by default (no prefixes set).

Example:

from pathlib import Path
from typing import Annotated

from cyclopts import App, Parameter

app = App(
   default_parameter=Parameter(negative_none="none-")
)

@app.default
def default(path: Path | None = Path("data.bin")):
    print(f"{path=}")

app()
$ my-script
path=PosixPath('data.bin')

$ my-script --path=cat.jpeg
path=PosixPath('cat.jpeg')

$ my-script --none-path
path=None
allow_leading_hyphen: bool = False

Allow parsing non-numeric values that begin with a hyphen -. This is disabled (False) by default, allowing for more helpful error messages for unknown CLI options.

requires_equals: bool = False

Require long options to use = to separate the option name from its value (e.g., --option=value). When enabled, the space-separated form --option value is rejected with a RequiresEqualsError.

  • Only applies to long-form options (those starting with --).

  • Short options (e.g., -o value) are not affected.

  • Boolean flags (e.g., --verbose) work regardless of this setting.

  • Can be set app-wide via App.default_parameter.

  • Cannot be combined with consume_multiple (raises ValueError). To provide multiple values for a list parameter, repeat the option (e.g., --urls=a --urls=b). To pass an empty iterable, use the negative flag (e.g., --empty-urls).

from cyclopts import App, Parameter
from typing import Annotated

app = App()

@app.default
def main(*, name: Annotated[str, Parameter(requires_equals=True)]):
    print(f"Hello {name}")

app()
$ my-script --name=alice
Hello alice

$ my-script --name alice
╭─ Error ───────────────────────────────────────────────────────╮
│ Parameter "--name" requires a value assigned with "=".        │
│ Use "--name=VALUE".                                           │
╰───────────────────────────────────────────────────────────────╯
parse: None | bool | str | re.Pattern = None

Attempt to use this parameter while parsing. Annotated parameter must be keyword-only or have a default value. This is intended to be used with meta apps for injecting values.

  • True - Parse this parameter from CLI tokens.

  • False - Do not parse; parameter will appear in the ignored dict from App.parse_args().

  • None - Default behavior (parse).

  • str - A regex pattern; parse if the pattern matches the parameter name, otherwise skip. String patterns are automatically compiled to re.Pattern for performance.

  • re.Pattern - A pre-compiled regex pattern; same behavior as string patterns.

Regex patterns are primarily intended for use with App.default_parameter to define app-wide skip patterns. For example, if we wanted to skip all fields that begin with an underscore _:

import re
from cyclopts import App, Parameter

# Skip parsing underscore-prefixed KEYWORD_ONLY parameters (i.e. private parameters)
# Both string and pre-compiled patterns are supported:
app = App(default_parameter=Parameter(parse="^(?!_)"))
# or: app = App(default_parameter=Parameter(parse=re.compile("^(?!_)")))

@app.default
def main(visible: str, *, _injected: str = "default"):
    # _injected is NOT parsed from CLI; uses default value
    pass
required: bool | None = None

Indicates that the parameter must be supplied. Defaults to inferring from the function signature; i.e. False if the parameter has a default, True otherwise.

show: bool | None = None

Show this parameter on the help screen. Defaults to whether the parameter is parsed (usually True).

show_default: None | bool | Callable[[Any], Any] = None

If a variable has a default, display the default on the help page. Defaults to None, similar to True, but will not display the default if it is None.

If set to a function with signature:

def formatter(value: Any) -> Any:
    ...

Then the function will be called with the default value, and the returned value will be used as the displayed default value.

Example formatting function:

def hex_formatter(value: int) -> str
   """Will result in something like "[default: 0xFF]" instead of "[default: 255]"."""
   return f"0x{value:X}"
show_choices: bool | None = True

If a variable has a set of choices, display the choices on the help page.

help: str | None = None

Help string to be displayed on the help page. If not specified, defaults to the docstring.

show_env_var: bool | None = True

If a variable has env_var set, display the variable name on the help page.

env_var: None | str | Iterable[str] = None

Fallback to environment variable(s) if CLI value not provided. If multiple environment variables are given, the left-most environment variable with a set value will be used. If no environment variable is set, Cyclopts will fallback to the function-signature default.

env_var_split: Callable = cyclopts.env_var_split

Function that splits up the read-in env_var value. The function must have signature:

def env_var_split(type_: type, val: str) -> list[str]:
    ...

where type_ is the associated parameter type-hint, and val is the environment value.

name_transform: Callable[[str], str] | None = None

A function that converts python parameter names to their CLI command counterparts.

The function must have signature:

def name_transform(s: str) -> str:
    ...

If None (default value), uses cyclopts.default_name_transform().

accepts_keys: bool | None = None

If False, treat the user-defined class annotation similar to a tuple. Individual class sub-parameters will not be addressable by CLI keywords. The class will consume enough tokens to populate all required positional parameters.

Default behavior (accepts_keys=True):

from cyclopts import App, Parameter
from typing import Annotated

app = App()

class Image:
   def __init__(self, path, label):
      self.path = path
      self.label = label

   def __repr__(self):
      return f"Image(path={self.path!r}, label={self.label!r})"

@app.default
def main(image: Image):
   print(f"{image=}")

app()
$ my-program --help
Usage: main COMMAND [ARGS] [OPTIONS]

╭─ Commands ──────────────────────────────────────────────────────────╮
│ --help -h  Display this message and exit.                           │
│ --version  Display application version.                             │
╰─────────────────────────────────────────────────────────────────────╯
╭─ Parameters ────────────────────────────────────────────────────────╮
│ *  IMAGE.PATH --image.path    [required]                            │
│ *  IMAGE.LABEL --image.label  [required]                            │
╰─────────────────────────────────────────────────────────────────────╯

$ my-program foo.jpg nature
image=Image(path='foo.jpg', label='nature')

$ my-program --image.path foo.jpg --image.label nature
image=Image(path='foo.jpg', label='nature')

Behavior when accepts_keys=False:

# Modify the default command function's signature.
@app.default
def main(image: Annotated[Image, Parameter(accepts_keys=False)]):
   print(f"{image=}")
$ my-program --help
Usage: main COMMAND [ARGS] [OPTIONS]

╭─ Commands ──────────────────────────────────────────────────────────╮
│ --help -h  Display this message and exit.                           │
│ --version  Display application version.                             │
╰─────────────────────────────────────────────────────────────────────╯
╭─ Parameters ────────────────────────────────────────────────────────╮
│ *  IMAGE --image  [required]                                        │
╰─────────────────────────────────────────────────────────────────────╯

$ my-program foo.jpg nature
image=Image(path='foo.jpg', label='nature')

$ my-program --image foo.jpg nature
image=Image(path='foo.jpg', label='nature')

The accepts_keys=False option is commonly used with converter and n_tokens.

consume_multiple: None | bool | int | Sequence[int] = None

Controls how many CLI tokens a list/iterable parameter consumes when specified by keyword. If the parameter is specified positionally, Parameter.consume_multiple is ignored.

The following value types are supported:

  • False (default) — only a single element worth of CLI tokens will be consumed per keyword occurrence.

  • True — all remaining CLI tokens will be consumed until the stream is exhausted or an option-like token is reached. Providing the keyword with no values creates an empty container.

  • int — like True, but the integer specifies the minimum number of elements required. For example, consume_multiple=1 requires at least one value (preventing empty lists), and consume_multiple=0 is equivalent to True.

  • Sequence[int] — a (min, max) pair (e.g. a tuple or list of two ints). All remaining CLI tokens are consumed greedily, and a ConsumeMultipleError is raised if the number of elements is outside the (min, max) bounds.

Example: consume_multiple=True

from cyclopts import App, Parameter
from typing import Annotated

app = App()

@app.command
def name_ext(
    name: str,
    ext: Annotated[list[str], Parameter(consume_multiple=True)],
):
    for extension in ext:
        print(f"{name}.{extension}")

app()
$ my-program --name "my_file" --ext "txt" "pdf"  # stream is exhausted
my_file.txt
my_file.pdf

$ my-program --ext "txt" "pdf" --name "my_file"  # a keyword is reached
my_file.txt
my_file.pdf

When consume_multiple=True, providing the keyword flag without any values will create an empty container, equivalent to using the negative_iterable prefix (e.g., --empty-ext):

$ my-program --name "my_file" --ext
# No output - ext is an empty list []

$ my-program --name "my_file" --empty-ext
# No output - ext is an empty list []

Example: consume_multiple=1 (require at least one value)

from cyclopts import App, Parameter
from typing import Annotated

app = App()

@app.default
def main(
    urls: Annotated[list[str] | None, Parameter(consume_multiple=1)] = None,
):
    print(urls)

app()
$ my-program --urls http://a.com http://b.com
['http://a.com', 'http://b.com']

$ my-program --urls
╭─ Error ────────────────────────────────────────────╮
│ Parameter "--urls" requires an argument.            │
╰────────────────────────────────────────────────────╯

Example: consume_multiple=(1, 3) (min/max bounds)

from cyclopts import App, Parameter
from typing import Annotated

app = App()

@app.default
def main(
    files: Annotated[list[str], Parameter(consume_multiple=(1, 3))],
):
    print(f"Files: {files}")

app()
$ my-program --files a.txt b.txt
Files: ['a.txt', 'b.txt']

$ my-program --files a.txt b.txt c.txt d.txt
╭─ Error ─────────────────────────────────────────╮
│ Parameter "--files" accepts at most 3 elements. │
│ Got 4.                                          │
╰─────────────────────────────────────────────────╯

In this example, --files raises a ConsumeMultipleError if fewer than 1 or more than 3 values are provided.

Example: consume_multiple=False (default)

from cyclopts import App
from pathlib import Path

app = App()

@app.default
def name_ext(name: str, ext: list[str]): # same as `ext: Annotated[list[str], Parameter(consume_multiple=False)]``
    for extension in ext:
        print(f"{name}.{extension}")

app()
$ my-program --name "my_file" --ext "txt" "pdf"
╭─ Error ────────────────────────────────────────────╮
│ Unused Tokens: ['pdf'].                            │
╰────────────────────────────────────────────────────╯
json_dict: bool | None = None

Allow for the parsing of json-dict-strings as data. If None (default behavior), acts like True, unless the annotated type is union'd with str. When True, data will be parsed as json if the following conditions are met:

  1. The parameter is specified as a keyword option; e.g. --movie.

  2. The referenced parameter is dataclass-like.

  3. The first character of the token is a {.

json_list: bool | None = None

Allow for the parsing of json-list-strings as data. If None (default behavior), acts like True, unless the annotated type has each element type str. When True, data will be parsed as json if the following conditions are met:

  1. The referenced parameter is iterable (not including str).

  2. The first character of the token is a [.

count: bool = False

If True, count the number of times the flag appears instead of parsing a value. Each occurrence increments the count by 1 (e.g., -vvv results in 3).

Requirements and behavior:

  • The parameter must have an int type hint (or Optional[int]).

  • Short flags can be concatenated: -vvv is equivalent to -v -v -v.

  • Long flags can be repeated: --verbose --verbose results in 2.

  • Negative flag variants (e.g., --no-verbose) are not generated.

Common use case: verbosity levels.

from cyclopts import App, Parameter
from typing import Annotated

app = App()

@app.default
def main(verbose: Annotated[int, Parameter(name="-v", count=True)] = 0):
   print(f"Verbosity level: {verbose}")

app()
$ my-script -vvv
Verbosity level: 3

See Coercion Rules for more details.

allow_repeating: bool | None = None

Controls whether a keyword option can be specified multiple times on the CLI (e.g., --foo a --foo b).

  • None (default): iterable types accumulate values, scalar types raise RepeatArgumentError.

  • False: always raise RepeatArgumentError on repeated options. Useful with consume_multiple to allow --foo a b c but disallow --foo a --foo b.

  • True: always allow repeated options. Iterable types accumulate as usual. Scalar types use "last wins" semantics (the last value specified is used).

from cyclopts import App, Parameter
from typing import Annotated

app = App()

@app.default
def main(
    values: Annotated[list[str], Parameter(consume_multiple=True, allow_repeating=False)],
):
    print(values)

app()
$ my-script --values a b c
['a', 'b', 'c']

$ my-script --values a --values b
╭─ Error ──────────────────────────────────────────────────╮
│ Parameter "--values" was specified multiple times.       │
╰─────────────────────────────────────────────────────────╯
n_tokens: int | None = None

Explicitly override the number of CLI tokens this parameter consumes.

By default, Cyclopts infers the token count from the parameter's type hint (e.g., int consumes 1 token, tuple[int, int] consumes 2, list consumes all remaining). This attribute allows you to override that inference, which is particularly useful when:

  • Using custom converters that need a different token count than the type suggests.

  • Loading complex types from a single token (e.g., loading from a file path).

  • Implementing selection/lookup patterns where one token identifies an object.

Values:

  • None (default): Infer token count from the type hint.

  • non-negative integer: Consume exactly that many tokens.

  • -1: Consume all remaining tokens (similar to iterables).

For *args parameters, n_tokens specifies tokens per element. For example, n_tokens=2 with 6 tokens creates 3 elements.

from cyclopts import App, Parameter
from typing import Annotated

class Config:
    def __init__(self, host: str, port: int):
        self.host = host
        self.port = port

def load_config(type_, tokens):
    # Load config from a file path (single token)
    filepath = tokens[0].value
    # ... load from file ...
    return Config("example.com", 8080)

app = App()

@app.default
def main(
    config: Annotated[
        Config,
        Parameter(n_tokens=1, converter=load_config, accepts_keys=False)
    ]
):
    print(f"Connecting to {config.host}:{config.port}")

app()
$ my-script --config prod.conf
Connecting to example.com:8080
classmethod combine(*parameters: Parameter | None) Parameter

Returns a new Parameter with combined values of all provided parameters.

Parameters:

*parameters (Parameter | None) -- Parameters who's attributes override self attributes. Ordered from least-to-highest attribute priority.

classmethod default() Self

Create a Parameter with all Cyclopts-default values.

This is different than just Parameter because the default values will be recorded and override all upstream parameter values.

__call__(obj: T) T

Decorator interface for annotating a function/class with a Parameter.

Most commonly used for directly configuring a class:

@Parameter(...)
class Foo: ...
class cyclopts.Group(name: str = '', help: str = '', *, show: bool | None = None, sort_key: Any = None, validator: None | Callable[[ArgumentCollection], Any] | Iterable[Callable[[ArgumentCollection], Any]] = None, default_parameter: Parameter | None = None, help_formatter: None | Literal['default', 'plain'] | HelpFormatter = None)

A group of parameters and/or commands in a CLI application.

name: str = ""

Group name used for the help-page and for group-referenced-by-string. This is a title, so the first character should be capitalized. If a name is not specified, it will not be shown on the help-page.

help: str = ""

Additional documentation shown on the help-page. This will be displayed inside the group's panel, above the parameters/commands.

show: bool | None = None

Show this group on the help-page. Defaults to None, which will only show the group if a name is provided.

help_formatter: None | Literal['default', 'plain'] | HelpFormatter = None

Help formatter to use for rendering this group's help panel.

This allows per-group customization of help appearance:

from cyclopts import App, Group, Parameter
from cyclopts.help import DefaultFormatter, PanelSpec
from typing import Annotated

app = App()

# Using string literal
simple_group = Group(
    "Simple Options",
    help_formatter="plain"
)

# Using custom formatter instance
custom_group = Group(
    "Custom Options",
    help_formatter=DefaultFormatter(
        panel_spec=PanelSpec(border_style="red")
    )
)

@app.default
def main(
    opt1: Annotated[str, Parameter(group=simple_group)],
    opt2: Annotated[str, Parameter(group=custom_group)]
):
    pass

See Help Customization for detailed examples.

sort_key: Any = None

Modifies group-panel display order on the help-page.

  1. If sort_key is a generator, it will be consumed immediately with next() to get the actual value.

  2. If sort_key, or any of it's contents, are Callable, then invoke it sort_key(group) and apply the rules below.

  3. The App default groups (App.group_command, App.group_arguments, App.group_parameters) will be displayed first. If you want to further customize the ordering of these default groups, you can define custom values and they will be treated like any other group:

    from cyclopts import App, Group
    
    app = App(
        group_parameters=Group("Parameters", sort_key=1),
        group_arguments=Group("Arguments", sort_key=2),
        group_commands=Group("Commands", sort_key=3),
    )
    
    
    @app.default
    def main(foo, /, bar):
        pass
    
    
    if __name__ == "__main__":
        app()
    
$ python main.py --help
Usage: main [ARGS] [OPTIONS]

╭─ Parameters ──────────────────────────────────────────────────────────╮
│ *  BAR --bar  [required]                                              │
╰───────────────────────────────────────────────────────────────────────╯
╭─ Arguments ───────────────────────────────────────────────────────────╮
│ *  FOO  [required]                                                    │
╰───────────────────────────────────────────────────────────────────────╯
╭─ Commands ────────────────────────────────────────────────────────────╮
│ --help -h  Display this message and exit.                             │
│ --version  Display application version.                               │
╰───────────────────────────────────────────────────────────────────────╯
  1. For all groups with sort_key!=None, sort them by (sort_key, group.name). That is, sort them by their sort_key, and then break ties alphabetically. It is the user's responsibility that sort_key are comparable.

  2. For all groups with sort_key==None (default value), sort them alphabetically after (4), App.group_commands, App.group_arguments, and App.group_parameters.

Example usage:

from cyclopts import App, Group

app = App()

@app.command(group=Group("4", sort_key=5))
def cmd1():
    pass


@app.command(group=Group("3", sort_key=lambda x: 10))
def cmd2():
    pass


@app.command(group=Group("2", sort_key=lambda x: None))
def cmd3():
    pass


@app.command(group=Group("1"))
def cmd4():
    pass

app()

Resulting help-page:

Usage: app COMMAND

╭─ 4 ────────────────────────────────────────────────────────────────╮
│ cmd1                                                               │
╰────────────────────────────────────────────────────────────────────╯
╭─ 3 ────────────────────────────────────────────────────────────────╮
│ cmd2                                                               │
╰────────────────────────────────────────────────────────────────────╯
╭─ 1 ────────────────────────────────────────────────────────────────╮
│ cmd4                                                               │
╰────────────────────────────────────────────────────────────────────╯
╭─ 2 ────────────────────────────────────────────────────────────────╮
│ cmd3                                                               │
╰────────────────────────────────────────────────────────────────────╯
╭─ Commands ─────────────────────────────────────────────────────────╮
│ --help,-h  Display this message and exit.                          │
│ --version  Display application version.                            │
╰────────────────────────────────────────────────────────────────────╯
default_parameter: Parameter | None = None

Default Parameter in the parameter-resolution-stack that goes between App.default_parameter and the function signature's Annotated Parameter. The provided Parameter is not allowed to have a group value.

validator: Callable | None = None

A function (or list of functions) that validates an ArgumentCollection.

Example usage:

def validator(argument_collection: ArgumentCollection):
    "Raise an exception if something is invalid."

The ArgumentCollection will contain all arguments that belong to that group. The validator(s) will always be invoked, regardless if any argument within the collection has token(s).

Validators are not invoked for command groups.

classmethod create_ordered(name='', help='', *, show=None, sort_key=None, validator=None, default_parameter=None, help_formatter=None) Self

Create a group with a globally incrementing sort_key.

Used to create a group that will be displayed after a previously instantiated Group.create_ordered() group on the help-page.

Parameters:
  • name (str) -- Group name used for the help-page and for group-referenced-by-string. This is a title, so the first character should be capitalized. If a name is not specified, it will not be shown on the help-page.

  • help (str) -- Additional documentation shown on the help-page. This will be displayed inside the group's panel, above the parameters/commands.

  • show (bool | None) -- Show this group on the help-page. Defaults to None, which will only show the group if a name is provided.

  • sort_key (Any) -- If provided, prepended to the globally incremented counter value (i.e. has priority during sorting).

  • validator (None | Callable[[ArgumentCollection], Any] | Iterable[Callable[[ArgumentCollection], Any]]) -- Group validator to collectively apply.

  • default_parameter (cyclopts.Parameter | None) -- Default parameter for elements within the group.

  • help_formatter (cyclopts.help.protocols.HelpFormatter | None) -- Custom help formatter for this group's help display.

class cyclopts.Token(*, keyword: str | None = None, value: str = '', source: str = '', index: int = 0, keys: tuple[str, ...] = (), implicit_value: ~typing.Any = <UNSET>)

Tracks how a user supplied a value to the application.

keyword: str | None = None

Unadulterated user-supplied keyword like --foo or --foo.bar.baz; None when token was pared positionally. Could also be something like tool.project.foo if from non-cli sources.

value: str = ""

The parsed token value (unadulterated).

source: str = ""

Where the token came from; used for error message purposes. Cyclopts uses the string cli for cli-parsed tokens.

index: int = 0

The relative positional index in which the value was provided.

keys: tuple[str, ...] = ()

The additional parsed python variable keys from keyword.

Only used for Arguments that take arbitrary keys.

implicit_value: Any = cyclopts.UNSET

Final value that should be used instead of converting from value.

Commonly used for boolean flags.

Ignored if UNSET.

class cyclopts.field_info.FieldInfo(names: tuple[str, ...] = (), kind: _ParameterKind = _ParameterKind.POSITIONAL_OR_KEYWORD, *, required: bool = False, default: Any, annotation: Any, help: str | None = None)

Extension of inspect.Parameter.

class cyclopts.Argument(*, tokens: list[~cyclopts.token.Token] = NOTHING, field_info: ~cyclopts.field_info.FieldInfo = NOTHING, parameter: ~cyclopts.parameter.Parameter = NOTHING, hint: ~typing.Any = <class 'str'>, index: int | None = None, keys: tuple[str, ...] = (), value: ~typing.Any = <UNSET>)

Encapsulates functionality and additional contextual information for parsing a parameter.

An argument is defined as anything that would have its own entry in the help page.

tokens: list[Token]

List of Token parsed from various sources. Do not directly mutate; see append().

field_info: FieldInfo

Additional information about the parameter from surrounding python syntax.

parameter: Parameter

Fully resolved user-provided Parameter.

hint: Any

The type hint for this argument; may be different from FieldInfo.annotation.

index: int | None

Associated python positional index for argument. If None, then cannot be assigned positionally.

keys: tuple[str, ...]

Python keys that lead to this leaf.

self.parameter.name and self.keys can naively disagree! For example, a self.parameter.name="--foo.bar.baz" could be aliased to "--fizz". The resulting self.keys would be ("bar", "baz").

This is populated based on type-hints and class-structure, not Parameter.name.

from cyclopts import App, Parameter
from dataclasses import dataclass
from typing import Annotated

app = App()


@dataclass
class User:
    id: int
    name: Annotated[str, Parameter(name="--fullname")]


@app.default
def main(user: User):
    pass


for argument in app.assemble_argument_collection():
    print(f"name: {argument.name:16} hint: {str(argument.hint):16} keys: {str(argument.keys)}")
$ my-script
name: --user.id        hint: <class 'int'>    keys: ('id',)
name: --fullname       hint: <class 'str'>    keys: ('name',)
children: ArgumentCollection

Collection of other Argument that eventually culminate into the python variable represented by field_info.

property value

Converted value from last convert() call.

This value may be stale if fields have changed since last convert() call. UNSET if convert() has not yet been called with tokens.

property show_default: bool | Callable[[Any], str]

Show the default value on the help page.

match(term: str | int, *, transform: Callable[[str], str] | None = None, delimiter: str = '.') tuple[tuple[str, ...], Any]

Match a name search-term, or a positional integer index.

Raises:

ValueError -- If no match is found.

Returns:

  • tuple[str, ...] -- Leftover keys after matching to this argument. Used if this argument accepts_arbitrary_keywords.

  • Any -- Implicit value. UNSET if no implicit value is applicable.

append(token: Token)

Safely add a Token.

property has_tokens: bool

This argument, or a child argument, has at least 1 parsed token.

property children_recursive: ArgumentCollection
convert(converter: Callable | None = None)

Converts tokens into value.

Parameters:

converter (Callable | None) -- Converter function to use. Overrides self.parameter.converter

Returns:

The converted data. Same as value.

Return type:

Any

validate(value)

Validates provided value.

Parameters:

value -- Value to validate.

Returns:

The converted data. Same as value.

Return type:

Any

convert_and_validate(converter: Callable | None = None)

Converts and validates tokens into value.

Parameters:

converter (Callable | None) -- Converter function to use. Overrides self.parameter.converter

Returns:

The converted data. Same as value.

Return type:

Any

token_count(keys: tuple[str, ...] = ())

The number of string tokens this argument consumes.

Parameters:

keys (tuple[str, ...]) -- The python keys into this argument. If provided, returns the number of string tokens that specific data type within the argument consumes.

Returns:

  • int -- Number of string tokens to create 1 element.

  • consume_all (bool) -- True if this data type is iterable.

property negatives

Negative flags from Parameter.get_negatives().

property name: str

The first provided name this argument goes by.

property names: tuple[str, ...]

Names the argument goes by (both positive and negative).

env_var_split(value: str, delimiter: str | None = None) list[str]

Split a given value with Parameter.env_var_split().

property show: bool

Show this argument on the help page.

If an argument has child arguments, don't show it on the help-page. Returns False for arguments that won't be parsed (including underscore-prefixed params).

property parse: bool

Whether this argument should be parsed from CLI tokens.

If Parameter.parse is a regex pattern, parse if the pattern matches the field name; otherwise don't parse.

property required: bool

Whether or not this argument requires a user-provided value.

is_positional_only() bool
is_var_positional() bool
is_flag() bool

Check if this argument is a flag (consumes no CLI tokens).

Flags are arguments that don't consume command-line tokens after the option name. They typically have implicit values (e.g., --verbose for bool, --no-items for list).

Returns:

True if the argument consumes zero tokens from the command line.

Return type:

bool

Examples

>>> from cyclopts import Parameter
>>> bool_arg = Argument(hint=bool, parameter=Parameter(name="--verbose"))
>>> bool_arg.is_flag()
True
>>> str_arg = Argument(hint=str, parameter=Parameter(name="--name"))
>>> str_arg.is_flag()
False
get_choices(force: bool = False) tuple[str, ...] | None

Extract completion choices from type hint.

Extracts choices from Literal types, Enum types, and Union types containing them. Respects the Parameter.show_choices setting unless force=True.

Parameters:

force (bool) -- If True, return choices even when show_choices=False. Used by shell completion to always provide choices.

Returns:

Tuple of choice strings if choices exist and should be shown, None otherwise.

Return type:

tuple[str, ...] | None

Examples

>>> argument = Argument(hint=Literal["dev", "staging", "prod"], parameter=Parameter(show_choices=True))
>>> argument.get_choices()
('dev', 'staging', 'prod')
>>> argument = Argument(hint=Literal["dev", "staging", "prod"], parameter=Parameter(show_choices=False))
>>> argument.get_choices()  # Returns None for help text
>>> argument.get_choices(force=True)  # Returns choices for completion
('dev', 'staging', 'prod')
class cyclopts.ArgumentCollection(*args)

A list-like container for Argument.

copy() ArgumentCollection

Returns a shallow copy of the ArgumentCollection.

__contains__(item: object, /) bool

Check if an argument or argument name exists in the collection.

Parameters:

item (Argument | str) -- Either an Argument object or a string name/alias to search for.

Returns:

True if the item is in the collection.

Return type:

bool

Examples

>>> argument_collection = ArgumentCollection(
...     [
...         Argument(parameter=Parameter(name="--foo")),
...         Argument(parameter=Parameter(name=("--bar", "-b"))),
...     ]
... )
>>> "--foo" in argument_collection
True
>>> "-b" in argument_collection  # Alias matching
True
>>> "--baz" in argument_collection
False
get(term: str | int, default: type[<UNSET>] = <UNSET>, *, transform: ~collections.abc.Callable[[str], str] | None = None, delimiter: str = '.') Argument
get(term: str | int, default: T, *, transform: Callable[[str], str] | None = None, delimiter: str = '.') Argument | T

Get an Argument by name or index.

This is a convenience wrapper around match() that returns just the Argument object instead of a tuple.

Parameters:
  • term (str | int) -- Either a string keyword or an integer positional index.

  • default (Any) -- Default value to return if term not found. If UNSET (default), will raise KeyError/IndexError.

  • transform (Callable[[str], str] | None) -- Optional function to transform string terms before matching.

  • delimiter (str) -- Delimiter for nested field access.

Returns:

The matched Argument, or default if provided and not found.

Return type:

Argument | None

Raises:
  • KeyError -- If term is a string and not found (when default is UNSET).

  • IndexError -- If term is an int and is out-of-range (when default is UNSET).

See also

match()

Returns a tuple of (Argument, keys, value) with more detailed information.

match(term: str | int, *, transform: Callable[[str], str] | None = None, delimiter: str = '.') tuple[Argument, tuple[str, ...], Any]

Matches CLI keyword or index to their Argument.

Parameters:

term (str | int) --

One of:

  • str keyword like "--foo" or "-f" or "--foo.bar.baz".

  • int global positional index.

Raises:

ValueError -- If the provided term doesn't match.

Returns:

  • Argument -- Matched Argument.

  • tuple[str, ...] -- Python keys into Argument. Non-empty iff Argument accepts keys.

  • Any -- Implicit value (if a flag). UNSET otherwise.

property groups
filter_by(*, group: Group | None = None, has_tokens: bool | None = None, has_tree_tokens: bool | None = None, keys_prefix: tuple[str, ...] | None = None, kind: _ParameterKind | None = None, parse: bool | None = None, show: bool | None = None, value_set: bool | None = None) ArgumentCollection

Filter the ArgumentCollection.

All non-None filters will be applied.

Parameters:
  • group (Group | None) -- The Group the arguments should be in.

  • has_tokens (bool | None) -- Immediately has tokens (not including children).

  • has_tree_tokens (bool | None) -- Argument and/or it's children have parsed tokens.

  • kind (inspect._ParameterKind | None) -- The kind of the argument.

  • parse (bool | None) -- If the argument is intended to be parsed or not.

  • show (bool | None) -- The Argument is intended to be show on the help page.

  • value_set (bool | None) -- The converted value is set.

class cyclopts.UNSET

Special sentinel value indicating that no data was provided. Do not instantiate.

cyclopts.default_name_transform(s: str) str

Converts a python identifier into a CLI token.

Performs the following operations (in order):

  1. Convert PascalCase to snake_case.

  2. Convert the string to all lowercase.

  3. Replace _ with -.

  4. Strip any leading/trailing - (also stripping _, due to point 3).

Intended to be used with App.name_transform and Parameter.name_transform.

Parameters:

s (str) -- Input python identifier string.

Returns:

Transformed name.

Return type:

str

cyclopts.env_var_split(type_: Any, val: str, *, delimiter: str | None = None) list[str]

Type-dependent environment variable value splitting.

Converts a single string into a list of strings. Splits when:

  • The type_ is some variant of Iterable[pathlib.Path] objects. If Windows, split on ;, otherwise split on :.

  • Otherwise, if the type_ is an Iterable, split on whitespace. Leading/trailing whitespace of each output element will be stripped.

This function is the default value for cyclopts.App.env_var_split.

Parameters:
  • type (type) -- Type hint that we will eventually coerce into.

  • val (str) -- String to split.

  • delimiter (str | None) -- Delimiter to split val on. If None, defaults to whitespace.

Returns:

List of individual string tokens.

Return type:

list[str]

cyclopts.edit(initial_text: str = '', *, fallback_editors: Sequence[str] = ('nano', 'vim', 'notepad', 'gedit'), editor_args: Sequence[str] = (), path: str | Path = '', encoding: str = 'utf-8', save: bool = True, required: bool = True) str

Get text input from a user by launching their default text editor.

Parameters:
  • initial_text (str) -- Initial text to populate the text file with.

  • fallback_editors (Sequence[str]) -- If the text editor cannot be determined from the environment variable EDITOR, attempt to use these text editors in the order provided.

  • editor_args (Sequence[str]) -- Additional CLI arguments that are passed along to the editor-launch command.

  • path (Union[str, Path]) -- If specified, the path to the file that should be opened. Text editors typically display this, so a custom path may result in a better user-interface. Defaults to a temporary text file.

  • encoding (str) -- File encoding to use.

  • save (bool) -- Require the user to save before exiting the editor. Otherwise raises EditorDidNotSaveError.

  • required (bool) -- Require for the saved text to be different from initial_text. Otherwise raises EditorDidNotChangeError.

Raises:
Returns:

The resulting text that was saved by the text editor.

Return type:

str

cyclopts.run(callable: Callable[[...], Coroutine[None, None, V]], /, *, result_action: Literal['return_value']) V
cyclopts.run(callable: Callable[[...], V], /, *, result_action: Literal['return_value']) V
cyclopts.run(callable: Callable[[...], Coroutine[None, None, Any]], /, *, result_action: Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any] | Iterable[Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any]] | None = None) Any
cyclopts.run(callable: Callable[[...], Any], /, *, result_action: Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any] | Iterable[Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any]] | None = None) Any

Run the given callable as a CLI command.

The callable may also be a coroutine function. This function is syntax sugar for very simple use cases, and is roughly equivalent to:

from cyclopts import App

app = App()
app.default(callable)
app()
Parameters:
  • callable -- The function to execute as a CLI command.

  • result_action -- How to handle the command's return value. If not specified, uses the default "print_non_int_sys_exit" which calls sys.exit() with the appropriate code. Can be set to "return_value" to return the result directly for testing/embedding.

  • usage (Example)

  • code-block: (..) --

    python: import cyclopts

    def main(name: str, age: int):

    print(f"Hello {name}, you are {age} years old.")

    cyclopts.run(main)

class cyclopts.CycloptsPanel(message: Any, title: str = 'Error', style: str = 'red')

Create a Panel with a consistent style.

The resulting panel can be displayed using a Console.

╭─ Title ──────────────────────────────────╮
│ Message content here.                    │
╰──────────────────────────────────────────╯
Parameters:
  • message (Any) -- The body of the panel will be filled with the stringified version of the message.

  • title (str) -- Title of the panel that appears in the top-left corner.

  • style (str) -- Rich style for the panel border.

Returns:

Formatted panel object.

Return type:

Panel

Validators

Cyclopts has several builtin validators for common CLI inputs.

class cyclopts.validators.LimitedChoice(min: int = 0, max: int | None = None, allow_none: bool = False)

Group validator that limits the number of selections per group.

Commonly used for enforcing mutually-exclusive parameters (default behavior).

Parameters:
  • min (int) -- The minimum (inclusive) number of CLI parameters allowed. If negative, then all parameters in the group must have CLI values provided.

  • max (int | None) -- The maximum (inclusive) number of CLI parameters allowed. Defaults to 1 if min==0, min otherwise.

  • allow_none (bool) -- If True, also allow 0 CLI parameters (even if min is greater than 0). Defaults to False.

class cyclopts.validators.MutuallyExclusive

Alias for LimitedChoice to make intentions more obvious.

Only 1 argument in the group can be supplied a value.

cyclopts.validators.mutually_exclusive = <cyclopts.validators._group.MutuallyExclusive object>

Instantiated version of MutuallyExclusive. Can be used directly in group validators:

import cyclopts
from cyclopts import Group

mutually_exclusive_group = Group(validator=cyclopts.validators.mutually_exclusive)
cyclopts.validators.all_or_none = <cyclopts.validators._group.LimitedChoice object>

Group validator that enforces that either all parameters in the group must be supplied an argument, or none of them.

class cyclopts.validators.Number(*, lt: int | float | None = None, lte: int | float | None = None, gt: int | float | None = None, gte: int | float | None = None, modulo: int | float | None = None)

Limit input number to a value range.

Example Usage:

from cyclopts import App, Parameter, validators
from typing import Annotated

app = App()


@app.default
def main(age: Annotated[int, Parameter(validator=validators.Number(gte=0, lte=150))]):
    print(f"You are {age} years old.")


app()
$ my-script 100
You are 100 years old.

$ my-script -1
╭─ Error ───────────────────────────────────────────────────────╮
│ Invalid value "-1" for "AGE". Must be >= 0.                   │
╰───────────────────────────────────────────────────────────────╯

$ my-script 200
╭─ Error ───────────────────────────────────────────────────────╮
│ Invalid value "200" for "AGE". Must be <= 150.                │
╰───────────────────────────────────────────────────────────────╯
lt: int | float | None

Input value must be less than this value.

lte: int | float | None

Input value must be less than or equal this value.

gt: int | float | None

Input value must be greater than this value.

gte: int | float | None

Input value must be greater than or equal this value.

modulo: int | float | None

Input value must be a multiple of this value.

class cyclopts.validators.Path(*, exists: bool = False, file_okay: bool = True, dir_okay: bool = True, ext: str | Iterable[str] | None = None)

Assertions on properties of pathlib.Path.

Example Usage:

from cyclopts import App, Parameter, validators
from pathlib import Path
from typing import Annotated

app = App()


@app.default
def main(
    # ``src`` must be a file that exists.
    src: Annotated[Path, Parameter(validator=validators.Path(exists=True, dir_okay=False))],
    # ``dst`` must be a path that does **not** exist.
    dst: Annotated[Path, Parameter(validator=validators.Path(dir_okay=False, file_okay=False))],
):
    "Copies src->dst."
    dst.write_bytes(src.read_bytes())


app()
$ my-script foo.bin bar.bin  # if foo.bin does not exist
╭─ Error ───────────────────────────────────────────────────────╮
│ Invalid value "foo.bin" for "SRC". "foo.bin" does not exist.  │
╰───────────────────────────────────────────────────────────────╯

$ my-script foo.bin bar.bin  # if bar.bin exists
╭─ Error ───────────────────────────────────────────────────────╮
│ Invalid value "bar.bin" for "DST". "bar.bin" already exists.  │
╰───────────────────────────────────────────────────────────────╯
exists: bool

If True, specified path must exist. Defaults to False.

file_okay: bool

If path exists, check it's type:

  • If True, specified path may be an existing file.

  • If False, then existing files are not allowed.

Defaults to True.

dir_okay: bool

If path exists, check it's type:

  • If True, specified path may be an existing directory.

  • If False, then existing directories are not allowed.

Defaults to True.

ext: str | Sequence[str]

Supplied path must have this extension (case insensitive). May or may not include the ".".

Types

Cyclopts has builtin pre-defined annotated-types for common conversion and validation configurations. Most definitions in this section are simply predefined annotations for convenience:

Annotated[..., Parameter(...)]

Custom classes that provide additional functionality beyond simple annotations will be noted.

Due to Cyclopts's advanced Parameter resolution engine, these annotations can themselves be annotated to further configure behavior. E.g:

Annotated[PositiveInt, Parameter(...)]

Path

Path annotated types for checking existence, type, and performing path-resolution. All of these types will also work on sequence of paths (e.g. tuple[Path, Path] or list[Path]).

class cyclopts.types.StdioPath

Note

This is a custom class, not a simple Annotated type alias.

Requires Python 3.12+ due to Path subclassing support.

A Path subclass that treats - as stdin (for reading) or stdout (for writing). This follows common Unix convention.

StdioPath is pre-configured with allow_leading_hyphen=True, so - can be passed as an argument without being interpreted as an option.

STDIO_STRING: str = "-"

Class attribute defining the string that triggers stdio behavior. Override in subclasses to use a different string.

is_stdio: bool

Returns True if this path represents stdin/stdout (i.e., str(self) == STDIO_STRING). Override this property in subclasses for custom matching logic (e.g., matching multiple strings).

Basic usage:

from cyclopts import App
from cyclopts.types import StdioPath

app = App()

@app.default
def main(input_file: StdioPath):
    data = input_file.read_text()
    print(data.upper())

app()
$ echo "hello" | python my_script.py -
HELLO

$ python my_script.py data.txt
<contents of data.txt uppercased>

To default to stdin/stdout when no argument is provided:

@app.default
def main(input_file: StdioPath = StdioPath("-")):
    data = input_file.read_text()
    print(data.upper())

See Reading/Writing From File or Stdin/Stdout for more examples.

Subclassing

To use a different trigger string or custom matching logic, subclass StdioPath:

from cyclopts.types import StdioPath

# Simple: different trigger string
class StdinPath(StdioPath):
    STDIO_STRING = "STDIN"

class StdoutPath(StdioPath):
    STDIO_STRING = "STDOUT"

# Advanced: match multiple strings
class MultiStdioPath(StdioPath):
    @property
    def is_stdio(self) -> bool:
        return str(self) in ("-", "STDIN", "STDOUT")
cyclopts.types.ExistingPath

A Path file or directory that must exist.

alias of Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=True, ext=()),))]

cyclopts.types.NonExistentPath

A Path file or directory that must not exist.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=()),))]

cyclopts.types.ResolvedPath

A Path file or directory. resolve() is invoked prior to returning the path.

cyclopts.types.ResolvedExistingPath

A Path file or directory that must exist. resolve() is invoked prior to returning the path.

cyclopts.types.Directory

A Path that must be a directory (or not exist).

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=True, ext=()),))]

cyclopts.types.ExistingDirectory

A Path directory that must exist.

alias of Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=False, dir_okay=True, ext=()),))]

cyclopts.types.NonExistentDirectory

A Path directory that must not exist.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=()),))]

cyclopts.types.ResolvedDirectory

A Path directory. resolve() is invoked prior to returning the path.

cyclopts.types.ResolvedExistingDirectory

A Path directory that must exist. resolve() is invoked prior to returning the path.

cyclopts.types.File

A File that must be a file (or not exist).

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=()),))]

cyclopts.types.ExistingFile

A Path file that must exist.

alias of Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=()),))]

cyclopts.types.NonExistentFile

A Path file that must not exist.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=()),))]

cyclopts.types.ResolvedFile

A Path file. resolve() is invoked prior to returning the path.

cyclopts.types.ResolvedExistingFile

A Path file that must exist. resolve() is invoked prior to returning the path.

cyclopts.types.BinPath

A Path that must have extension bin.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('bin',)),))]

cyclopts.types.ExistingBinPath

A Path that must exist and have extension bin.

alias of Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('bin',)),))]

cyclopts.types.NonExistentBinPath

A Path that must not exist and have extension bin.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('bin',)),))]

cyclopts.types.CsvPath

A Path that must have extension csv.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('csv',)),))]

cyclopts.types.ExistingCsvPath

A Path that must exist and have extension csv.

alias of Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('csv',)),))]

cyclopts.types.NonExistentCsvPath

A Path that must not exist and have extension csv.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('csv',)),))]

cyclopts.types.TxtPath

A Path that must have extension txt.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('txt',)),))]

cyclopts.types.ExistingTxtPath

A Path that must exist and have extension txt.

alias of Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('txt',)),))]

cyclopts.types.NonExistentTxtPath

A Path that must not exist and have extension txt.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('txt',)),))]

cyclopts.types.ImagePath

A Path that must have extension in {png, jpg, jpeg}.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('png', 'jpg', 'jpeg')),))]

cyclopts.types.ExistingImagePath

A Path that must exist and have extension in {png, jpg, jpeg}.

alias of Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('png', 'jpg', 'jpeg')),))]

cyclopts.types.NonExistentImagePath

A Path that must not exist and have extension in {png, jpg, jpeg}.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('png', 'jpg', 'jpeg')),))]

cyclopts.types.Mp4Path

A Path that must have extension mp4.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('mp4',)),))]

cyclopts.types.ExistingMp4Path

A Path that must exist and have extension mp4.

alias of Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('mp4',)),))]

cyclopts.types.NonExistentMp4Path

A Path that must not exist and have extension mp4.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('mp4',)),))]

cyclopts.types.JsonPath

A Path that must have extension json.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('json',)),))]

cyclopts.types.ExistingJsonPath

A Path that must exist and have extension json.

alias of Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('json',)),))]

cyclopts.types.NonExistentJsonPath

A Path that must not exist and have extension json.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('json',)),))]

cyclopts.types.TomlPath

A Path that must have extension toml.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('toml',)),))]

cyclopts.types.ExistingTomlPath

A Path that must exist and have extension toml.

alias of Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('toml',)),))]

cyclopts.types.NonExistentTomlPath

A Path that must not exist and have extension toml.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('toml',)),))]

cyclopts.types.YamlPath

A Path that must have extension yaml.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('yaml',)),))]

cyclopts.types.ExistingYamlPath

A Path that must exist and have extension yaml.

alias of Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('yaml',)),))]

cyclopts.types.NonExistentYamlPath

A Path that must not exist and have extension yaml.

alias of Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('yaml',)),))]

Number

Annotated types for checking common int/float value constraints. All of these types will also work on sequence of numbers (e.g. tuple[int, int] or list[float]).

cyclopts.types.PositiveFloat

A float that must be >0.

alias of Annotated[float, Parameter(validator=(Number(lt=None, lte=None, gt=0, gte=None, modulo=None),))]

cyclopts.types.NonNegativeFloat

A float that must be >=0.

alias of Annotated[float, Parameter(validator=(Number(lt=None, lte=None, gt=None, gte=0, modulo=None),))]

cyclopts.types.NegativeFloat

A float that must be <0.

alias of Annotated[float, Parameter(validator=(Number(lt=0, lte=None, gt=None, gte=None, modulo=None),))]

cyclopts.types.NonPositiveFloat

A float that must be <=0.

alias of Annotated[float, Parameter(validator=(Number(lt=None, lte=0, gt=None, gte=None, modulo=None),))]

cyclopts.types.NormFloat

A float in the range [0, 1].

alias of Annotated[float, Parameter(validator=(Number(lt=None, lte=1, gt=None, gte=0, modulo=None),))]

cyclopts.types.SignedNormFloat

A float in the range [-1, 1].

alias of Annotated[float, Parameter(validator=(Number(lt=None, lte=1, gt=None, gte=-1, modulo=None),))]

cyclopts.types.PositiveInt

An int that must be >0.

alias of Annotated[int, Parameter(validator=(Number(lt=None, lte=None, gt=0, gte=None, modulo=None),))]

cyclopts.types.NonNegativeInt

An int that must be >=0.

alias of Annotated[int, Parameter(validator=(Number(lt=None, lte=None, gt=None, gte=0, modulo=None),))]

cyclopts.types.NegativeInt

An int that must be <0.

alias of Annotated[int, Parameter(validator=(Number(lt=0, lte=None, gt=None, gte=None, modulo=None),))]

cyclopts.types.NonPositiveInt

An int that must be <=0.

alias of Annotated[int, Parameter(validator=(Number(lt=None, lte=0, gt=None, gte=None, modulo=None),))]

cyclopts.types.PercentInt

An int in the range [0, 100].

alias of Annotated[int, Parameter(validator=(Number(lt=None, lte=100, gt=None, gte=0, modulo=None),))]

cyclopts.types.UInt8

An unsigned 8-bit integer.

alias of Annotated[int, Parameter(validator=(Number(lt=None, lte=255, gt=None, gte=0, modulo=None),))]

cyclopts.types.HexUInt8

An unsigned 8-bit integer who's default value will be displayed as hexadecimal in the help-page.

cyclopts.types.Int8

A signed 8-bit integer.

alias of Annotated[int, Parameter(validator=(Number(lt=None, lte=127, gt=None, gte=-128, modulo=None),))]

cyclopts.types.UInt16

An unsigned 16-bit integer.

alias of Annotated[int, Parameter(validator=(Number(lt=None, lte=65535, gt=None, gte=0, modulo=None),))]

cyclopts.types.HexUInt16

An unsigned 16-bit integer who's default value will be displayed as hexadecimal in the help-page.

cyclopts.types.Int16

A signed 16-bit integer.

alias of Annotated[int, Parameter(validator=(Number(lt=None, lte=32767, gt=None, gte=-32768, modulo=None),))]

cyclopts.types.UInt32

An unsigned 32-bit integer.

alias of Annotated[int, Parameter(validator=(Number(lt=4294967296, lte=None, gt=None, gte=0, modulo=None),))]

cyclopts.types.HexUInt32

An unsigned 32-bit integer who's default value will be displayed as hexadecimal in the help-page.

cyclopts.types.Int32

A signed 32-bit integer.

alias of Annotated[int, Parameter(validator=(Number(lt=2147483648, lte=None, gt=None, gte=-2147483648, modulo=None),))]

cyclopts.types.UInt64

An unsigned 64-bit integer.

alias of Annotated[int, Parameter(validator=(Number(lt=18446744073709551616, lte=None, gt=None, gte=0, modulo=None),))]

cyclopts.types.HexUInt64

An unsigned 64-bit integer who's default value will be displayed as hexadecimal in the help-page.

cyclopts.types.Int64

A signed 64-bit integer.

alias of Annotated[int, Parameter(validator=(Number(lt=9223372036854775808, lte=None, gt=None, gte=-9223372036854775808, modulo=None),))]

Json

Annotated types for parsing a json-string from the CLI.

cyclopts.types.Json

Parse a json-string from the CLI.

Note: Since Cyclopts v3.6.0, all dataclass-like classes now natively attempt to parse json-strings, so practical use-case of this annotation is limited.

Usage example:

from cyclopts import App, types

app = App()

@app.default
def main(json: types.Json):
    print(json)

app()
$ my-script '{"foo": 1, "bar": 2}'
{'foo': 1, 'bar': 2}

Web

Annotated types for common web-related values.

cyclopts.types.Email

An email address string with simple validation.

cyclopts.types.Port

An int limited to range [0, 65535].

alias of Annotated[int, Parameter(validator=(Number(lt=None, lte=65535, gt=None, gte=0, modulo=None),))]

cyclopts.types.URL

A str URL string with some simple validation.

Help Formatting

Cyclopts provides a flexible help formatting system for customizing the help-page's appearance.

class cyclopts.help.protocols.HelpFormatter(*args, **kwargs)

Protocol for help formatter functions.

It's the Formatter's job to transform a HelpPanel into rendered text on the display.

Implementations may optionally provide the following methods for custom rendering of "usage" and "description". If these methods are not provided, default rendering will be used.

def render_usage(self, console: Console, options: ConsoleOptions, usage: Any) -> None:
    """Render the usage line."""
    ...

def render_description(self, console: Console, options: ConsoleOptions, description: Any) -> None:
    """Render the description."""
    ...
__call__(console: Console, options: ConsoleOptions, panel: HelpPanel) None

Format and render a single help panel.

Parameters:
  • console (Console) -- Console to render to.

  • options (ConsoleOptions) -- Console rendering options.

  • panel (HelpPanel) -- Help panel to render (commands, parameters, etc).

class cyclopts.help.DefaultFormatter(*, panel_spec: PanelSpec | None = None, table_spec: TableSpec | None = None, column_specs: tuple[ColumnSpec, ...] | ColumnSpecBuilder | None = None)

Default help formatter using Rich library with customizable specs.

Parameters:
  • panel_spec (Optional[PanelSpec]) -- Panel specification for the outer box/panel styling.

  • table_spec (Optional[TableSpec]) -- Table specification for table styling (borders, padding, etc).

  • column_specs (Optional[Union[tuple[ColumnSpec, ...], ColumnSpecBuilder]]) -- Column specifications or builder function for table columns.

Notes

The relationship between these specs can be visualized as:

╭─ Commands ───────────────────────────────────────────────────────╮  ← panel_spec
│ serve     Start the development server                           │     (border, title)
│ --help    Display this message and exit.                         │
╰──────────────────────────────────────────────────────────────────╯
 ↑         ↑
 col[0]    col[1]
 (name)    (description)

╭─ Parameters ─────────────────────────────────────────────────────╮  ← panel_spec
│ *  PORT --port        Server port number [required]              │
│    VERBOSE --verbose  Enable verbose output [default: False]     │
╰──────────────────────────────────────────────────────────────────╯
 ↑  ↑                  ↑
 │  col[1]             col[2]
 │  (name/flags)       (description)
 │
 col[0]
 (required marker)

Where:

  • panel_spec controls the outer panel appearance (border, title, etc.)

  • table_spec controls the inner table styling (no visible borders by default)

  • column_specs defines individual columns (width, style, alignment, etc.)

panel_spec: PanelSpec | None

Panel specification for the outer box/panel styling (border, title, padding, etc).

table_spec: TableSpec | None

Table specification for table styling (borders, padding, column separation, etc).

column_specs: tuple[ColumnSpec, ...] | ColumnSpecBuilder | None

Column specifications or builder function for table columns (width, style, alignment, etc).

classmethod with_newline_metadata(**kwargs)

Create formatter with metadata on separate lines.

Returns a DefaultFormatter configured to display parameter metadata (choices, env vars, defaults) on separate indented lines rather than inline with descriptions.

Parameters:

**kwargs -- Additional keyword arguments to pass to DefaultFormatter constructor.

Returns:

Configured formatter instance with newline metadata display.

Return type:

DefaultFormatter

Examples

>>> from cyclopts import App
>>> from cyclopts.help import DefaultFormatter
>>> app = App(help_formatter=DefaultFormatter.with_newline_metadata())
__call__(console: Console, options: ConsoleOptions, panel: HelpPanel) None

Format and render a single help panel using Rich.

Parameters:
  • console (Console) -- Console to render to.

  • options (ConsoleOptions) -- Console rendering options.

  • panel (HelpPanel) -- Help panel to render.

render_usage(console: Console, options: ConsoleOptions, usage: Any) None

Render the usage line.

Parameters:
  • console (Console) -- Console to render to.

  • options (ConsoleOptions) -- Console rendering options.

  • usage (Any) -- The usage line (Text or str).

render_description(console: Console, options: ConsoleOptions, description: Any) None

Render the description.

Parameters:
  • console (Console) -- Console to render to.

  • options (ConsoleOptions) -- Console rendering options.

  • description (Any) -- The description (can be various Rich renderables).

class cyclopts.help.PlainFormatter(indent_width: int = 2, max_width: int | None = None)

Plain text formatter for improved accessibility.

Parameters:
  • indent_width (int) -- Number of spaces to indent entries (default: 2).

  • max_width (Optional[int]) -- Maximum line width for wrapping text.

__call__(console: Console, options: ConsoleOptions, panel: HelpPanel) None

Format and render a single help panel as plain text.

Parameters:
  • console (Console) -- Console to render to.

  • options (ConsoleOptions) -- Console rendering options.

  • panel (HelpPanel) -- Help panel to render.

render_usage(console: Console, options: ConsoleOptions, usage: Any) None

Render the usage line.

Parameters:
  • console (Console) -- Console to render to.

  • options (ConsoleOptions) -- Console rendering options.

  • usage (Any) -- The usage line (Text or str).

render_description(console: Console, options: ConsoleOptions, description: Any) None

Render the description.

Parameters:
  • console (Console) -- Console to render to.

  • options (ConsoleOptions) -- Console rendering options.

  • description (Any) -- The description (can be various Rich renderables).

class cyclopts.help.protocols.ColumnSpecBuilder(*args, **kwargs)

Protocol for ColumnSpecBuilders.

__call__(console: Console, options: ConsoleOptions, entries: list[HelpEntry]) tuple[ColumnSpec, ...]

Build column specifications based on console settings and entries.

Parameters:
  • console (Console) -- The Rich console instance.

  • options (ConsoleOptions) -- Console rendering options.

  • entries (list[HelpEntry]) -- List of help entries to be displayed.

Returns:

Tuple of column specifications for table rendering.

Return type:

tuple[ColumnSpec, ...]

class cyclopts.help.PanelSpec(title: RenderableType | None = None, subtitle: RenderableType | None = None, title_align: Literal['left', 'center', 'right'] = 'left', subtitle_align: Literal['left', 'center', 'right'] = 'center', style: StyleType | None = 'none', border_style: StyleType | None = 'none', box: Box | None = None, padding: PaddingDimensions = (0, 1), expand: bool = True, width: int | None = None, height: int | None = None, safe_box: bool | None = None, highlight: bool = False)

Specification for panel (outer box) styling.

Used by DefaultFormatter to control the appearance of the outer panel that wraps help sections. This spec defines the panel's border, title, subtitle, and overall styling.

See also

DefaultFormatter

The formatter that uses these specs.

TableSpec

Specification for the inner table.

ColumnSpec

Specification for individual columns.

title: RenderableType | None

Title text displayed at the top of the panel.

Corresponds to the title parameter of Panel.

subtitle: RenderableType | None

Subtitle text displayed at the bottom of the panel.

Corresponds to the subtitle parameter of Panel.

title_align: Literal['left', 'center', 'right']

Alignment of the title text within the panel.

Corresponds to the title_align parameter of Panel.

subtitle_align: Literal['left', 'center', 'right']

Alignment of the subtitle text within the panel.

Corresponds to the subtitle_align parameter of Panel.

style: StyleType | None

Style applied to the panel background.

Corresponds to the style parameter of Panel.

border_style: StyleType | None

Style applied to the panel border.

Corresponds to the border_style parameter of Panel.

box: Box | None

Box drawing style for the panel border.

Corresponds to the box parameter of Panel. See rich.box for available styles. Defaults to rich.box.ROUNDED.

padding: PaddingDimensions

Padding inside the panel (top/bottom, left/right) or (top, right, bottom, left).

Corresponds to the padding parameter of Panel.

expand: bool

Whether the panel should expand to fill available width.

Corresponds to the expand parameter of Panel.

width: int | None

Fixed width for the panel in characters.

Corresponds to the width parameter of Panel.

height: int | None

Fixed height for the panel in lines.

Corresponds to the height parameter of Panel.

safe_box: bool | None

Whether to use ASCII-safe box characters for compatibility.

Corresponds to the safe_box parameter of Panel.

highlight: bool

Enable automatic highlighting of panel contents.

Corresponds to the highlight parameter of Panel.

build(renderable: RenderableType, **overrides) Panel

Create a Panel around renderable. Use kwargs to override spec per render.

copy(**kwargs)
class cyclopts.help.TableSpec(title: str | None = None, caption: str | None = None, style: StyleType | None = None, border_style: StyleType | None = None, header_style: StyleType | None = None, footer_style: StyleType | None = None, box: Box | None = None, show_header: bool = False, show_footer: bool = False, show_lines: bool = False, show_edge: bool = True, expand: bool = False, pad_edge: bool = False, padding: PaddingDimensions = (0, 2, 0, 0), collapse_padding: bool = False, width: int | None = None, min_width: int | None = None, safe_box: bool | None = None)

Specification for table layout and styling.

Used by DefaultFormatter to control the appearance of tables that display commands and parameters. This spec defines table-wide properties like borders, headers, and padding.

See also

DefaultFormatter

The formatter that uses these specs.

ColumnSpec

Specification for individual columns.

PanelSpec

Specification for the outer panel.

title: str | None

Title text displayed above the table.

Corresponds to the title parameter of Table.

caption: str | None

Caption text displayed below the table.

Corresponds to the caption parameter of Table.

style: StyleType | None

Default style applied to the entire table.

Corresponds to the style parameter of Table.

border_style: StyleType | None

Style applied to table borders.

Corresponds to the border_style parameter of Table.

header_style: StyleType | None

Default style for all table headers (can be overridden per column).

Corresponds to the header_style parameter of Table.

footer_style: StyleType | None

Default style for all table footers (can be overridden per column).

Corresponds to the footer_style parameter of Table.

box: Box | None

Box drawing style for the table borders.

Corresponds to the box parameter of Table. See rich.box for available styles.

show_header: bool

Whether to display column headers.

Corresponds to the show_header parameter of Table.

Whether to display column footers.

Corresponds to the show_footer parameter of Table.

show_lines: bool

Whether to show horizontal lines between rows.

Corresponds to the show_lines parameter of Table.

show_edge: bool

Whether to draw a box around the outside of the table.

Corresponds to the show_edge parameter of Table.

expand: bool

Whether the table should expand to fill available width.

Corresponds to the expand parameter of Table.

pad_edge: bool

Whether to add padding to the table edges.

Corresponds to the pad_edge parameter of Table.

padding: PaddingDimensions

Padding around cell content (top, right, bottom, left).

Corresponds to the padding parameter of Table.

collapse_padding: bool

Whether to collapse padding when adjacent cells are empty.

Corresponds to the collapse_padding parameter of Table.

width: int | None

Fixed width for the table in characters.

Corresponds to the width parameter of Table.

min_width: int | None

Minimum width for the table in characters.

Corresponds to the min_width parameter of Table.

safe_box: bool | None

Whether to use ASCII-safe box characters for compatibility.

Corresponds to the safe_box parameter of Table.

build(columns: tuple[ColumnSpec, ...], entries: Iterable[HelpEntry], **overrides) Table

Construct and populate a rich.Table.

Parameters:
  • columns (tuple[ColumnSpec, ...]) -- Column specifications defining the table structure.

  • entries (Iterable[HelpEntry]) -- Table entries to populate the table with.

  • **overrides -- Per-render overrides for table settings.

Returns:

A populated Rich Table.

Return type:

Table

copy(**kwargs)
class cyclopts.help.ColumnSpec(renderer: str | Renderer, header: str = '', footer: str = '', header_style: StyleType | None = None, footer_style: StyleType | None = None, style: StyleType | None = None, justify: Literal['default', 'left', 'center', 'right', 'full'] = 'left', vertical: Literal['top', 'middle', 'bottom'] = 'top', overflow: Literal['fold', 'crop', 'ellipsis', 'ignore'] = 'ellipsis', width: int | None = None, min_width: int | None = None, max_width: int | None = None, ratio: int | None = None, no_wrap: bool = False, highlight: bool | None = None)

Specification for a single column in a help table.

Used by DefaultFormatter to define how individual columns are rendered in help tables. Each column can have its own renderer, styling, and layout properties.

See also

DefaultFormatter

The formatter that uses these specs.

TableSpec

Specification for the entire table.

PanelSpec

Specification for the outer panel.

renderer: str | Renderer

Specifies how to extract and render cell content from a HelpEntry.

Can be either:

  • A string: The attribute name to retrieve from HelpEntry (e.g., 'names', 'description', 'required', 'type'). The string is displayed as-is.

  • A callable: A function matching the Renderer protocol. The function receives a HelpEntry and should return a RenderableType (str, Text, or other Rich renderable).

Examples:

# String renderer - get attribute directly
ColumnSpec(renderer="description")

# Callable renderer - custom formatting
def format_names(entry: HelpEntry) -> str:
    return ", ".join(entry.names) if entry.names else ""
ColumnSpec(renderer=format_names)
header: str

Column header text displayed at the top of the column.

Example:

header="Options" renders:
┌─────────┬─────────────┐
│ Options │ Description │
├─────────┼─────────────┤
│ --help  │ Show help   │
└─────────┴─────────────┘
footer: str

Column footer text displayed at the bottom of the column.

Example:

footer="Required" renders:
┌──────────┬────────────┐
│ --help   │ Show help  │
├──────────┼────────────┤
│ Required │            │
└──────────┴────────────┘
header_style: StyleType | None

Style applied to the column header text.

Corresponds to the header_style parameter of rich.table.Table.add_column().

footer_style: StyleType | None

Style applied to the column footer text.

Corresponds to the footer_style parameter of rich.table.Table.add_column().

style: StyleType | None

Default style applied to all cells in this column.

Corresponds to the style parameter of rich.table.Table.add_column().

justify: Literal['default', 'left', 'center', 'right', 'full']

Text justification within the column.

Corresponds to the justify parameter of rich.table.Table.add_column().

vertical: Literal['top', 'middle', 'bottom']

Vertical alignment of text within cells.

Corresponds to the vertical parameter of rich.table.Table.add_column().

overflow: Literal['fold', 'crop', 'ellipsis', 'ignore']

How to handle text that exceeds column width.

Corresponds to the overflow parameter of rich.table.Table.add_column().

width: int | None

Fixed width for the column in characters.

Corresponds to the width parameter of rich.table.Table.add_column().

min_width: int | None

Minimum width for the column in characters.

Corresponds to the min_width parameter of rich.table.Table.add_column().

max_width: int | None

Maximum width for the column in characters.

Corresponds to the max_width parameter of rich.table.Table.add_column().

ratio: int | None

Relative width ratio compared to other columns.

Corresponds to the ratio parameter of rich.table.Table.add_column().

no_wrap: bool

Prevent text wrapping in the column.

Corresponds to the no_wrap parameter of rich.table.Table.add_column().

highlight: bool | None

Enable automatic highlighting of text in the column.

Corresponds to the highlight parameter of rich.table.Table.add_column().

copy(**kwargs)
class cyclopts.help.NameRenderer(max_width: int | None = None)

Renderer for parameter/command names with optional text wrapping.

Parameters:

max_width (int | None) -- Maximum width for wrapping. If None, no wrapping is applied.

Initialize the renderer with formatting options.

Parameters:

max_width (int | None) -- Maximum width for wrapping. If None, no wrapping is applied.

__call__(entry: HelpEntry) RenderableType

Render the names column with optional text wrapping.

Parameters:

entry (HelpEntry) -- The table entry to render.

Returns:

Combined names and shorts, optionally wrapped. Order: positive_names, positive_shorts, negative_names, negative_shorts

Return type:

RenderableType

class cyclopts.help.DescriptionRenderer(newline_metadata: bool = False)

Renderer for descriptions with configurable metadata formatting.

Parameters:

newline_metadata (bool) -- If True, display metadata (choices, env vars, defaults) on separate lines. If False (default), display metadata inline with the description.

Initialize the renderer with formatting options.

Parameters:

newline_metadata (bool) -- If True, display metadata on separate lines instead of inline.

__call__(entry: HelpEntry) RenderableType

Render parameter description with metadata annotations.

Enriches the base description with choices, environment variables, default values, and required status.

Parameters:

entry (HelpEntry) -- The table entry to render.

Returns:

Description with appended metadata.

Return type:

RenderableType

class cyclopts.help.AsteriskRenderer

Renderer for required parameter asterisk indicator.

A simple renderer that displays an asterisk (*) for required parameters.

__call__(entry: HelpEntry) RenderableType

Render an asterisk for required parameters.

Parameters:

entry (HelpEntry) -- The table entry to render.

Returns:

An asterisk if the entry is required, empty string otherwise.

Return type:

RenderableType

class cyclopts.help.HelpPanel(format: Literal['command', 'parameter'], title: RenderableType, description: Any | None = None, entries: list[HelpEntry] = NOTHING)

Data container for help panel information.

format: Literal['command', 'parameter']

Panel format type.

title: RenderableType

The title text displayed at the top of the help panel.

description: Any

Optional description text displayed below the title.

Typically a str or a RenderableType

entries: list[HelpEntry]

List of help entries to display (in order) in the panel.

copy(**kwargs)
class cyclopts.help.HelpEntry(*, positive_names: tuple[str, ...] = (), positive_shorts: tuple[str, ...] = (), negative_names: tuple[str, ...] = (), negative_shorts: tuple[str, ...] = (), description: Any = None, required: bool = False, sort_key: Any = None, type: Any | None = None, choices: tuple[str, ...] | None = None, env_var: tuple[str, ...] | None = None, default: str | None = None)

Container for help table entry data.

positive_names: tuple[str, ...]

Positive long option names (e.g., "--verbose", "--dry-run").

positive_shorts: tuple[str, ...]

Positive short option names (e.g., "-v", "-n").

negative_names: tuple[str, ...]

Negative long option names (e.g., "--no-verbose", "--no-dry-run").

negative_shorts: tuple[str, ...]

Negative short option names (e.g., "-N"). Rarely used.

property names: tuple[str, ...]

All long option names (positive + negative). For backward compatibility.

property shorts: tuple[str, ...]

All short option names (positive + negative). For backward compatibility.

property all_options: tuple[str, ...]

positive longs, positive shorts, negative longs, negative shorts.

Type:

All options in display order

description: Any

Help text description for this entry.

Typically a str or a RenderableType

required: bool

Whether this parameter/command is required.

sort_key: Any

Custom sorting key for ordering entries.

type: Any | None

Type annotation of the parameter.

choices: tuple[str, ...] | None

Available choices for this parameter.

env_var: tuple[str, ...] | None

Environment variable names that can set this parameter.

default: str | None

Default value for this parameter to display. None means no default to show.

copy(**kwargs)

Config

Cyclopts has builtin configuration classes to be used with App.config for loading user-defined defaults in many common scenarios. All Cyclopts builtins index into the configuration file with the following rules:

  1. Apply root_keys (if provided) to enter the project's configuration namespace.

  2. Apply the command name(s) to enter the current command's configuration namespace.

  3. Apply each key/value pair if CLI arguments have not been provided for that parameter.

class cyclopts.config.Toml(path, *, root_keys: Iterable[str] = (), allow_unknown: bool = False, use_commands_as_keys: bool = True, source: str | None = None, must_exist: bool = False, search_parents: bool = False)

Automatically read configuration from Toml file.

path: str | pathlib.Path

Path to TOML configuration file.

source: str | None = None

Identifier for the configuration source, used in error messages. If not provided, defaults to the absolute path of the configuration file.

root_keys: Iterable[str] = None

The key or sequence of keys that lead to the root configuration structure for this app. For example, if referencing a pyproject.toml, it is common to store all of your projects configuration under:

[tool.myproject]

So, your Cyclopts App should be configured as:

app = cyclopts.App(config=cyclopts.config.Toml("pyproject.toml", root_keys=("tool", "myproject")))
must_exist: bool = False

The configuration file MUST exist. Raises FileNotFoundError if it does not exist.

search_parents: bool = False

If path doesn't exist, iteratively search parenting directories for a same-named configuration file. Raises FileNotFoundError if no configuration file is found.

allow_unknown: bool = False

Allow for unknown keys. Otherwise, if an unknown key is provided, raises UnknownOptionError.

use_commands_as_keys: bool = True

Use the sequence of commands as keys into the configuration.

For example, the following CLI invocation:

$ python my-script.py my-command

Would search into ["my-command"] for values.

class cyclopts.config.Yaml(path, *, root_keys: Iterable[str] = (), allow_unknown: bool = False, use_commands_as_keys: bool = True, source: str | None = None, must_exist: bool = False, search_parents: bool = False)

Automatically read configuration from YAML file.

path: str | pathlib.Path

Path to YAML configuration file.

source: str | None = None

Identifier for the configuration source, used in error messages. If not provided, defaults to the absolute path of the configuration file.

root_keys: Iterable[str] = None

The key or sequence of keys that lead to the root configuration structure for this app. For example, if referencing a common config.yaml that is shared with other applications, it is common to store your projects configuration under a key like myproject:.

Your Cyclopts App would be configured as:

app = cyclopts.App(config=cyclopts.config.Yaml("config.yaml", root_keys="myproject"))
must_exist: bool = False

The configuration file MUST exist. Raises FileNotFoundError if it does not exist.

search_parents: bool = False

If path doesn't exist, iteratively search parenting directories for a same-named configuration file. Raises FileNotFoundError if no configuration file is found.

allow_unknown: bool = False

Allow for unknown keys. Otherwise, if an unknown key is provided, raises UnknownOptionError.

use_commands_as_keys: bool = True

Use the sequence of commands as keys into the configuration.

For example, the following CLI invocation:

$ python my-script.py my-command

Would search into ["my-command"] for values.

class cyclopts.config.Json(path, *, root_keys: Iterable[str] = (), allow_unknown: bool = False, use_commands_as_keys: bool = True, source: str | None = None, must_exist: bool = False, search_parents: bool = False)

Automatically read configuration from Json file.

path: str | pathlib.Path

Path to JSON configuration file.

source: str | None = None

Identifier for the configuration source, used in error messages. If not provided, defaults to the absolute path of the configuration file. Can be customized to provide more descriptive error context.

Example:

app = cyclopts.App(config=cyclopts.config.Json("config.json", source="production-config"))
root_keys: Iterable[str] = None

The key or sequence of keys that lead to the root configuration structure for this app. For example, if referencing a common config.json that is shared with other applications, it is common to store your projects configuration under a key like "myproject":.

Your Cyclopts App would be configured as:

app = cyclopts.App(config=cyclopts.config.Json("config.json", root_keys="myproject"))
must_exist: bool = False

The configuration file MUST exist. Raises FileNotFoundError if it does not exist.

search_parents: bool = False

If path doesn't exist, iteratively search parenting directories for a same-named configuration file. Raises FileNotFoundError if no configuration file is found.

allow_unknown: bool = False

Allow for unknown keys. Otherwise, if an unknown key is provided, raises UnknownOptionError.

use_commands_as_keys: bool = True

Use the sequence of commands as keys into the configuration.

For example, the following CLI invocation:

$ python my-script.py my-command

Would search into ["my-command"] for values.

class cyclopts.config.Dict(data: dict[str, Any], *, root_keys: Iterable[str] = (), allow_unknown: bool = False, use_commands_as_keys: bool = True, source: str | None = None)

Configuration source from an in-memory dictionary.

Useful for programmatically generated configurations.

Use an in-memory Python dictionary as configuration source.

data: dict[str, Any]

The configuration dictionary.

source: str = "dict"

Identifier for the configuration source, used in error messages.

root_keys: Iterable[str] = ()

The key or sequence of keys that lead to the root configuration structure for this app.

allow_unknown: bool = False

Allow for unknown keys. Otherwise, if an unknown key is provided, raises UnknownOptionError.

use_commands_as_keys: bool = True

Use the sequence of commands as keys into the configuration.

class cyclopts.config.Env(prefix: str = '', *, source: str = 'env', command: bool = True, show: bool = True)

Automatically derive environment variable names to read configurations from.

For example, consider the following app:

import cyclopts

app = cyclopts.App(config=cyclopts.config.Env("MY_SCRIPT_"))

@app.command
def my_command(foo, bar):
    print(f"{foo=} {bar=}")

app()

If values for foo and bar are not supplied by the command line, the app will check the environment variables MY_SCRIPT_MY_COMMAND_FOO and MY_SCRIPT_MY_COMMAND_BAR, respectively:

$ python my_script.py my-command 1 2
foo=1 bar=2

$ export MY_SCRIPT_MY_COMMAND_FOO=100
$ python my_script.py my-command --bar=2
foo=100 bar=2
$ python my_script.py my-command 1 2
foo=1 bar=2
prefix: str = ""

String to prepend to all autogenerated environment variable names. Typically ends in _, and is something like MY_APP_.

source: str = "env"

Identifier for the configuration source, used in error messages and token tracking. Defaults to "env".

command: bool = True

If True, add the command's name (uppercase) after prefix.

show: bool = True

If True, then show the environment variables on the help-page.

Exceptions

exception cyclopts.CycloptsError

Bases: Exception

Root exception for runtime errors.

As CycloptsErrors bubble up the Cyclopts call-stack, more information is added to it.

msg: str | None

If set, override automatic message generation.

verbose: bool

More verbose error messages; aimed towards developers debugging their Cyclopts app. Defaults to False.

root_input_tokens: list[str] | None

The parsed CLI tokens that were initially fed into the App.

unused_tokens: list[str] | None

Leftover tokens after parsing is complete.

target: Callable | None

The python function associated with the command being parsed.

argument: Argument | None

Argument that was matched.

command_chain: Sequence[str] | None

List of command that lead to target.

app: App | None

The Cyclopts application itself.

console: Console | None

Console to display runtime errors.

exception cyclopts.ValidationError

Bases: CycloptsError

Validator function raised an exception.

exception_message: str

Parenting Assertion/Value/Type Error message.

group: Group | None

If a group validator caused the exception.

value: Any

Converted value that failed validation.

exception cyclopts.UnknownOptionError

Bases: CycloptsError

Unknown/unregistered option provided by the cli.

A nearest-neighbor parameter suggestion may be printed.

token: Token

Token without a matching parameter.

argument_collection: ArgumentCollection

Argument collection of plausible options.

exception cyclopts.CoercionError

Bases: CycloptsError

There was an error performing automatic type coercion.

token: Token | None

Input token that couldn't be coerced.

target_type: type | None

Intended type to coerce into.

exception cyclopts.UnknownCommandError

Bases: CycloptsError

CLI token combination did not yield a valid command.

msg: str | None

If set, override automatic message generation.

verbose: bool

More verbose error messages; aimed towards developers debugging their Cyclopts app. Defaults to False.

root_input_tokens: list[str] | None

The parsed CLI tokens that were initially fed into the App.

unused_tokens: list[str] | None

Leftover tokens after parsing is complete.

target: Callable | None

The python function associated with the command being parsed.

argument: 'Argument' | None

Argument that was matched.

command_chain: Sequence[str] | None

List of command that lead to target.

app: 'App' | None

The Cyclopts application itself.

console: 'Console' | None

Console to display runtime errors.

exception cyclopts.UnusedCliTokensError

Bases: CycloptsError

Not all CLI tokens were used as expected.

exception cyclopts.MissingArgumentError

Bases: CycloptsError

A required argument was not provided.

tokens_so_far: list[str]

If the matched parameter requires multiple tokens, these are the ones we have parsed so far.

keyword: str | None

The keyword that was used when the error was raised (e.g., '-o' instead of '--option').

exception cyclopts.ConsumeMultipleError

Bases: MissingArgumentError

The number of values provided doesn't meet consume_multiple constraints.

min_required: int
max_allowed: int | None
actual_count: int
exception cyclopts.RequiresEqualsError

Bases: CycloptsError

A long option requires = to assign a value (e.g., --option=value).

keyword: str | None

The keyword that was used (e.g., '--name').

exception cyclopts.RepeatArgumentError

Bases: CycloptsError

The same parameter has erroneously been specified multiple times.

token: Token

The repeated token.

exception cyclopts.MixedArgumentError

Bases: CycloptsError

Cannot supply keywords and non-keywords to the same argument.

exception cyclopts.CommandCollisionError

Bases: Exception

A command with the same name has already been registered to the app.

exception cyclopts.CombinedShortOptionError

Bases: CycloptsError

Cannot combine short, token-consuming options with short flags.

exception cyclopts.EditorError

Bases: Exception

Root editor-related error.

Root exception raised by all exceptions in edit().

exception cyclopts.EditorNotFoundError

Bases: EditorError

Could not find a valid text editor for :func`.edit`.

exception cyclopts.EditorDidNotSaveError

Bases: EditorError

User did not save upon exiting edit().

exception cyclopts.EditorDidNotChangeError

Bases: EditorError

User did not edit file contents in edit().