API
- class cyclopts.App(name: str | Iterable[str] | None = None, help: str | None = None, usage: str | None = None, *, alias: str | Iterable[str] | None = None, synonym: 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)[source]
Cyclopts Application.
- name: str | Iterable[str] | None = None
Name of application, or subcommand if registering to another application. Name resolution order:
User specified
nameparameter.If a
defaultfunction has been registered, the name of that function.If the module name is
__main__.py, the name of the encompassing package.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 withcommand()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
namewith additional names. Unlikename, 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.
- synonym: str | Iterable[str] | None = None
Alternate names that trigger a "Did you mean..." suggestion when typed, but do not register the command under those names.
Unlike
alias, synonyms are not runnable and are hidden from--help. They exist to guide users who type a semantically equivalent but orthographically dissimilar token that Cyclopts' fuzzy matcher would otherwise miss (e.g.,removewhen the command isuninstall).from cyclopts import App app = App() @app.command(synonym=["remove", "rm"]) def uninstall(name: str): print(f"uninstalling {name}") app()
$ my-script uninstall mypackage uninstalling mypackage $ my-script remove mypackage Unknown command "remove". Did you mean "uninstall"? Available commands: uninstall.
See Synonyms for details.
- 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 parentinghelp_format. If nohelp_formatis defined, falls back to"markdown".
- help_formatter: None | Literal['default', 'plain'] | HelpFormatter = None
Help formatter to use for rendering help panels.
If
None(default), inherits from parentApp, eventually defaulting toDefaultFormatter.If
"default", usesDefaultFormatter.If
"plain", usesPlainFormatterfor no-frills plain text output.If a callable (see
HelpFormatterprotocol), uses the provided formatter.
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 parentingApp.The prologue supports the same formatting as
helpbased onhelp_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 parentingApp.The epilogue supports the same formatting as
helpbased onhelp_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 toFalse.
- print_error: bool | None = None
Print a rich-formatted error on error. If not set, attempts to inherit from parenting
App, eventually defaulting toTrue.
- 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 parentingApp, eventually defaulting toTrue.
- verbose: bool | None = None
Populate exception strings with more information intended for developers. If not set, attempts to inherit from parenting
App, eventually defaulting toFalse.
- error_formatter: Callable[[CycloptsError], Any] | None = None
A callable that formats
CycloptsErrorexceptions 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 parentingApp, eventually defaulting toCycloptsPanel().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 parentingversion_format. If noversion_formatis defined, falls back to resolvedhelp_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.
If
sort_keyis a generator, it will be consumed immediately withnext()to get the actual value.If
sort_key, or any of it's contents, areCallable, then invoke itsort_key(app)and apply the returned value to (3) ifNone, (4) otherwise.For all commands with
sort_key==None(default value), sort them alphabetically. These sorted commands will be displayed aftersort_key != Nonelist (see 4).For all commands with
sort_key!=None, sort them by(sort_key, app.name). It is the user's responsibility thatsort_keys 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_flagsis parsed. Defaults to the version of the package instantiatingApp. If aCallable, 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
Consoleto use when displaying runtime messages. Cyclopts console resolution is as follows:Any explicitly passed in console to methods like
App.__call__(),App.parse_args(), etc.The relevant subcommand's
App.consoleattribute, if notNone.The parenting
App.console(and so on), if notNone.
- error_console: Console = None
Default
Consoleto use when displaying error messages. Cyclopts error_console resolution is as follows:Any explicitly passed in error_console to methods like
App.__call__(),App.parse_args(), etc.The relevant subcommand's
App.error_consoleattribute, if notNone.The parenting
App.error_console(and so on), if notNone.If all values are
None, then a defaultConsolewithstderr=Trueis 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
Parameterconfiguration. Unspecified values of command-annotatedParameterwill inherit these values. See Default Parameter for more details.
- group: None | str | Group | Iterable[str | Group] = None
The group(s) that
default_commandbelongs to.
- group_arguments: Group = Group("Arguments")
The default
Groupthat positional-only parameters are assigned to.
- group_parameters: Group = Group("Parameters")
The default
Groupthat 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."
- 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
--. IfNone(default value), usesdefault_name_transform(). Subapps inherit from the first non-Noneparentname_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
Falseto letKeyboardInterruptpropagate 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__()andApp.run_async()handle command return values. By default ("print_non_int_sys_exit"), the app will callsys.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(resolve_returncode(result)) else: sys.exit(resolve_returncode(result))
"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(resolve_returncode(result))
"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 resolve_returncode(result) else: return resolve_returncode(result)
"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 resolve_returncode(result) elif isinstance(result, bool): return 0 if result else 1 # i.e. True is success elif isinstance(result, int): return result else: return resolve_returncode(result)
"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 resolve_returncode(result)
"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 resolve_returncode(result)
"print_non_none_return_zero"
Prints all non-None values (including ints), always returns 0.
if result is not None: print(result) return resolve_returncode(result)
"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 resolve_returncode(result)
"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 resolve_returncode(result)
"print_return_zero"
Always prints the result (even None), then always returns 0.
print(result) return resolve_returncode(result)
"sys_exit_zero"
Always calls
sys.exit(0), regardless of the command's return value.sys.exit(resolve_returncode(result))
"print_sys_exit_zero"
Always prints the result (even None), then calls
sys.exit(0).print(result) sys.exit(resolve_returncode(result))
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
ValueErrorat 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[source]
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[source]
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][source]
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: str | Iterable[str] | None = None, *, include_parent_meta=True) tuple[tuple[str, ...], tuple[App, ...], list[str]][source]
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[source]
- 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
Appcan take.
- default(obj: T, *, validator: Callable[[...], Any] | None = None) T[source]
- 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[source]
Assemble the argument collection for this app.
- Parameters:
- Returns:
All arguments for this app.
- Return type:
- 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]][source]
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.Annotatedwill 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]][source]
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 fromApp.print_error, eventually defaulting toTrue.exit_on_error (bool | None) -- If there is an error parsing the CLI tokens invoke
sys.exit(1). Otherwise, continue to raise the exception. IfNone, inherits fromApp.exit_on_error, eventually defaulting toTrue.help_on_error (bool | None) -- Prints the help-page before printing an error. If
None, inherits fromApp.help_on_error, eventually defaulting toFalse.verbose (bool | None) -- Populate exception strings with more information intended for developers. If
None, inherits fromApp.verbose, eventually defaulting toFalse.end_of_options_delimiter (str | None) -- All tokens after this delimiter will be force-interpreted as positional arguments. If
None, inherits fromApp.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
argsandkwargsto be used when callingcommand.ignored (dict[str, Any]) -- A mapping of python-variable-name to type-hint of any parameter with annotation
parse=False.Annotatedwill 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[source]
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 fromApp.print_error, eventually defaulting toTrue.exit_on_error (bool | None) -- If there is an error parsing the CLI tokens invoke
sys.exit(1). Otherwise, continue to raise the exception. IfNone, inherits fromApp.exit_on_error, eventually defaulting toTrue.help_on_error (bool | None) -- Prints the help-page before printing an error. If
None, inherits fromApp.help_on_error, eventually defaulting toFalse.verbose (bool | None) -- Populate exception strings with more information intended for developers. If
None, inherits fromApp.verbose, eventually defaulting toFalse.end_of_options_delimiter (str | None) -- All tokens after this delimiter will be force-interpreted as positional arguments. If
None, inherits fromApp.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 fromApp.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 fromApp.result_action, eventually defaulting to "print_non_int_return_int_as_exit_code". SeeApp.result_actionfor 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[source]
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 fromApp.print_error, eventually defaulting toTrue.exit_on_error (bool | None) -- If there is an error parsing the CLI tokens invoke
sys.exit(1). Otherwise, continue to raise the exception. IfNone, inherits fromApp.exit_on_error, eventually defaulting toTrue.help_on_error (bool | None) -- Prints the help-page before printing an error. If
None, inherits fromApp.help_on_error, eventually defaulting toFalse.verbose (bool | None) -- Populate exception strings with more information intended for developers. If
None, inherits fromApp.verbose, eventually defaulting toFalse.end_of_options_delimiter (str | None) -- All tokens after this delimiter will be force-interpreted as positional arguments. If
None, inherits fromApp.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 fromApp.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 fromApp.result_action, eventually defaulting to "print_non_int_return_int_as_exit_code". SeeApp.result_actionfor 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[source]
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[source]
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 asuv run cli. Only theUsage:lines change; document titles, section headings, and table-of-contents anchors continue to useapp.name[0]. Default is None (useapp.name[0]).
- Returns:
The generated documentation.
- Return type:
- 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[source]
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:
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[source]
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:
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[source]
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_completionThe 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[source]
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
dispatcherfunction 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, usesApp.console.exit_on_error (bool) -- Whether to call
sys.exiton parsing errors. Defaults toFalse.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. IfNone, inherits fromApp.result_action.**kwargs -- Get passed along to
parse_args().
- update(app: App)[source]
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] | str | ~collections.abc.Iterable[~collections.abc.Callable[[...], ~typing.Any] | str] | 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)[source]
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_transformto 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, andtokensis 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
dictofTokenif 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 withaccepts_keys.Decorating Converters: Converter functions can be decorated with
Parameterto 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 | str | Iterable[Callable | str] = 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.
Classmethod Support: Validators can be classmethods. Use string references for class decoration or direct references in annotations.
@Parameter(name="*", validator="validate") @dataclass class TextStyle: color: str bold: bool = False italic: bool = False @classmethod def validate(cls, value): if value.bold and value.italic: raise ValueError("Cannot use both --bold and --italic together.")
- 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:Parenting
App.group_argumentsif the parameter isPOSITIONAL_ONLY. By default, this isGroup("Arguments").Parenting
App.group_parametersotherwise. By default, this isGroup("Parameters").
See Groups for examples.
- negative: None | str | Iterable[str] = None
Name(s) for empty iterables or false boolean flags.
For booleans, defaults to
no-{name}(seenegative_bool).For iterables, defaults to
empty-{name}(seenegative_iterable).
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_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 valueis rejected with aRequiresEqualsError.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(raisesValueError). 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 theignoreddict fromApp.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 tore.Patternfor performance.re.Pattern- A pre-compiled regex pattern; same behavior as string patterns.
Regex patterns are primarily intended for use with
App.default_parameterto 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.
Falseif the parameter has a default,Trueotherwise.
- show: bool | None = None
Show this parameter on the help screen. Defaults to whether the parameter is
parsed(usuallyTrue).
- 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 toTrue, but will not display the default if it isNone.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_varset, 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_varvalue. The function must have signature:def env_var_split(type_: type, val: str) -> list[str]: ...
where
type_is the associated parameter type-hint, andvalis 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), usescyclopts.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=Falseoption is commonly used withconverterandn_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_multipleis 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— likeTrue, but the integer specifies the minimum number of elements required. For example,consume_multiple=1requires at least one value (preventing empty lists), andconsume_multiple=0is equivalent toTrue.Sequence[int] — a(min, max)pair (e.g. a tuple or list of two ints). All remaining CLI tokens are consumed greedily, and aConsumeMultipleErroris 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 thenegative_iterableprefix (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,
--filesraises aConsumeMultipleErrorif 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 likeTrue, unless the annotated type is union'd withstr. WhenTrue, data will be parsed as json if the following conditions are met:The parameter is specified as a keyword option; e.g.
--movie.The referenced parameter is dataclass-like.
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 likeTrue, unless the annotated type has each element typestr. WhenTrue, data will be parsed as json if the following conditions are met:The referenced parameter is iterable (not including
str).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.,-vvvresults in3).Requirements and behavior:
The parameter must have an
inttype hint (orOptional[int]).Short flags can be concatenated:
-vvvis equivalent to-v -v -v.Long flags can be repeated:
--verbose --verboseresults in2.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 raiseRepeatArgumentError.False: always raiseRepeatArgumentErroron repeated options. Useful withconsume_multipleto allow--foo a b cbut 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 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.,
intconsumes 1 token,tuple[int, int]consumes 2,listconsumes 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
*argsparameters,n_tokensspecifies tokens per element. For example,n_tokens=2with 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[source]
Returns a new Parameter with combined values of all provided
parameters.- Parameters:
*parameters (Parameter | None) -- Parameters who's attributes override
selfattributes. Ordered from least-to-highest attribute priority.
- 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)[source]
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 anameis provided.
- help_formatter: None | Literal['default', 'plain'] | HelpFormatter = None
Help formatter to use for rendering this group's help panel.
If
None(default), inherits from theApp'shelp_formatter.If
"default", usesDefaultFormatter.If
"plain", usesPlainFormatterfor no-frills plain text output.If a callable (see
HelpFormatterprotocol), uses the provided formatter.
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.
If
sort_keyis a generator, it will be consumed immediately withnext()to get the actual value.If
sort_key, or any of it's contents, areCallable, then invoke itsort_key(group)and apply the rules below.The
Appdefault 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. │ ╰───────────────────────────────────────────────────────────────────────╯
For all groups with
sort_key!=None, sort them by(sort_key, group.name). That is, sort them by theirsort_key, and then break ties alphabetically. It is the user's responsibility thatsort_keyare comparable.For all groups with
sort_key==None(default value), sort them alphabetically after (4),App.group_commands,App.group_arguments, andApp.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
Parameterin the parameter-resolution-stack that goes betweenApp.default_parameterand the function signature'sAnnotatedParameter. The providedParameteris not allowed to have agroupvalue.
- 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
ArgumentCollectionwill 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[source]
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 anameis 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>)[source]
Tracks how a user supplied a value to the application.
- keyword: str | None = None
Unadulterated user-supplied keyword like
--fooor--foo.bar.baz;Nonewhen token was pared positionally. Could also be something liketool.project.fooif from non-cli sources.
- source: str = ""
Where the token came from; used for error message purposes. Cyclopts uses the string
clifor cli-parsed tokens.
- 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)[source]
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>)[source]
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
Tokenparsed from various sources. Do not directly mutate; seeappend().
- 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.nameandself.keyscan naively disagree! For example, aself.parameter.name="--foo.bar.baz"could be aliased to "--fizz". The resultingself.keyswould 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
Argumentthat eventually culminate into the python variable represented byfield_info.
- property value
Converted value from last
convert()call.This value may be stale if fields have changed since last
convert()call.UNSETifconvert()has not yet been called with tokens.
- match(term: str | int, *, transform: Callable[[str], str] | None = None, delimiter: str = '.') tuple[tuple[str, ...], Any][source]
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.
UNSETif no implicit value is applicable.
- property children_recursive: ArgumentCollection
- convert(converter: Callable | None = None)[source]
-
- Parameters:
converter (Callable | None) -- Converter function to use. Overrides
self.parameter.converter- Returns:
The converted data. Same as
value.- Return type:
Any
- validate(value)[source]
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)[source]
Converts and validates
tokensintovalue.- 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, ...] = ())[source]
The number of string tokens this argument consumes.
- property negatives
Negative flags from
Parameter.get_negatives().
- env_var_split(value: str, delimiter: str | None = None) list[str][source]
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.parseis a regex pattern, parse if the pattern matches the field name; otherwise don't parse.
- is_flag() bool[source]
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:
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[source]
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:
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)[source]
A list-like container for
Argument.- copy() ArgumentCollection[source]
Returns a shallow copy of the
ArgumentCollection.
- __contains__(item: object, /) bool[source]
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:
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[source]
- get(term: str | int, default: T, *, transform: Callable[[str], str] | None = None, delimiter: str = '.') Argument | T
Get an
Argumentby name or index.This is a convenience wrapper around
match()that returns just theArgumentobject 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 raiseKeyError/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, ordefaultif provided and not found.- Return type:
Argument | None
- Raises:
KeyError -- If
termis a string and not found (whendefaultisUNSET).IndexError -- If
termis an int and is out-of-range (whendefaultisUNSET).
- match(term: str | int, *, transform: Callable[[str], str] | None = None, delimiter: str = '.') tuple[Argument, tuple[str, ...], Any][source]
Matches CLI keyword or index to their
Argument.- Parameters:
One of:
- Raises:
ValueError -- If the provided
termdoesn't match.- Returns:
- 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[source]
Filter the
ArgumentCollection.All non-None filters will be applied.
- Parameters:
group (Group | None) -- The
Groupthe arguments should be in.has_tokens (bool | None) -- Immediately has tokens (not including children).
has_tree_tokens (bool | None) --
Argumentand/or it's children have parsed tokens.kind (inspect._ParameterKind | None) -- The
kindof the argument.parse (bool | None) -- If the argument is intended to be parsed or not.
show (bool | None) -- The
Argumentis intended to be show on the help page.value_set (bool | None) -- The converted value is set.
- class cyclopts.UNSET[source]
Special sentinel value indicating that no data was provided. Do not instantiate.
- cyclopts.default_name_transform(s: str) str[source]
Converts a python identifier into a CLI token.
Performs the following operations (in order):
Convert PascalCase to snake_case.
Convert the string to all lowercase.
Replace
_with-.Strip any leading/trailing
-(also stripping_, due to point 3).
Intended to be used with
App.name_transformandParameter.name_transform.
- cyclopts.env_var_split(type_: Any, val: str, *, delimiter: str | None = None) list[str][source]
Type-dependent environment variable value splitting.
Converts a single string into a list of strings. Splits when:
The
type_is some variant ofIterable[pathlib.Path]objects. If Windows, split on;, otherwise split on:.Otherwise, if the
type_is anIterable, 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.
- 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[source]
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 raisesEditorDidNotChangeError.
- Raises:
EditorError -- Base editor error exception. Explicitly raised if editor subcommand returned a non-zero exit code.
EditorNotFoundError -- A suitable text editor could not be found.
EditorDidNotSaveError -- The user exited the text-editor without saving and
save=True.EditorDidNotChangeError -- The user did not change the file contents and
required=True.
- Returns:
The resulting text that was saved by the text editor.
- Return type:
- cyclopts.run(callable: Callable[[...], Coroutine[None, None, V]], /, *, result_action: Literal['return_value']) V[source]
- 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 callssys.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)
- cyclopts.resolve_returncode(result: Any, default: int = 0) int[source]
Resolve the return code for
result.If
resultdefines__cyclopts_returncode__(a zero-argument callable), its value is used. Otherwisedefaultis returned.Custom
result_actioncallables can use this helper to honor the__cyclopts_returncode__protocol consistently with the built-in actions.
- class cyclopts.CycloptsPanel(message: Any, title: str = 'Error', style: str = 'red')[source]
Create a
Panelwith a consistent style.The resulting panel can be displayed using a
Console.╭─ Title ──────────────────────────────────╮ │ Message content here. │ ╰──────────────────────────────────────────╯
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)[source]
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
1ifmin==0,minotherwise.allow_none (bool) -- If
True, also allow 0 CLI parameters (even ifminis greater than 0). Defaults toFalse.
- class cyclopts.validators.MutuallyExclusive[source]
Alias for
LimitedChoiceto 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)[source]
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. │ ╰───────────────────────────────────────────────────────────────╯
- class cyclopts.validators.Path(*, exists: bool = False, file_okay: bool = True, dir_okay: bool = True, ext: str | Iterable[str] | None = None)[source]
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. │ ╰───────────────────────────────────────────────────────────────╯
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
Annotatedtype alias.Requires Python 3.12+ due to
Pathsubclassing support.A
Pathsubclass that treats-as stdin (for reading) or stdout (for writing). This follows common Unix convention.StdioPathis pre-configured withallow_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
Trueif 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
Pathfile 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
Pathfile 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
Pathfile or directory.resolve()is invoked prior to returning the path.alias of
Annotated[Path, Parameter(converter=<function _path_resolve_converter at 0x731f3fde5090>)]
- cyclopts.types.ResolvedExistingPath
A
Pathfile or directory that must exist.resolve()is invoked prior to returning the path.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=True, ext=()),)), Parameter(converter=<function _path_resolve_converter at 0x731f3fde5090>)]
- cyclopts.types.Directory
A
Paththat 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
Pathdirectory that must exist.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=False, dir_okay=True, ext=()),))]
- cyclopts.types.NonExistentDirectory
A
Pathdirectory that must not exist.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=()),))]
- cyclopts.types.ResolvedDirectory
A
Pathdirectory.resolve()is invoked prior to returning the path.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=True, ext=()),)), Parameter(converter=<function _path_resolve_converter at 0x731f3fde5090>)]
- cyclopts.types.ResolvedExistingDirectory
A
Pathdirectory that must exist.resolve()is invoked prior to returning the path.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=False, dir_okay=True, ext=()),)), Parameter(converter=<function _path_resolve_converter at 0x731f3fde5090>)]
- cyclopts.types.File
A
Filethat 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
Pathfile that must exist.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=()),))]
- cyclopts.types.NonExistentFile
A
Pathfile that must not exist.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=()),))]
- cyclopts.types.ResolvedFile
A
Pathfile.resolve()is invoked prior to returning the path.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=()),)), Parameter(converter=<function _path_resolve_converter at 0x731f3fde5090>)]
- cyclopts.types.ResolvedExistingFile
A
Pathfile that must exist.resolve()is invoked prior to returning the path.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=()),)), Parameter(converter=<function _path_resolve_converter at 0x731f3fde5090>)]
- cyclopts.types.BinPath
A
Paththat must have extensionbin.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('bin',)),))]
- cyclopts.types.ExistingBinPath
A
Paththat must exist and have extensionbin.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('bin',)),))]
- cyclopts.types.NonExistentBinPath
A
Paththat must not exist and have extensionbin.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('bin',)),))]
- cyclopts.types.CsvPath
A
Paththat must have extensioncsv.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('csv',)),))]
- cyclopts.types.ExistingCsvPath
A
Paththat must exist and have extensioncsv.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('csv',)),))]
- cyclopts.types.NonExistentCsvPath
A
Paththat must not exist and have extensioncsv.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('csv',)),))]
- cyclopts.types.TxtPath
A
Paththat must have extensiontxt.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('txt',)),))]
- cyclopts.types.ExistingTxtPath
A
Paththat must exist and have extensiontxt.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('txt',)),))]
- cyclopts.types.NonExistentTxtPath
A
Paththat must not exist and have extensiontxt.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('txt',)),))]
- cyclopts.types.ImagePath
A
Paththat 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
Paththat 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
Paththat 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
Paththat must have extensionmp4.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('mp4',)),))]
- cyclopts.types.ExistingMp4Path
A
Paththat must exist and have extensionmp4.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('mp4',)),))]
- cyclopts.types.NonExistentMp4Path
A
Paththat must not exist and have extensionmp4.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('mp4',)),))]
- cyclopts.types.JsonPath
A
Paththat must have extensionjson.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('json',)),))]
- cyclopts.types.ExistingJsonPath
A
Paththat must exist and have extensionjson.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('json',)),))]
- cyclopts.types.NonExistentJsonPath
A
Paththat must not exist and have extensionjson.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('json',)),))]
- cyclopts.types.TomlPath
A
Paththat must have extensiontoml.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, dir_okay=False, ext=('toml',)),))]
- cyclopts.types.ExistingTomlPath
A
Paththat must exist and have extensiontoml.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('toml',)),))]
- cyclopts.types.NonExistentTomlPath
A
Paththat must not exist and have extensiontoml.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('toml',)),))]
- cyclopts.types.YamlPath
A
Paththat must have extensionyaml.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=True, 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.
alias of
Annotated[int, Parameter(validator=(Number(lt=None, lte=255, gt=None, gte=0, modulo=None),)), Parameter(show_default=functools.partial(<function _hex_formatter at 0x731f55772dd0>, digits=2))]
- 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.
alias of
Annotated[int, Parameter(validator=(Number(lt=None, lte=65535, gt=None, gte=0, modulo=None),)), Parameter(show_default=functools.partial(<function _hex_formatter at 0x731f55772dd0>, digits=4))]
- 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.
alias of
Annotated[int, Parameter(validator=(Number(lt=4294967296, lte=None, gt=None, gte=0, modulo=None),)), Parameter(show_default=functools.partial(<function _hex_formatter at 0x731f55772dd0>, digits=8))]
- 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.
alias of
Annotated[int, Parameter(validator=(Number(lt=18446744073709551616, lte=None, gt=None, gte=0, modulo=None),)), Parameter(show_default=functools.partial(<function _hex_formatter at 0x731f55772dd0>, digits=16))]
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}
alias of
Annotated[Any, Parameter(converter=<function _json_converter at 0x731f3fbdc430>)]
Web
Annotated types for common web-related values.
- cyclopts.types.Email
An email address string with simple validation.
alias of
Annotated[str, Parameter(validator=(<function _email_validator at 0x731f3fbdc280>,))]
.. autodata:: cyclopts.types.URL
Help Formatting
Cyclopts provides a flexible help formatting system for customizing the help-page's appearance.
- class cyclopts.help.protocols.HelpFormatter(*args, **kwargs)[source]
Protocol for help formatter functions.
It's the Formatter's job to transform a
HelpPanelinto 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[source]
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)[source]
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_speccontrols the outer panel appearance (border, title, etc.)table_speccontrols the inner table styling (no visible borders by default)column_specsdefines 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)[source]
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:
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[source]
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.
- class cyclopts.help.PlainFormatter(indent_width: int = 2, max_width: int | None = None)[source]
Plain text formatter for improved accessibility.
- Parameters:
- __call__(console: Console, options: ConsoleOptions, panel: HelpPanel) None[source]
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.
- class cyclopts.help.protocols.ColumnSpecBuilder(*args, **kwargs)[source]
Protocol for ColumnSpecBuilders.
- __call__(console: Console, options: ConsoleOptions, entries: list[HelpEntry]) tuple[ColumnSpec, ...][source]
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)[source]
Specification for panel (outer box) styling.
Used by
DefaultFormatterto 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
DefaultFormatterThe formatter that uses these specs.
TableSpecSpecification for the inner table.
ColumnSpecSpecification for individual columns.
- title: RenderableType | None
Title text displayed at the top of the panel.
Corresponds to the
titleparameter ofPanel.
- subtitle: RenderableType | None
Subtitle text displayed at the bottom of the panel.
Corresponds to the
subtitleparameter ofPanel.
- title_align: Literal['left', 'center', 'right']
Alignment of the title text within the panel.
Corresponds to the
title_alignparameter ofPanel.
- subtitle_align: Literal['left', 'center', 'right']
Alignment of the subtitle text within the panel.
Corresponds to the
subtitle_alignparameter ofPanel.
- style: StyleType | None
Style applied to the panel background.
Corresponds to the
styleparameter ofPanel.
- border_style: StyleType | None
Style applied to the panel border.
Corresponds to the
border_styleparameter ofPanel.
- box: Box | None
Box drawing style for the panel border.
Corresponds to the
boxparameter ofPanel. Seerich.boxfor available styles. Defaults torich.box.ROUNDED.
- padding: PaddingDimensions
Padding inside the panel (top/bottom, left/right) or (top, right, bottom, left).
Corresponds to the
paddingparameter ofPanel.
- expand: bool
Whether the panel should expand to fill available width.
Corresponds to the
expandparameter ofPanel.
- width: int | None
Fixed width for the panel in characters.
Corresponds to the
widthparameter ofPanel.
- height: int | None
Fixed height for the panel in lines.
Corresponds to the
heightparameter ofPanel.
- safe_box: bool | None
Whether to use ASCII-safe box characters for compatibility.
Corresponds to the
safe_boxparameter ofPanel.
- highlight: bool
Enable automatic highlighting of panel contents.
Corresponds to the
highlightparameter ofPanel.
- 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)[source]
Specification for table layout and styling.
Used by
DefaultFormatterto control the appearance of tables that display commands and parameters. This spec defines table-wide properties like borders, headers, and padding.See also
DefaultFormatterThe formatter that uses these specs.
ColumnSpecSpecification for individual columns.
PanelSpecSpecification for the outer panel.
- title: str | None
Title text displayed above the table.
Corresponds to the
titleparameter ofTable.
- caption: str | None
Caption text displayed below the table.
Corresponds to the
captionparameter ofTable.
- style: StyleType | None
Default style applied to the entire table.
Corresponds to the
styleparameter ofTable.
- border_style: StyleType | None
Style applied to table borders.
Corresponds to the
border_styleparameter ofTable.
- header_style: StyleType | None
Default style for all table headers (can be overridden per column).
Corresponds to the
header_styleparameter ofTable.
Default style for all table footers (can be overridden per column).
Corresponds to the
footer_styleparameter ofTable.
- box: Box | None
Box drawing style for the table borders.
Corresponds to the
boxparameter ofTable. Seerich.boxfor available styles.
- show_header: bool
Whether to display column headers.
Corresponds to the
show_headerparameter ofTable.
Whether to display column footers.
Corresponds to the
show_footerparameter ofTable.
- show_lines: bool
Whether to show horizontal lines between rows.
Corresponds to the
show_linesparameter ofTable.
- show_edge: bool
Whether to draw a box around the outside of the table.
Corresponds to the
show_edgeparameter ofTable.
- expand: bool
Whether the table should expand to fill available width.
Corresponds to the
expandparameter ofTable.
- pad_edge: bool
Whether to add padding to the table edges.
Corresponds to the
pad_edgeparameter ofTable.
- padding: PaddingDimensions
Padding around cell content (top, right, bottom, left).
Corresponds to the
paddingparameter ofTable.
- collapse_padding: bool
Whether to collapse padding when adjacent cells are empty.
Corresponds to the
collapse_paddingparameter ofTable.
- width: int | None
Fixed width for the table in characters.
Corresponds to the
widthparameter ofTable.
- min_width: int | None
Minimum width for the table in characters.
Corresponds to the
min_widthparameter ofTable.
- safe_box: bool | None
Whether to use ASCII-safe box characters for compatibility.
Corresponds to the
safe_boxparameter ofTable.
- build(columns: tuple[ColumnSpec, ...], entries: Iterable[HelpEntry], **overrides) Table[source]
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
- 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)[source]
Specification for a single column in a help table.
Used by
DefaultFormatterto define how individual columns are rendered in help tables. Each column can have its own renderer, styling, and layout properties.See also
DefaultFormatterThe formatter that uses these specs.
TableSpecSpecification for the entire table.
PanelSpecSpecification 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
Rendererprotocol. The function receives aHelpEntryand should return aRenderableType(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 │ └─────────┴─────────────┘
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_styleparameter ofrich.table.Table.add_column().
Style applied to the column footer text.
Corresponds to the
footer_styleparameter ofrich.table.Table.add_column().
- style: StyleType | None
Default style applied to all cells in this column.
Corresponds to the
styleparameter ofrich.table.Table.add_column().
- justify: Literal['default', 'left', 'center', 'right', 'full']
Text justification within the column.
Corresponds to the
justifyparameter ofrich.table.Table.add_column().
- vertical: Literal['top', 'middle', 'bottom']
Vertical alignment of text within cells.
Corresponds to the
verticalparameter ofrich.table.Table.add_column().
- overflow: Literal['fold', 'crop', 'ellipsis', 'ignore']
How to handle text that exceeds column width.
Corresponds to the
overflowparameter ofrich.table.Table.add_column().
- width: int | None
Fixed width for the column in characters.
Corresponds to the
widthparameter ofrich.table.Table.add_column().
- min_width: int | None
Minimum width for the column in characters.
Corresponds to the
min_widthparameter ofrich.table.Table.add_column().
- max_width: int | None
Maximum width for the column in characters.
Corresponds to the
max_widthparameter ofrich.table.Table.add_column().
- ratio: int | None
Relative width ratio compared to other columns.
Corresponds to the
ratioparameter ofrich.table.Table.add_column().
- no_wrap: bool
Prevent text wrapping in the column.
Corresponds to the
no_wrapparameter ofrich.table.Table.add_column().
- highlight: bool | None
Enable automatic highlighting of text in the column.
Corresponds to the
highlightparameter ofrich.table.Table.add_column().
- class cyclopts.help.NameRenderer(max_width: int | None = None)[source]
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[source]
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)[source]
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[source]
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[source]
Renderer for required parameter asterisk indicator.
A simple renderer that displays an asterisk (*) for required parameters.
- class cyclopts.help.HelpPanel(format: Literal['command', 'parameter'], title: RenderableType, description: Any | None = None, entries: list[HelpEntry] = NOTHING)[source]
Data container for help panel information.
- title: RenderableType
The title text displayed at the top of the help panel.
- description: Any
Optional description text displayed below the title.
Typically a
stror aRenderableType
- class cyclopts.help.HelpEntry(*, positive_names: tuple[str, ...] = (), positive_shorts: tuple[str, ...] = (), negative_names: tuple[str, ...] = (), negative_shorts: tuple[str, ...] = (), description: Any | None = None, required: bool = False, sort_key: Any | None = None, type: Any | None = None, choices: tuple[str, ...] | None = None, env_var: tuple[str, ...] | None = None, default: str | None = None)[source]
Container for help table entry data.
- 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
stror aRenderableType
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:
Apply
root_keys(if provided) to enter the project's configuration namespace.Apply the command name(s) to enter the current command's configuration namespace.
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)[source]
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
Appshould 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
FileNotFoundErrorif it does not exist.
- search_parents: bool = False
If
pathdoesn't exist, iteratively search parenting directories for a same-named configuration file. RaisesFileNotFoundErrorif no configuration file is found.
- 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)[source]
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.yamlthat is shared with other applications, it is common to store your projects configuration under a key likemyproject:.Your Cyclopts
Appwould 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
FileNotFoundErrorif it does not exist.
- search_parents: bool = False
If
pathdoesn't exist, iteratively search parenting directories for a same-named configuration file. RaisesFileNotFoundErrorif no configuration file is found.
- 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)[source]
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.jsonthat is shared with other applications, it is common to store your projects configuration under a key like"myproject":.Your Cyclopts
Appwould 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
FileNotFoundErrorif it does not exist.
- search_parents: bool = False
If
pathdoesn't exist, iteratively search parenting directories for a same-named configuration file. RaisesFileNotFoundErrorif no configuration file is found.
- 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)[source]
Configuration source from an in-memory dictionary.
Useful for programmatically generated configurations.
Use an in-memory Python dictionary as configuration source.
- root_keys: Iterable[str] = ()
The key or sequence of keys that lead to the root configuration structure for this app.
- class cyclopts.config.Env(prefix: str = '', *, source: str = 'env', command: bool = True, show: bool = True)[source]
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
fooandbarare not supplied by the command line, the app will check the environment variablesMY_SCRIPT_MY_COMMAND_FOOandMY_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 likeMY_APP_.
Exceptions
- exception cyclopts.CycloptsError[source]
Bases:
ExceptionRoot exception for runtime errors.
As CycloptsErrors bubble up the Cyclopts call-stack, more information is added to it.
- msg: str | Text | None
If set, override automatic message generation.
A
stris rendered as literal text. To apply styling, pass arich.text.Textinstance — either constructed from Rich console markup:from rich.text import Text raise CycloptsError(msg=Text.from_markup("Invalid value [bold red]foo[/]."))
or assembled directly using the built-in palette (
STYLE_OFFENDING_VALUE,STYLE_NAME,STYLE_VALID_CHOICE,STYLE_SUGGESTION,STYLE_SOURCE) to keep custom errors visually consistent with the framework's output:from rich.text import Text from cyclopts.exceptions import STYLE_NAME, STYLE_OFFENDING_VALUE t = Text("Invalid value ") t.append("foo", style=STYLE_OFFENDING_VALUE) t.append(" for ") t.append("--name", style=STYLE_NAME) raise CycloptsError(msg=t)
- exception cyclopts.ValidationError[source]
Bases:
CycloptsErrorValidator function raised an exception.
- exception cyclopts.UnknownOptionError[source]
Bases:
CycloptsErrorUnknown/unregistered option provided by the cli.
A nearest-neighbor parameter suggestion may be printed.
- argument_collection: ArgumentCollection
Argument collection of plausible options.
- exception cyclopts.CoercionError[source]
Bases:
CycloptsErrorThere was an error performing automatic type coercion.
- exception cyclopts.UnknownCommandError[source]
Bases:
CycloptsErrorCLI token combination did not yield a valid command.
- msg: str | Text | None
If set, override automatic message generation.
A
stris rendered as literal text. To apply styling, pass arich.text.Textinstance — either constructed from Rich console markup:from rich.text import Text raise CycloptsError(msg=Text.from_markup("Invalid value [bold red]foo[/]."))
or assembled directly using the built-in palette (
STYLE_OFFENDING_VALUE,STYLE_NAME,STYLE_VALID_CHOICE,STYLE_SUGGESTION,STYLE_SOURCE) to keep custom errors visually consistent with the framework's output:from rich.text import Text from cyclopts.exceptions import STYLE_NAME, STYLE_OFFENDING_VALUE t = Text("Invalid value ") t.append("foo", style=STYLE_OFFENDING_VALUE) t.append(" for ") t.append("--name", style=STYLE_NAME) raise CycloptsError(msg=t)
- exception cyclopts.UnusedCliTokensError[source]
Bases:
CycloptsErrorNot all CLI tokens were used as expected.
- exception cyclopts.MissingArgumentError[source]
Bases:
CycloptsErrorA required argument was not provided.
- exception cyclopts.ConsumeMultipleError[source]
Bases:
MissingArgumentErrorThe number of values provided doesn't meet consume_multiple constraints.
- exception cyclopts.RequiresEqualsError[source]
Bases:
CycloptsErrorA long option requires
=to assign a value (e.g.,--option=value).
- exception cyclopts.RepeatArgumentError[source]
Bases:
CycloptsErrorThe same parameter has erroneously been specified multiple times.
- exception cyclopts.MixedArgumentError[source]
Bases:
CycloptsErrorCannot supply keywords and non-keywords to the same argument.
- exception cyclopts.CommandCollisionError[source]
Bases:
ExceptionA command with the same name has already been registered to the app.
- exception cyclopts.CombinedShortOptionError[source]
Bases:
CycloptsErrorCannot combine short, token-consuming options with short flags.
- exception cyclopts.EditorError[source]
Bases:
ExceptionRoot editor-related error.
Root exception raised by all exceptions in
edit().
- exception cyclopts.EditorNotFoundError[source]
Bases:
EditorErrorCould not find a valid text editor for :func`.edit`.
- exception cyclopts.EditorDidNotSaveError[source]
Bases:
EditorErrorUser did not save upon exiting
edit().
- exception cyclopts.EditorDidNotChangeError[source]
Bases:
EditorErrorUser did not edit file contents in
edit().
Style Constants
Palette used by the built-in error messages. See
CycloptsError.msg for example usage.
- cyclopts.exceptions.STYLE_OFFENDING_VALUE = 'bold red'
Rich style for an offending user-supplied value.
- cyclopts.exceptions.STYLE_NAME = 'bold'
Rich style for a parameter, option, or command name.
- cyclopts.exceptions.STYLE_VALID_CHOICE = 'cyan'
Rich style for valid choices in
Choose from:lists.
- cyclopts.exceptions.STYLE_SUGGESTION = 'bold green'
Rich style for
Did you mean ...suggestions.
- cyclopts.exceptions.STYLE_SOURCE = 'dim'
Rich style for source suffixes like
from <CONFIG>.