{"id":849,"library":"cyclopts","title":"Cyclopts","description":"Cyclopts is a modern, easy-to-use command-line interface (CLI) framework built on Python type hints, offering an intuitive and efficient developer experience. It provides advanced type hinting support, rich help page generation from docstrings, and extensive customization options for parsing and launching. The library is actively maintained, currently at version 4.10.1, with frequent updates and ongoing development towards version 5.0.","status":"active","version":"4.10.1","language":"python","source_language":"en","source_url":"https://github.com/BrianPugh/cyclopts","tags":["cli","command-line-interface","type-hints","parser","rich","developer-tool"],"install":[{"cmd":"pip install cyclopts","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Used for generating aesthetically pleasing help pages and formatting exceptions in the console.","package":"rich"},{"reason":"Provides backports of new `typing` features for older Python versions, especially `Annotated`.","package":"typing-extensions"},{"reason":"Enables advanced type hinting support for `attrs` classes.","package":"attrs"},{"reason":"Parses function docstrings (ReST, Google, Numpydoc, Epydoc styles) to automatically generate CLI help text.","package":"docstring-parser"}],"imports":[{"symbol":"App","correct":"from cyclopts import App"},{"note":"Often used with `typing.Annotated` for detailed parameter configuration.","symbol":"Parameter","correct":"from cyclopts import Parameter"},{"note":"A terser API for simple applications with a single command.","symbol":"run","correct":"from cyclopts import run"}],"quickstart":{"code":"from cyclopts import App\n\napp = App()\n\n@app.default\ndef main(name: str, count: int = 1):\n    \"\"\"Greets the given name(s).\n\n    Parameters\n    ----------\n    name: str\n        The name to greet.\n    count: int\n        Number of times to greet.\n    \"\"\"\n    for _ in range(count):\n        print(f\"Hello, {name}!\")\n\nif __name__ == \"__main__\":\n    # Example usage: python your_script.py World --count 3\n    # Or: python your_script.py --help\n    app()\n","lang":"python","description":"This basic example demonstrates creating an `App` instance, registering a default command using the `@app.default` decorator, and defining parameters with type hints. Docstrings are automatically used to generate help messages. The `app()` call parses command-line arguments and executes the corresponding function."},"warnings":[{"fix":"Consult the official Cyclopts v5 migration guide (when available) and update code to reflect new API patterns and behaviors.","message":"Major version 5.x (currently in alpha) is expected to introduce breaking changes. While specific details are not yet fully documented, major version bumps typically involve API alterations. Always review the official migration guide when upgrading to a new major version.","severity":"breaking","affected_versions":">=5.0.0a0"},{"fix":"Replace `typer.Argument`/`typer.Option` with `cyclopts.Parameter`. Re-evaluate default command logic and how `Enum`/`Union` types are handled.","message":"Migrating from Typer: `Argument` and `Option` from `typer` are replaced by `cyclopts.Parameter`. The handling of default actions, callbacks, `Enum` lookups, and `Union` types differs. Cyclopts natively supports `Union` types, unlike Typer.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Be aware of the resolution hierarchy: function-level annotations > group `default_parameter` > app `default_parameter`. Override specific behaviors at the highest-priority level needed.","message":"Parameter Resolution Order: When multiple `Parameter` annotations are applied (e.g., at the function, group, or app level), explicitly set attributes in `Annotated[..., Parameter()]` for a specific function parameter have the highest priority.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always provide explicit type hints (e.g., `value: int`) for function parameters to ensure correct type coercion and prevent unexpected `str` parsing.","message":"Implicit Type Coercion: If a function parameter lacks an explicit type hint, Cyclopts will attempt to infer its type from a non-None default value. If no default is provided, it defaults to `str`. This can lead to unexpected parsing if not explicitly hinted.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Upgrade to Cyclopts v4.8.0 or later. For lazy commands, provide the `help=` argument at registration time (e.g., `app.command('module:command_func', help='Description')`) to display descriptions without triggering imports.","message":"Lazy Loading `--help` Behavior (pre-v4.8.0): Prior to version 4.8.0, running `--help` on a parent command would eagerly import and resolve *all* lazy child commands. This negated the startup-time benefits of lazy loading.","severity":"gotcha","affected_versions":"<4.8.0"},{"fix":"Ensure all required parameters are supplied with their corresponding argument values when invoking a command. Define a default value for parameters if they should be optional.","message":"Required parameters without default values must always be provided with an argument during command invocation. Not supplying a value for a required parameter will result in a runtime error.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T20:21:57.082Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"Adjust the input value to comply with the expected validation criteria or modify the validator function if the criteria are incorrect. For example, if using `cyclopts.validators.Number.range()`, ensure the input falls within the specified range.","cause":"The input value provided for a command-line argument failed a custom or built-in validation rule, even after successful type coercion. Cyclopts re-interprets `ValueError`, `TypeError`, or `AssertionError` into a user-friendly `ValidationError` message.","error":"Invalid value \"200\" for \"AGE\". You are too old to be using this application."},{"fix":"Ensure the command name provided on the command line exactly matches a registered command or check for typos. If the command should be available, verify it has been correctly registered with `@app.command` or that it is the default command using `@app.default`.","cause":"The command-line input specified a command name that has not been registered with the Cyclopts `App` instance using `@app.command` or `@app.default`.","error":"Unknown command \"this-is-not-a-registered-command\""},{"fix":"Modify the command-line input to specify the parameter only once, or adjust the `Parameter` definition in your code to `allow_repeating=True` if the argument is intended to accept multiple values that form a list or similar collection.","cause":"A command-line parameter was provided more than once, and its definition (e.g., in `Parameter(allow_repeating=False)`) does not permit multiple occurrences.","error":"Parameter \"--values\" was specified multiple times."},{"fix":"Verify that the import path (e.g., `nonexistent.module` and `func`) is correct and that the module is accessible within your Python environment. Ensure there are no typos in the module path or the function/App name specified after the colon.","cause":"When using Cyclopts's lazy loading feature for commands (e.g., `app.command(\"module.path:function\")`), the specified Python module or attribute could not be found or imported at the time the command was executed.","error":"ImportError: Cannot import module 'nonexistent.module'."}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"4.11.2","cli_name":"cyclopts","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","installed_version":"3.24.0","pypi_latest":"4.11.2","is_stale":true,"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"cyclopts","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.17,"mem_mb":5.5,"disk_size":"37.3M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"cyclopts","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.2,"mem_mb":5.5,"disk_size":"37.4M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"cyclopts","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3.3,"import_time_s":0.12,"mem_mb":5.5,"disk_size":"38M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"cyclopts","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.12,"mem_mb":5.5,"disk_size":"38M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"cyclopts","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.25,"mem_mb":5.4,"disk_size":"41.1M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"cyclopts","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.3,"mem_mb":5.4,"disk_size":"41.2M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"cyclopts","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3.2,"import_time_s":0.22,"mem_mb":5.4,"disk_size":"42M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"cyclopts","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.25,"mem_mb":5.4,"disk_size":"42M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"cyclopts","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.21,"mem_mb":5.4,"disk_size":"32.5M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"cyclopts","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.23,"mem_mb":5.4,"disk_size":"32.7M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"cyclopts","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3.1,"import_time_s":0.21,"mem_mb":5.4,"disk_size":"33M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"cyclopts","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.26,"mem_mb":5.4,"disk_size":"33M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"cyclopts","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.21,"mem_mb":5.5,"disk_size":"32.3M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"cyclopts","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.23,"mem_mb":5.5,"disk_size":"32.3M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"cyclopts","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3,"import_time_s":0.21,"mem_mb":5.5,"disk_size":"33M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"cyclopts","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.24,"mem_mb":5.5,"disk_size":"33M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"cyclopts","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.19,"mem_mb":5.8,"disk_size":"35.3M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"cyclopts","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.22,"mem_mb":5.8,"disk_size":"35.5M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"cyclopts","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3.6,"import_time_s":0.16,"mem_mb":5.8,"disk_size":"36M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"cyclopts","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":5.8,"disk_size":"36M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}