API
- class cyclopts.App(name: str | Iterable[str] | None = None, help: str | None = None, usage: str | None = None, *, alias: str | Iterable[str] | None = None, default_command: Callable[[...], Any] | None = None, default_parameter: Parameter | None = None, config: _ConfigCallable | Iterable[_ConfigCallable] | None = None, version: None | str | Callable[[...], str] | Callable[[...], Coroutine[Any, Any, str]] = None, version_flags: str | Iterable[str] | None = ['--version'], show: bool = True, console: Console | None = None, error_console: Console | None = None, help_flags: str | Iterable[str] | None = ['--help', '-h'], help_format: Literal['markdown', 'md', 'plaintext', 'restructuredtext', 'rst', 'rich'] | None = None, help_on_error: bool | None = None, help_prologue: str | None = None, help_epilogue: str | None = None, version_format: Literal['markdown', 'md', 'plaintext', 'restructuredtext', 'rst', 'rich'] | None = None, group: Group | str | Iterable[Group | str] | None = None, group_arguments: None | str | Group = None, group_parameters: None | str | Group = None, group_commands: None | str | Group = None, validator: Callable[[...], Any] | Iterable[Callable[[...], Any]] | None = None, name_transform: Callable[[str], str] | None = None, sort_key: Any = None, end_of_options_delimiter: str | None = None, print_error: bool | None = None, exit_on_error: bool | None = None, verbose: bool | None = None, suppress_keyboard_interrupt: bool = True, backend: Literal['asyncio', 'trio'] | None = None, help_formatter: None | Literal['default', 'plain'] | HelpFormatter = None, error_formatter: Callable[[CycloptsError], Any] | None = None, result_action: ResultAction | ResultActionSingle | None = None)
Cyclopts Application.
- name: str | Iterable[str] | None = None
Name of application, or subcommand if registering to another application. Name resolution order:
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.
- 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.If all values are
None, then the defaultConsoleis used.
- 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(0) else: sys.exit(0)
"return_value"
Returns the command's value unchanged. Use for embedding Cyclopts in other Python code or testing.
return result
"call_if_callable"
Calls the result if it's callable (with no arguments), otherwise returns it unchanged. Useful for the dataclass command pattern where commands return class instances with
__call__methods. Intended to be used in composition with other result actions (e.g.,["call_if_callable", "print_non_int_sys_exit"]).return result() if callable(result) else result
See Dataclass Commands for usage examples.
"sys_exit"
Never prints output. Calls
sys.exit()with the appropriate exit code. Useful for CLI apps that handle their own output and just need exit code handling.if isinstance(result, bool): sys.exit(0 if result else 1) # i.e. True is success elif isinstance(result, int): sys.exit(result) else: sys.exit(0)
"print_non_int_return_int_as_exit_code"
Prints non-int values, returns int/bool as exit codes. Useful for testing and embedding.
if isinstance(result, bool): return 0 if result else 1 # i.e. True is success elif isinstance(result, int): return result elif result is not None: print(result) return 0 else: return 0
"print_str_return_int_as_exit_code"
Only prints string return values. Returns int/bool as exit codes, silently returns 0 for other types.
if isinstance(result, str): print(result) return 0 elif isinstance(result, bool): return 0 if result else 1 # i.e. True is success elif isinstance(result, int): return result else: return 0
"print_str_return_zero"
Only prints string return values, always returns 0. Useful for simple output-only CLIs.
if isinstance(result, str): print(result) return 0
"print_non_none_return_int_as_exit_code"
Prints all non-None values (including ints), returns int/bool as exit codes.
if result is not None: print(result) if isinstance(result, bool): return 0 if result else 1 # i.e. True is success elif isinstance(result, int): return result return 0
"print_non_none_return_zero"
Prints all non-None values (including ints), always returns 0.
if result is not None: print(result) return 0
"return_int_as_exit_code_else_zero"
Never prints output. Returns int/bool as exit codes, 0 for all other types. Useful for silent CLIs.
if isinstance(result, bool): return 0 if result else 1 # i.e. True is success elif isinstance(result, int): return result else: return 0
"return_none"
Always returns None, regardless of the command's return value.
return None
"return_zero"
Always returns 0, regardless of the command's return value.
return 0
"print_return_zero"
Always prints the result (even None), then always returns 0.
print(result) return 0
"sys_exit_zero"
Always calls
sys.exit(0), regardless of the command's return value.sys.exit(0)
"print_sys_exit_zero"
Always prints the result (even None), then calls
sys.exit(0).print(result) sys.exit(0)
Custom Callable
Provide a function for fully custom result handling. Receives the command's return value and returns a processed value.
def custom_handler(result): if result is None: return 0 elif isinstance(result, str): print(f"[OUTPUT] {result}") return 0 return result app = App(result_action=custom_handler)
Sequence of Actions
Provide a sequence (list or tuple) of actions to create a result-processing pipeline. Actions are applied left-to-right, with each action receiving the result of the previous action.
def uppercase(result): return result.upper() if isinstance(result, str) else result def add_prefix(result): return f"[OUTPUT] {result}" if isinstance(result, str) else result # Pipeline: result → uppercase → add_prefix → return app = App(result_action=[uppercase, add_prefix, "return_value"]) @app.command def greet(name: str) -> str: return f"hello {name}" result = app(["greet", "world"]) # result == "[OUTPUT] HELLO WORLD"
Actions in a sequence can be any combination of predefined literal strings and custom callables. Empty sequences raise a
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
Print the application version.
- Parameters:
console (Console) -- Console to print version string to. If not provided, follows the resolution order defined in
App.console.
- __getitem__(key: str) App
Get the subapp from a command string.
All commands get registered to Cyclopts as subapps. The actual function handler is at
app[key].default_command.If the command was registered via lazy loading (import path string), it will be imported and resolved on first access.
Example usage:
from cyclopts import App app = App() app.command(App(name="foo")) @app["foo"].command def bar(): print("Running bar.") app()
- __iter__() Iterator[str]
Iterate over command & meta command names.
Example usage:
from cyclopts import App app = App() @app.command def foo(): pass @app.command def bar(): pass # help and version flags are treated as commands. assert list(app) == ["--help", "-h", "--version", "foo", "bar"]
- parse_commands(tokens: None | str | Iterable[str] = None, *, include_parent_meta=True) tuple[tuple[str, ...], tuple[App, ...], list[str]]
Extract out the command tokens from a command.
You are probably actually looking for
parse_args().- Parameters:
tokens (None | str | Iterable[str]) -- Either a string, or a list of strings to launch a command. Defaults to
sys.argv[1:]include_parent_meta (bool) --
Controls whether parent meta apps are included in the execution path.
When True (default): - Parent meta apps (i.e. the "normal" app ) are added to the apps list. - Meta app options are consumed while parsing commands. - Used for getting the inheritance hierarchy.
When False: - Meta app options are treated as regular arguments. - Used for getting the execution hierarchy.
This parameter is primarily for internal use.
- Returns:
tuple[str, ...] -- Strings that are interpreted as a valid command chain.
tuple[App, ...] -- The execution path - apps that will be invoked in order.
list[str] -- The remaining non-command tokens.
- command(obj: T, name: None | str | Iterable[str] = None, *, alias: None | str | Iterable[str] = None, **kwargs: object) T
- command(obj: None = None, name: None | str | Iterable[str] = None, *, alias: None | str | Iterable[str] = None, **kwargs: object) Callable[[T], T]
- command(obj: str, name: None | str | Iterable[str] = None, *, alias: None | str | Iterable[str] = None, **kwargs: object) None
Decorator to register a function as a CLI command.
Example usage:
from cyclopts import App app = App() @app.command def foo(): print("foo!") @app.command(name="buzz") def bar(): print("bar!") # Lazy loading via import path app.command("myapp.commands:create_user", name="create") app()
$ my-script foo foo! $ my-script buzz bar! $ my-script create # Imports and runs myapp.commands:create_user
- Parameters:
obj (Callable | App | str | None) -- Function,
App, or import path string to be registered as a command. For lazy loading, provide a string in format "module.path:function_or_app_name".name (None | str | Iterable[str]) --
Name(s) to register the command to. If not provided, defaults to:
If registering an
App, then the app's name.If registering a function, then the function's name after applying
name_transform.If registering via import path, then the attribute name after applying
name_transform.
Special value
"*"flattens all sub-App commands into this app (App instances only). See Flattening SubCommands for details.**kwargs -- Any argument that
Appcan take.
- default(obj: T, *, validator: Callable[[...], Any] | None = None) T
- default(obj: None = None, *, validator: Callable[[...], Any] | None = None) Callable[[T], T]
Decorator to register a function as the default action handler.
Example usage:
from cyclopts import App app = App() @app.default def main(): print("Hello world!") app()
$ my-script Hello world!
- assemble_argument_collection(*, default_parameter: Parameter | None = None, parse_docstring: bool = False) ArgumentCollection
Assemble the argument collection for this app.
- Parameters:
default_parameter (Parameter | None) -- Default parameter with highest priority.
parse_docstring (bool) -- Parse the docstring of
default_command. Set toTrueif we need help strings, otherwise set toFalsefor performance reasons.
- 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]]
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]]
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
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
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
Print the help page.
- Parameters:
tokens (None | str | Iterable[str]) -- Tokens to interpret for traversing the application command structure. If not provided, defaults to
sys.argv.console (Console) -- Console to print help and runtime Cyclopts errors. If not provided, follows the resolution order defined in
App.console.
- generate_docs(output_format: DocFormat = 'markdown', recursive: bool = True, include_hidden: bool = False, heading_level: int = 1, max_heading_level: int = 6, flatten_commands: bool = False, usage_name: str | None = None) str
Generate documentation for this CLI application.
- Parameters:
output_format (DocFormat) -- Output format for the documentation. Accepts "markdown"/"md", "html"/"htm", or "rst"/"rest"/"restructuredtext". Default is "markdown".
recursive (bool) -- If True, generate documentation for all subcommands recursively. Default is True.
include_hidden (bool) -- If True, include hidden commands/parameters in documentation. Default is False.
heading_level (int) -- Starting heading level for the main application title. Default is 1 (single # for markdown, = for RST).
max_heading_level (int) -- Maximum heading level to use. Headings deeper than this will be capped at this level. Standard Markdown and HTML support levels 1-6. Default is 6.
flatten_commands (bool) -- If True, generate all commands at the same heading level instead of nested. Default is False.
usage_name (str | None) -- Optional replacement for the root app name shown in
Usage:lines of the generated documentation. Useful when the runtime invocation differs from the app's configured name — for example, an app named"cli"that is typically invoked 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:
str
- Raises:
ValueError -- If an unsupported output format is specified.
Examples
>>> app = App(name="myapp", help="My CLI Application") >>> docs = app.generate_docs() # Generate markdown as string >>> html_docs = app.generate_docs(output_format="html") # Generate HTML >>> rst_docs = app.generate_docs(output_format="rst") # Generate RST >>> # To write to file, caller can do: >>> # Path("docs/cli.md").write_text(docs) >>> # Override the invocation shown in Usage: lines (e.g., uv run cli) >>> docs = app.generate_docs(usage_name="uv run cli")
- generate_completion(*, prog_name: str | None = None, shell: Literal['zsh', 'bash', 'fish'] | None = None) str
Generate shell completion script for this application.
- Parameters:
prog_name (str | None) -- Program name for completion. If None, uses first name from app.name.
shell (Literal["zsh", "bash", "fish"] | None) -- Shell type. If None, automatically detects current shell. Supported shells: "zsh", "bash", "fish".
- Returns:
Complete shell completion script.
- Return type:
str
Examples
Auto-detect shell and generate completion:
>>> app = App(name="myapp") >>> script = app.generate_completion() >>> Path("_myapp").write_text(script)
Explicitly specify shell type:
>>> script = app.generate_completion(shell="zsh")
- Raises:
ValueError -- If app has no name or shell type is unsupported.
ShellDetectionError -- If shell is None and auto-detection fails.
- install_completion(*, shell: Literal['zsh', 'bash', 'fish'] | None = None, output: Path | None = None, add_to_startup: bool = True) Path
Install shell completion script to appropriate location.
Generates and writes the completion script to a shell-specific location.
- Parameters:
shell (Literal["zsh", "bash", "fish"] | None) -- Shell type for completion. If not specified, attempts to auto-detect current shell.
output (Path | None) -- Output path for the completion script. If not specified, uses shell-specific default: - zsh: ~/.zsh/completions/_<prog_name> (or $ZSH_CUSTOM/completions/_<prog_name> with oh-my-zsh) - bash: ~/.local/share/bash-completion/completions/<prog_name> - fish: ~/.config/fish/completions/<prog_name>.fish
add_to_startup (bool) -- If True (default), adds source line to shell RC file to ensure completion is loaded. Set to False if completions are already configured to auto-load.
- Returns:
Path where the completion script was installed.
- Return type:
Examples
Auto-detect shell and install:
>>> app = App(name="myapp") >>> path = app.install_completion()
Install for specific shell:
>>> path = app.install_completion(shell="zsh")
Install to custom path:
>>> path = app.install_completion(output=Path("/custom/path"))
Install without modifying RC files:
>>> path = app.install_completion(shell="bash", add_to_startup=False)
- Raises:
ShellDetectionError -- If shell is None and auto-detection fails.
ValueError -- If shell type is unsupported.
- register_install_completion_command(name: str | Iterable[str] = '--install-completion', add_to_startup: bool = True, **kwargs) None
Register a command for installing shell completion.
This is a convenience method that creates a command which calls
install_completion(). For more control over the command implementation, users can manually define their own command.- Parameters:
name (str | Iterable[str]) -- Command name(s) for the install completion command. Defaults to "--install-completion".
add_to_startup (bool) -- If True (default), adds source line to shell RC file to ensure completion is loaded. Set to False if completions are already configured to auto-load.
**kwargs -- Additional keyword arguments to pass to
command(). Can be used to customize the command registration (e.g., help, group, help_flags, version_flags).
Examples
Register install-completion command:
>>> app = App(name="myapp") >>> app.register_install_completion_command() >>> app() # Now responds to: myapp --install-completion
Use a custom command name:
>>> app.register_install_completion_command(name="--setup-completion")
Customize help text:
>>> app.register_install_completion_command(help="Install shell completion for myapp.")
Customize command registration:
>>> app.register_install_completion_command(group="Setup", help_flags=[])
Install without modifying RC files:
>>> app.register_install_completion_command(add_to_startup=False)
See also
install_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
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)
Copy over all commands from another
App.Commands from the meta app will not be copied over.
- Parameters:
app (cyclopts.App) -- All commands from this application will be copied over.
- class cyclopts.Parameter(name: str | ~collections.abc.Iterable[str] | None = None, *, converter: ~collections.abc.Callable[[...], ~typing.Any] | str | None = None, validator: ~collections.abc.Callable[[~typing.Any, ~typing.Any], ~typing.Any] | ~collections.abc.Iterable[~collections.abc.Callable[[~typing.Any, ~typing.Any], ~typing.Any]] | None = (), alias: str | ~collections.abc.Iterable[str] | None = None, negative: bool | str | ~collections.abc.Iterable[str] | None = None, group: None | ~cyclopts.group.Group | str | ~collections.abc.Iterable[~cyclopts.group.Group | str] = None, parse: bool | ~re.Pattern[str] | str | None = None, show: bool | None = None, show_default: None | bool | ~collections.abc.Callable[[~typing.Any], ~typing.Any] = None, show_choices: bool | None = None, help: str | None = None, show_env_var: bool | None = None, env_var: str | ~collections.abc.Iterable[str] | None = None, env_var_split: ~collections.abc.Callable[[...], ~typing.Any] = <function env_var_split>, negative_bool: str | ~collections.abc.Iterable[str] | None = None, negative_iterable: str | ~collections.abc.Iterable[str] | None = None, negative_none: str | ~collections.abc.Iterable[str] | None = None, required: bool | None = None, allow_leading_hyphen: bool = False, requires_equals: bool = False, name_transform: ~collections.abc.Callable[[str], str] | None = None, accepts_keys: bool | None = None, consume_multiple: bool | int | ~collections.abc.Sequence[int] | tuple[int, int | None] | None = None, json_dict: bool | None = None, json_list: bool | None = None, count: bool | None = None, allow_repeating: bool | None = None, n_tokens: int | None = None)
Cyclopts configuration for individual function parameters with
Annotated.Example usage:
from cyclopts import app, Parameter from typing import Annotated app = App() @app.default def main(foo: Annotated[int, Parameter(name="bar")]): print(foo) app()
$ my-script 100 100 $ my-script --bar 100 100
- name: None | str | Iterable[str] = None
Name(s) to expose to the CLI. If not specified, cyclopts will apply
name_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 | Iterable[Callable] = None
A function (or list of functions) that validates data returned by the
converter.def validator(type_, value: Any) -> None: pass # Raise a TypeError, ValueError, or AssertionError here if data is invalid.
- group: None | str | Group | Iterable[str | Group] = None
The group(s) that this parameter belongs to. This can be used to better organize the help-page, and/or to add additional conversion/validation logic (such as ensuring mutually-exclusive arguments).
If
None, defaults to one of the following groups: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_bool: str | None = None
Prefix for negative boolean flags. Defaults to
"no-".
- negative_iterable: str | None = None
Prefix for empty iterables (like lists and sets) flags. Defaults to
"empty-".
- negative_none: str | None = None
Prefix for setting optional parameters to
None. Not enabled by default (no prefixes set).Example:
from pathlib import Path from typing import Annotated from cyclopts import App, Parameter app = App( default_parameter=Parameter(negative_none="none-") ) @app.default def default(path: Path | None = Path("data.bin")): print(f"{path=}") app()
$ my-script path=PosixPath('data.bin') $ my-script --path=cat.jpeg path=PosixPath('cat.jpeg') $ my-script --none-path path=None
- allow_leading_hyphen: bool = False
Allow parsing non-numeric values that begin with a hyphen
-. This is disabled (False) by default, allowing for more helpful error messages for unknown CLI options.
- requires_equals: bool = False
Require long options to use
=to separate the option name from its value (e.g.,--option=value). When enabled, the space-separated form--option 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" was specified multiple times. │ ╰─────────────────────────────────────────────────────────╯
- n_tokens: int | None = None
Explicitly override the number of CLI tokens this parameter consumes.
By default, Cyclopts infers the token count from the parameter's type hint (e.g.,
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
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)
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
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>)
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.
- value: str = ""
The parsed token value (unadulterated).
- source: str = ""
Where the token came from; used for error message purposes. Cyclopts uses the string
clifor cli-parsed tokens.
- index: int = 0
The relative positional index in which the value was provided.
- class cyclopts.field_info.FieldInfo(names: tuple[str, ...] = (), kind: _ParameterKind = _ParameterKind.POSITIONAL_OR_KEYWORD, *, required: bool = False, default: Any, annotation: Any, help: str | None = None)
Extension of
inspect.Parameter.
- class cyclopts.Argument(*, tokens: list[~cyclopts.token.Token] = NOTHING, field_info: ~cyclopts.field_info.FieldInfo = NOTHING, parameter: ~cyclopts.parameter.Parameter = NOTHING, hint: ~typing.Any = <class 'str'>, index: int | None = None, keys: tuple[str, ...] = (), value: ~typing.Any = <UNSET>)
Encapsulates functionality and additional contextual information for parsing a parameter.
An argument is defined as anything that would have its own entry in the help page.
- tokens: list[Token]
List of
Tokenparsed from various sources. Do not directly mutate; seeappend().
- hint: Any
The type hint for this argument; may be different from
FieldInfo.annotation.
- index: int | None
Associated python positional index for argument. If
None, then cannot be assigned positionally.
- keys: tuple[str, ...]
Python keys that lead to this leaf.
self.parameter.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.
- property show_default: bool | Callable[[Any], str]
Show the default value on the help page.
- match(term: str | int, *, transform: Callable[[str], str] | None = None, delimiter: str = '.') tuple[tuple[str, ...], Any]
Match a name search-term, or a positional integer index.
- Raises:
ValueError -- If no match is found.
- Returns:
tuple[str, ...] -- Leftover keys after matching to this argument. Used if this argument accepts_arbitrary_keywords.
Any -- Implicit value.
UNSETif no implicit value is applicable.
- property has_tokens: bool
This argument, or a child argument, has at least 1 parsed token.
- property children_recursive: ArgumentCollection
- convert(converter: Callable | None = None)
-
- Parameters:
converter (Callable | None) -- Converter function to use. Overrides
self.parameter.converter- Returns:
The converted data. Same as
value.- Return type:
Any
- validate(value)
Validates provided value.
- Parameters:
value -- Value to validate.
- Returns:
The converted data. Same as
value.- Return type:
Any
- convert_and_validate(converter: Callable | None = None)
Converts and validates
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, ...] = ())
The number of string tokens this argument consumes.
- Parameters:
keys (tuple[str, ...]) -- The python keys into this argument. If provided, returns the number of string tokens that specific data type within the argument consumes.
- Returns:
int -- Number of string tokens to create 1 element.
consume_all (bool) --
Trueif this data type is iterable.
- property negatives
Negative flags from
Parameter.get_negatives().
- property name: str
The first provided name this argument goes by.
- property names: tuple[str, ...]
Names the argument goes by (both positive and negative).
- env_var_split(value: str, delimiter: str | None = None) list[str]
Split a given value with
Parameter.env_var_split().
- property show: bool
Show this argument on the help page.
If an argument has child arguments, don't show it on the help-page. Returns False for arguments that won't be parsed (including underscore-prefixed params).
- property parse: bool
Whether this argument should be parsed from CLI tokens.
If
Parameter.parseis a regex pattern, parse if the pattern matches the field name; otherwise don't parse.
- property required: bool
Whether or not this argument requires a user-provided value.
- is_positional_only() bool
- is_var_positional() bool
- is_flag() bool
Check if this argument is a flag (consumes no CLI tokens).
Flags are arguments that don't consume command-line tokens after the option name. They typically have implicit values (e.g., --verbose for bool, --no-items for list).
- Returns:
True if the argument consumes zero tokens from the command line.
- Return type:
bool
Examples
>>> from cyclopts import Parameter >>> bool_arg = Argument(hint=bool, parameter=Parameter(name="--verbose")) >>> bool_arg.is_flag() True >>> str_arg = Argument(hint=str, parameter=Parameter(name="--name")) >>> str_arg.is_flag() False
- get_choices(force: bool = False) tuple[str, ...] | None
Extract completion choices from type hint.
Extracts choices from Literal types, Enum types, and Union types containing them. Respects the Parameter.show_choices setting unless force=True.
- Parameters:
force (bool) -- If True, return choices even when show_choices=False. Used by shell completion to always provide choices.
- Returns:
Tuple of choice strings if choices exist and should be shown, None otherwise.
- Return type:
tuple[str, ...] | None
Examples
>>> argument = Argument(hint=Literal["dev", "staging", "prod"], parameter=Parameter(show_choices=True)) >>> argument.get_choices() ('dev', 'staging', 'prod') >>> argument = Argument(hint=Literal["dev", "staging", "prod"], parameter=Parameter(show_choices=False)) >>> argument.get_choices() # Returns None for help text >>> argument.get_choices(force=True) # Returns choices for completion ('dev', 'staging', 'prod')
- class cyclopts.ArgumentCollection(*args)
A list-like container for
Argument.- copy() ArgumentCollection
Returns a shallow copy of the
ArgumentCollection.
- __contains__(item: object, /) bool
Check if an argument or argument name exists in the collection.
- Parameters:
item (Argument | str) -- Either an Argument object or a string name/alias to search for.
- Returns:
True if the item is in the collection.
- Return type:
bool
Examples
>>> argument_collection = ArgumentCollection( ... [ ... Argument(parameter=Parameter(name="--foo")), ... Argument(parameter=Parameter(name=("--bar", "-b"))), ... ] ... ) >>> "--foo" in argument_collection True >>> "-b" in argument_collection # Alias matching True >>> "--baz" in argument_collection False
- get(term: str | int, default: type[<UNSET>] = <UNSET>, *, transform: ~collections.abc.Callable[[str], str] | None = None, delimiter: str = '.') Argument
- get(term: str | int, default: T, *, transform: Callable[[str], str] | None = None, delimiter: str = '.') Argument | T
Get an
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:
- match(term: str | int, *, transform: Callable[[str], str] | None = None, delimiter: str = '.') tuple[Argument, tuple[str, ...], Any]
Matches CLI keyword or index to their
Argument.- Parameters:
term (str | int) --
One of:
strkeyword like"--foo"or"-f"or"--foo.bar.baz".intglobal positional index.
- 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
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
Special sentinel value indicating that no data was provided. Do not instantiate.
- cyclopts.default_name_transform(s: str) str
Converts a python identifier into a CLI token.
Performs the following operations (in order):
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.- Parameters:
s (str) -- Input python identifier string.
- Returns:
Transformed name.
- Return type:
str
- cyclopts.env_var_split(type_: Any, val: str, *, delimiter: str | None = None) list[str]
Type-dependent environment variable value splitting.
Converts a single string into a list of strings. Splits when:
The
type_is some variant 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.- Parameters:
type (type) -- Type hint that we will eventually coerce into.
val (str) -- String to split.
delimiter (str | None) -- Delimiter to split
valon. If None, defaults to whitespace.
- Returns:
List of individual string tokens.
- Return type:
list[str]
- cyclopts.edit(initial_text: str = '', *, fallback_editors: Sequence[str] = ('nano', 'vim', 'notepad', 'gedit'), editor_args: Sequence[str] = (), path: str | Path = '', encoding: str = 'utf-8', save: bool = True, required: bool = True) str
Get text input from a user by launching their default text editor.
- Parameters:
initial_text (str) -- Initial text to populate the text file with.
fallback_editors (Sequence[str]) -- If the text editor cannot be determined from the environment variable
EDITOR, attempt to use these text editors in the order provided.editor_args (Sequence[str]) -- Additional CLI arguments that are passed along to the editor-launch command.
path (Union[str, Path]) -- If specified, the path to the file that should be opened. Text editors typically display this, so a custom path may result in a better user-interface. Defaults to a temporary text file.
encoding (str) -- File encoding to use.
save (bool) -- Require the user to save before exiting the editor. Otherwise raises
EditorDidNotSaveError.required (bool) -- Require for the saved text to be different from
initial_text. Otherwise 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:
str
- cyclopts.run(callable: Callable[[...], Coroutine[None, None, V]], /, *, result_action: Literal['return_value']) V
- cyclopts.run(callable: Callable[[...], V], /, *, result_action: Literal['return_value']) V
- cyclopts.run(callable: Callable[[...], Coroutine[None, None, Any]], /, *, result_action: Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any] | Iterable[Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any]] | None = None) Any
- cyclopts.run(callable: Callable[[...], Any], /, *, result_action: Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any] | Iterable[Literal['return_value', 'call_if_callable', 'print_non_int_return_int_as_exit_code', 'print_str_return_int_as_exit_code', 'print_str_return_zero', 'print_non_none_return_int_as_exit_code', 'print_non_none_return_zero', 'return_int_as_exit_code_else_zero', 'print_non_int_sys_exit', 'sys_exit', 'return_none', 'return_zero', 'print_return_zero', 'sys_exit_zero', 'print_sys_exit_zero'] | Callable[[Any], Any]] | None = None) Any
Run the given callable as a CLI command.
The callable may also be a coroutine function. This function is syntax sugar for very simple use cases, and is roughly equivalent to:
from cyclopts import App app = App() app.default(callable) app()
- Parameters:
callable -- The function to execute as a CLI command.
result_action -- How to handle the command's return value. If not specified, uses the default
"print_non_int_sys_exit"which 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)
- class cyclopts.CycloptsPanel(message: Any, title: str = 'Error', style: str = 'red')
Create a
Panelwith a consistent style.The resulting panel can be displayed using a
Console.╭─ Title ──────────────────────────────────╮ │ Message content here. │ ╰──────────────────────────────────────────╯
- Parameters:
message (Any) -- The body of the panel will be filled with the stringified version of the message.
title (str) -- Title of the panel that appears in the top-left corner.
style (str) -- Rich style for the panel border.
- Returns:
Formatted panel object.
- Return type:
Panel
Validators
Cyclopts has several builtin validators for common CLI inputs.
- class cyclopts.validators.LimitedChoice(min: int = 0, max: int | None = None, allow_none: bool = False)
Group validator that limits the number of selections per group.
Commonly used for enforcing mutually-exclusive parameters (default behavior).
- Parameters:
min (int) -- The minimum (inclusive) number of CLI parameters allowed. If negative, then all parameters in the group must have CLI values provided.
max (int | None) -- The maximum (inclusive) number of CLI parameters allowed. Defaults to
1ifmin==0,minotherwise.allow_none (bool) -- If
True, also allow 0 CLI parameters (even ifminis greater than 0). Defaults toFalse.
- class cyclopts.validators.MutuallyExclusive
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)
Limit input number to a value range.
Example Usage:
from cyclopts import App, Parameter, validators from typing import Annotated app = App() @app.default def main(age: Annotated[int, Parameter(validator=validators.Number(gte=0, lte=150))]): print(f"You are {age} years old.") app()
$ my-script 100 You are 100 years old. $ my-script -1 ╭─ Error ───────────────────────────────────────────────────────╮ │ Invalid value "-1" for "AGE". Must be >= 0. │ ╰───────────────────────────────────────────────────────────────╯ $ my-script 200 ╭─ Error ───────────────────────────────────────────────────────╮ │ Invalid value "200" for "AGE". Must be <= 150. │ ╰───────────────────────────────────────────────────────────────╯
- lt: int | float | None
Input value must be less than this value.
- lte: int | float | None
Input value must be less than or equal this value.
- gt: int | float | None
Input value must be greater than this value.
- gte: int | float | None
Input value must be greater than or equal this value.
- modulo: int | float | None
Input value must be a multiple of this value.
- class cyclopts.validators.Path(*, exists: bool = False, file_okay: bool = True, dir_okay: bool = True, ext: str | Iterable[str] | None = None)
Assertions on properties of
pathlib.Path.Example Usage:
from cyclopts import App, Parameter, validators from pathlib import Path from typing import Annotated app = App() @app.default def main( # ``src`` must be a file that exists. src: Annotated[Path, Parameter(validator=validators.Path(exists=True, dir_okay=False))], # ``dst`` must be a path that does **not** exist. dst: Annotated[Path, Parameter(validator=validators.Path(dir_okay=False, file_okay=False))], ): "Copies src->dst." dst.write_bytes(src.read_bytes()) app()
$ my-script foo.bin bar.bin # if foo.bin does not exist ╭─ Error ───────────────────────────────────────────────────────╮ │ Invalid value "foo.bin" for "SRC". "foo.bin" does not exist. │ ╰───────────────────────────────────────────────────────────────╯ $ my-script foo.bin bar.bin # if bar.bin exists ╭─ Error ───────────────────────────────────────────────────────╮ │ Invalid value "bar.bin" for "DST". "bar.bin" already exists. │ ╰───────────────────────────────────────────────────────────────╯
- exists: bool
If
True, specified path must exist. Defaults toFalse.
- file_okay: bool
If path exists, check it's type:
If
True, specified path may be an existing file.If
False, then existing files are not allowed.
Defaults to
True.
- dir_okay: bool
If path exists, check it's type:
If
True, specified path may be an existing directory.If
False, then existing directories are not allowed.
Defaults to
True.
- ext: str | Sequence[str]
Supplied path must have this extension (case insensitive). May or may not include the ".".
Types
Cyclopts has builtin pre-defined annotated-types for common conversion and validation configurations. Most definitions in this section are simply predefined annotations for convenience:
Annotated[..., Parameter(...)]
Custom classes that provide additional functionality beyond simple annotations will be noted.
Due to Cyclopts's advanced Parameter resolution engine, these annotations can themselves be annotated to further configure behavior. E.g:
Annotated[PositiveInt, Parameter(...)]
Path
Path annotated types for checking existence, type, and performing path-resolution.
All of these types will also work on sequence of paths (e.g. tuple[Path, Path] or list[Path]).
- class cyclopts.types.StdioPath
Note
This is a custom class, not a simple
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.
- cyclopts.types.ResolvedExistingPath
A
Pathfile or directory that must exist.resolve()is invoked prior to returning the path.
- 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.
- cyclopts.types.ResolvedExistingDirectory
A
Pathdirectory that must exist.resolve()is invoked prior to returning the path.
- 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.
- cyclopts.types.ResolvedExistingFile
A
Pathfile that must exist.resolve()is invoked prior to returning the path.
- 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',)),))]
- cyclopts.types.ExistingYamlPath
A
Paththat must exist and have extensionyaml.alias of
Annotated[Path, Parameter(validator=(Path(exists=True, file_okay=True, dir_okay=False, ext=('yaml',)),))]
- cyclopts.types.NonExistentYamlPath
A
Paththat must not exist and have extensionyaml.alias of
Annotated[Path, Parameter(validator=(Path(exists=False, file_okay=False, dir_okay=False, ext=('yaml',)),))]
Number
Annotated types for checking common int/float value constraints.
All of these types will also work on sequence of numbers (e.g. tuple[int, int] or list[float]).
- cyclopts.types.PositiveFloat
A float that must be
>0.alias of
Annotated[float, Parameter(validator=(Number(lt=None, lte=None, gt=0, gte=None, modulo=None),))]
- cyclopts.types.NonNegativeFloat
A float that must be
>=0.alias of
Annotated[float, Parameter(validator=(Number(lt=None, lte=None, gt=None, gte=0, modulo=None),))]
- cyclopts.types.NegativeFloat
A float that must be
<0.alias of
Annotated[float, Parameter(validator=(Number(lt=0, lte=None, gt=None, gte=None, modulo=None),))]
- cyclopts.types.NonPositiveFloat
A float that must be
<=0.alias of
Annotated[float, Parameter(validator=(Number(lt=None, lte=0, gt=None, gte=None, modulo=None),))]
- cyclopts.types.NormFloat
A float in the range
[0, 1].alias of
Annotated[float, Parameter(validator=(Number(lt=None, lte=1, gt=None, gte=0, modulo=None),))]
- cyclopts.types.SignedNormFloat
A float in the range
[-1, 1].alias of
Annotated[float, Parameter(validator=(Number(lt=None, lte=1, gt=None, gte=-1, modulo=None),))]
- cyclopts.types.PositiveInt
An int that must be
>0.alias of
Annotated[int, Parameter(validator=(Number(lt=None, lte=None, gt=0, gte=None, modulo=None),))]
- cyclopts.types.NonNegativeInt
An int that must be
>=0.alias of
Annotated[int, Parameter(validator=(Number(lt=None, lte=None, gt=None, gte=0, modulo=None),))]
- cyclopts.types.NegativeInt
An int that must be
<0.alias of
Annotated[int, Parameter(validator=(Number(lt=0, lte=None, gt=None, gte=None, modulo=None),))]
- cyclopts.types.NonPositiveInt
An int that must be
<=0.alias of
Annotated[int, Parameter(validator=(Number(lt=None, lte=0, gt=None, gte=None, modulo=None),))]
- cyclopts.types.PercentInt
An int in the range
[0, 100].alias of
Annotated[int, Parameter(validator=(Number(lt=None, lte=100, gt=None, gte=0, modulo=None),))]
- cyclopts.types.UInt8
An unsigned 8-bit integer.
alias of
Annotated[int, Parameter(validator=(Number(lt=None, lte=255, gt=None, gte=0, modulo=None),))]
- cyclopts.types.HexUInt8
An unsigned 8-bit integer who's default value will be displayed as hexadecimal in the help-page.
- cyclopts.types.Int8
A signed 8-bit integer.
alias of
Annotated[int, Parameter(validator=(Number(lt=None, lte=127, gt=None, gte=-128, modulo=None),))]
- cyclopts.types.UInt16
An unsigned 16-bit integer.
alias of
Annotated[int, Parameter(validator=(Number(lt=None, lte=65535, gt=None, gte=0, modulo=None),))]
- cyclopts.types.HexUInt16
An unsigned 16-bit integer who's default value will be displayed as hexadecimal in the help-page.
- cyclopts.types.Int16
A signed 16-bit integer.
alias of
Annotated[int, Parameter(validator=(Number(lt=None, lte=32767, gt=None, gte=-32768, modulo=None),))]
- cyclopts.types.UInt32
An unsigned 32-bit integer.
alias of
Annotated[int, Parameter(validator=(Number(lt=4294967296, lte=None, gt=None, gte=0, modulo=None),))]
- cyclopts.types.HexUInt32
An unsigned 32-bit integer who's default value will be displayed as hexadecimal in the help-page.
- cyclopts.types.Int32
A signed 32-bit integer.
alias of
Annotated[int, Parameter(validator=(Number(lt=2147483648, lte=None, gt=None, gte=-2147483648, modulo=None),))]
- cyclopts.types.UInt64
An unsigned 64-bit integer.
alias of
Annotated[int, Parameter(validator=(Number(lt=18446744073709551616, lte=None, gt=None, gte=0, modulo=None),))]
- cyclopts.types.HexUInt64
An unsigned 64-bit integer who's default value will be displayed as hexadecimal in the help-page.
- cyclopts.types.Int64
A signed 64-bit integer.
alias of
Annotated[int, Parameter(validator=(Number(lt=9223372036854775808, lte=None, gt=None, gte=-9223372036854775808, modulo=None),))]
Json
Annotated types for parsing a json-string from the CLI.
- cyclopts.types.Json
Parse a json-string from the CLI.
Note: Since Cyclopts v3.6.0, all dataclass-like classes now natively attempt to parse json-strings, so practical use-case of this annotation is limited.
Usage example:
from cyclopts import App, types app = App() @app.default def main(json: types.Json): print(json) app()
$ my-script '{"foo": 1, "bar": 2}' {'foo': 1, 'bar': 2}
Web
Annotated types for common web-related values.
- cyclopts.types.Email
An email address string with simple validation.
- cyclopts.types.Port
An
intlimited to range[0, 65535].alias of
Annotated[int, Parameter(validator=(Number(lt=None, lte=65535, gt=None, gte=0, modulo=None),))]
- cyclopts.types.URL
A
strURL string with some simple validation.
Help Formatting
Cyclopts provides a flexible help formatting system for customizing the help-page's appearance.
- class cyclopts.help.protocols.HelpFormatter(*args, **kwargs)
Protocol for help formatter functions.
It's the Formatter's job to transform a
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.""" ...
- class cyclopts.help.DefaultFormatter(*, panel_spec: PanelSpec | None = None, table_spec: TableSpec | None = None, column_specs: tuple[ColumnSpec, ...] | ColumnSpecBuilder | None = None)
Default help formatter using Rich library with customizable specs.
- Parameters:
panel_spec (Optional[PanelSpec]) -- Panel specification for the outer box/panel styling.
table_spec (Optional[TableSpec]) -- Table specification for table styling (borders, padding, etc).
column_specs (Optional[Union[tuple[ColumnSpec, ...], ColumnSpecBuilder]]) -- Column specifications or builder function for table columns.
Notes
The relationship between these specs can be visualized as:
╭─ Commands ───────────────────────────────────────────────────────╮ ← panel_spec │ serve Start the development server │ (border, title) │ --help Display this message and exit. │ ╰──────────────────────────────────────────────────────────────────╯ ↑ ↑ col[0] col[1] (name) (description) ╭─ Parameters ─────────────────────────────────────────────────────╮ ← panel_spec │ * PORT --port Server port number [required] │ │ VERBOSE --verbose Enable verbose output [default: False] │ ╰──────────────────────────────────────────────────────────────────╯ ↑ ↑ ↑ │ col[1] col[2] │ (name/flags) (description) │ col[0] (required marker)
Where:
panel_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)
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
Format and render a single help panel using Rich.
- Parameters:
console (Console) -- Console to render to.
options (ConsoleOptions) -- Console rendering options.
panel (HelpPanel) -- Help panel to render.
- render_usage(console: Console, options: ConsoleOptions, usage: Any) None
Render the usage line.
- Parameters:
console (Console) -- Console to render to.
options (ConsoleOptions) -- Console rendering options.
usage (Any) -- The usage line (Text or str).
- render_description(console: Console, options: ConsoleOptions, description: Any) None
Render the description.
- Parameters:
console (Console) -- Console to render to.
options (ConsoleOptions) -- Console rendering options.
description (Any) -- The description (can be various Rich renderables).
- class cyclopts.help.PlainFormatter(indent_width: int = 2, max_width: int | None = None)
Plain text formatter for improved accessibility.
- Parameters:
indent_width (int) -- Number of spaces to indent entries (default: 2).
max_width (Optional[int]) -- Maximum line width for wrapping text.
- __call__(console: Console, options: ConsoleOptions, panel: HelpPanel) None
Format and render a single help panel as plain text.
- Parameters:
console (Console) -- Console to render to.
options (ConsoleOptions) -- Console rendering options.
panel (HelpPanel) -- Help panel to render.
- render_usage(console: Console, options: ConsoleOptions, usage: Any) None
Render the usage line.
- Parameters:
console (Console) -- Console to render to.
options (ConsoleOptions) -- Console rendering options.
usage (Any) -- The usage line (Text or str).
- render_description(console: Console, options: ConsoleOptions, description: Any) None
Render the description.
- Parameters:
console (Console) -- Console to render to.
options (ConsoleOptions) -- Console rendering options.
description (Any) -- The description (can be various Rich renderables).
- class cyclopts.help.protocols.ColumnSpecBuilder(*args, **kwargs)
Protocol for ColumnSpecBuilders.
- __call__(console: Console, options: ConsoleOptions, entries: list[HelpEntry]) tuple[ColumnSpec, ...]
Build column specifications based on console settings and entries.
- Parameters:
console (Console) -- The Rich console instance.
options (ConsoleOptions) -- Console rendering options.
entries (list[HelpEntry]) -- List of help entries to be displayed.
- Returns:
Tuple of column specifications for table rendering.
- Return type:
tuple[ColumnSpec, ...]
- class cyclopts.help.PanelSpec(title: RenderableType | None = None, subtitle: RenderableType | None = None, title_align: Literal['left', 'center', 'right'] = 'left', subtitle_align: Literal['left', 'center', 'right'] = 'center', style: StyleType | None = 'none', border_style: StyleType | None = 'none', box: Box | None = None, padding: PaddingDimensions = (0, 1), expand: bool = True, width: int | None = None, height: int | None = None, safe_box: bool | None = None, highlight: bool = False)
Specification for panel (outer box) styling.
Used by
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.
- build(renderable: RenderableType, **overrides) Panel
Create a Panel around renderable. Use kwargs to override spec per render.
- copy(**kwargs)
- class cyclopts.help.TableSpec(title: str | None = None, caption: str | None = None, style: StyleType | None = None, border_style: StyleType | None = None, header_style: StyleType | None = None, footer_style: StyleType | None = None, box: Box | None = None, show_header: bool = False, show_footer: bool = False, show_lines: bool = False, show_edge: bool = True, expand: bool = False, pad_edge: bool = False, padding: PaddingDimensions = (0, 2, 0, 0), collapse_padding: bool = False, width: int | None = None, min_width: int | None = None, safe_box: bool | None = None)
Specification for table layout and styling.
Used by
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
Construct and populate a rich.Table.
- Parameters:
columns (tuple[ColumnSpec, ...]) -- Column specifications defining the table structure.
entries (Iterable[HelpEntry]) -- Table entries to populate the table with.
**overrides -- Per-render overrides for table settings.
- Returns:
A populated Rich Table.
- Return type:
Table
- copy(**kwargs)
- class cyclopts.help.ColumnSpec(renderer: str | Renderer, header: str = '', footer: str = '', header_style: StyleType | None = None, footer_style: StyleType | None = None, style: StyleType | None = None, justify: Literal['default', 'left', 'center', 'right', 'full'] = 'left', vertical: Literal['top', 'middle', 'bottom'] = 'top', overflow: Literal['fold', 'crop', 'ellipsis', 'ignore'] = 'ellipsis', width: int | None = None, min_width: int | None = None, max_width: int | None = None, ratio: int | None = None, no_wrap: bool = False, highlight: bool | None = None)
Specification for a single column in a help table.
Used by
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().
- copy(**kwargs)
- class cyclopts.help.NameRenderer(max_width: int | None = None)
Renderer for parameter/command names with optional text wrapping.
- Parameters:
max_width (int | None) -- Maximum width for wrapping. If None, no wrapping is applied.
Initialize the renderer with formatting options.
- Parameters:
max_width (int | None) -- Maximum width for wrapping. If None, no wrapping is applied.
- __call__(entry: HelpEntry) RenderableType
Render the names column with optional text wrapping.
- Parameters:
entry (HelpEntry) -- The table entry to render.
- Returns:
Combined names and shorts, optionally wrapped. Order: positive_names, positive_shorts, negative_names, negative_shorts
- Return type:
RenderableType
- class cyclopts.help.DescriptionRenderer(newline_metadata: bool = False)
Renderer for descriptions with configurable metadata formatting.
- Parameters:
newline_metadata (bool) -- If True, display metadata (choices, env vars, defaults) on separate lines. If False (default), display metadata inline with the description.
Initialize the renderer with formatting options.
- Parameters:
newline_metadata (bool) -- If True, display metadata on separate lines instead of inline.
- __call__(entry: HelpEntry) RenderableType
Render parameter description with metadata annotations.
Enriches the base description with choices, environment variables, default values, and required status.
- Parameters:
entry (HelpEntry) -- The table entry to render.
- Returns:
Description with appended metadata.
- Return type:
RenderableType
- class cyclopts.help.AsteriskRenderer
Renderer for required parameter asterisk indicator.
A simple renderer that displays an asterisk (*) for required parameters.
- class cyclopts.help.HelpPanel(format: Literal['command', 'parameter'], title: RenderableType, description: Any | None = None, entries: list[HelpEntry] = NOTHING)
Data container for help panel information.
- format: Literal['command', 'parameter']
Panel format type.
- title: RenderableType
The title text displayed at the top of the help panel.
- description: Any
Optional description text displayed below the title.
Typically a
stror aRenderableType
- copy(**kwargs)
- class cyclopts.help.HelpEntry(*, positive_names: tuple[str, ...] = (), positive_shorts: tuple[str, ...] = (), negative_names: tuple[str, ...] = (), negative_shorts: tuple[str, ...] = (), description: Any = None, required: bool = False, sort_key: Any = None, type: Any | None = None, choices: tuple[str, ...] | None = None, env_var: tuple[str, ...] | None = None, default: str | None = None)
Container for help table entry data.
- positive_names: tuple[str, ...]
Positive long option names (e.g., "--verbose", "--dry-run").
- positive_shorts: tuple[str, ...]
Positive short option names (e.g., "-v", "-n").
- negative_names: tuple[str, ...]
Negative long option names (e.g., "--no-verbose", "--no-dry-run").
- negative_shorts: tuple[str, ...]
Negative short option names (e.g., "-N"). Rarely used.
- property names: tuple[str, ...]
All long option names (positive + negative). For backward compatibility.
- property shorts: tuple[str, ...]
All short option names (positive + negative). For backward compatibility.
- property all_options: tuple[str, ...]
positive longs, positive shorts, negative longs, negative shorts.
- Type:
All options in display order
- description: Any
Help text description for this entry.
Typically a
stror aRenderableType
- required: bool
Whether this parameter/command is required.
- sort_key: Any
Custom sorting key for ordering entries.
- type: Any | None
Type annotation of the parameter.
- choices: tuple[str, ...] | None
Available choices for this parameter.
- env_var: tuple[str, ...] | None
Environment variable names that can set this parameter.
- default: str | None
Default value for this parameter to display. None means no default to show.
- copy(**kwargs)
Config
Cyclopts has builtin configuration classes to be used with App.config for loading user-defined defaults in many common scenarios.
All Cyclopts builtins index into the configuration file with the following rules:
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)
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.
- allow_unknown: bool = False
Allow for unknown keys. Otherwise, if an unknown key is provided, raises
UnknownOptionError.
- use_commands_as_keys: bool = True
Use the sequence of commands as keys into the configuration.
For example, the following CLI invocation:
$ python my-script.py my-command
Would search into
["my-command"]for values.
- class cyclopts.config.Yaml(path, *, root_keys: Iterable[str] = (), allow_unknown: bool = False, use_commands_as_keys: bool = True, source: str | None = None, must_exist: bool = False, search_parents: bool = False)
Automatically read configuration from YAML file.
- path: str | pathlib.Path
Path to YAML configuration file.
- source: str | None = None
Identifier for the configuration source, used in error messages. If not provided, defaults to the absolute path of the configuration file.
- root_keys: Iterable[str] = None
The key or sequence of keys that lead to the root configuration structure for this app. For example, if referencing a common
config.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.
- allow_unknown: bool = False
Allow for unknown keys. Otherwise, if an unknown key is provided, raises
UnknownOptionError.
- use_commands_as_keys: bool = True
Use the sequence of commands as keys into the configuration.
For example, the following CLI invocation:
$ python my-script.py my-command
Would search into
["my-command"]for values.
- class cyclopts.config.Json(path, *, root_keys: Iterable[str] = (), allow_unknown: bool = False, use_commands_as_keys: bool = True, source: str | None = None, must_exist: bool = False, search_parents: bool = False)
Automatically read configuration from Json file.
- path: str | pathlib.Path
Path to JSON configuration file.
- source: str | None = None
Identifier for the configuration source, used in error messages. If not provided, defaults to the absolute path of the configuration file. Can be customized to provide more descriptive error context.
Example:
app = cyclopts.App(config=cyclopts.config.Json("config.json", source="production-config"))
- root_keys: Iterable[str] = None
The key or sequence of keys that lead to the root configuration structure for this app. For example, if referencing a common
config.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.
- allow_unknown: bool = False
Allow for unknown keys. Otherwise, if an unknown key is provided, raises
UnknownOptionError.
- use_commands_as_keys: bool = True
Use the sequence of commands as keys into the configuration.
For example, the following CLI invocation:
$ python my-script.py my-command
Would search into
["my-command"]for values.
- class cyclopts.config.Dict(data: dict[str, Any], *, root_keys: Iterable[str] = (), allow_unknown: bool = False, use_commands_as_keys: bool = True, source: str | None = None)
Configuration source from an in-memory dictionary.
Useful for programmatically generated configurations.
Use an in-memory Python dictionary as configuration source.
- data: dict[str, Any]
The configuration dictionary.
- source: str = "dict"
Identifier for the configuration source, used in error messages.
- root_keys: Iterable[str] = ()
The key or sequence of keys that lead to the root configuration structure for this app.
- allow_unknown: bool = False
Allow for unknown keys. Otherwise, if an unknown key is provided, raises
UnknownOptionError.
- use_commands_as_keys: bool = True
Use the sequence of commands as keys into the configuration.
- class cyclopts.config.Env(prefix: str = '', *, source: str = 'env', command: bool = True, show: bool = True)
Automatically derive environment variable names to read configurations from.
For example, consider the following app:
import cyclopts app = cyclopts.App(config=cyclopts.config.Env("MY_SCRIPT_")) @app.command def my_command(foo, bar): print(f"{foo=} {bar=}") app()
If values for
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_.
- source: str = "env"
Identifier for the configuration source, used in error messages and token tracking. Defaults to
"env".
- show: bool = True
If
True, then show the environment variables on the help-page.
Exceptions
- exception cyclopts.CycloptsError
Bases:
ExceptionRoot exception for runtime errors.
As CycloptsErrors bubble up the Cyclopts call-stack, more information is added to it.
- msg: str | None
If set, override automatic message generation.
- verbose: bool
More verbose error messages; aimed towards developers debugging their Cyclopts app. Defaults to
False.
- unused_tokens: list[str] | None
Leftover tokens after parsing is complete.
- target: Callable | None
The python function associated with the command being parsed.
- command_chain: Sequence[str] | None
List of command that lead to
target.
- console: Console | None
Consoleto display runtime errors.
- exception cyclopts.ValidationError
Bases:
CycloptsErrorValidator function raised an exception.
- exception_message: str
Parenting Assertion/Value/Type Error message.
- value: Any
Converted value that failed validation.
- exception cyclopts.UnknownOptionError
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
Bases:
CycloptsErrorThere was an error performing automatic type coercion.
- target_type: type | None
Intended type to coerce into.
- exception cyclopts.UnknownCommandError
Bases:
CycloptsErrorCLI token combination did not yield a valid command.
- msg: str | None
If set, override automatic message generation.
- verbose: bool
More verbose error messages; aimed towards developers debugging their Cyclopts app. Defaults to
False.
- unused_tokens: list[str] | None
Leftover tokens after parsing is complete.
- target: Callable | None
The python function associated with the command being parsed.
- command_chain: Sequence[str] | None
List of command that lead to
target.
- app: 'App' | None
The Cyclopts application itself.
- console: 'Console' | None
Consoleto display runtime errors.
- exception cyclopts.UnusedCliTokensError
Bases:
CycloptsErrorNot all CLI tokens were used as expected.
- exception cyclopts.MissingArgumentError
Bases:
CycloptsErrorA required argument was not provided.
- tokens_so_far: list[str]
If the matched parameter requires multiple tokens, these are the ones we have parsed so far.
- keyword: str | None
The keyword that was used when the error was raised (e.g., '-o' instead of '--option').
- exception cyclopts.ConsumeMultipleError
Bases:
MissingArgumentErrorThe number of values provided doesn't meet consume_multiple constraints.
- min_required: int
- max_allowed: int | None
- actual_count: int
- exception cyclopts.RequiresEqualsError
Bases:
CycloptsErrorA long option requires
=to assign a value (e.g.,--option=value).- keyword: str | None
The keyword that was used (e.g., '--name').
- exception cyclopts.RepeatArgumentError
Bases:
CycloptsErrorThe same parameter has erroneously been specified multiple times.
- exception cyclopts.MixedArgumentError
Bases:
CycloptsErrorCannot supply keywords and non-keywords to the same argument.
- exception cyclopts.CommandCollisionError
Bases:
ExceptionA command with the same name has already been registered to the app.
- exception cyclopts.CombinedShortOptionError
Bases:
CycloptsErrorCannot combine short, token-consuming options with short flags.
- exception cyclopts.EditorError
Bases:
ExceptionRoot editor-related error.
Root exception raised by all exceptions in
edit().
- exception cyclopts.EditorNotFoundError
Bases:
EditorErrorCould not find a valid text editor for :func`.edit`.
- exception cyclopts.EditorDidNotSaveError
Bases:
EditorErrorUser did not save upon exiting
edit().
- exception cyclopts.EditorDidNotChangeError
Bases:
EditorErrorUser did not edit file contents in
edit().