Sphinx Integration
Cyclopts provides builtin Sphinx support.
Quick Start
Add the extension to your Sphinx configuration (
docs/conf.py):extensions = [ 'cyclopts.sphinx_ext', # Add this line # ... your other extensions ]
Use the directive in your RST files:
.. cyclopts:: mypackage.cli:app
Directive Usage
Basic Syntax
The cyclopts directive accepts a module path to your Cyclopts App object:
.. cyclopts:: mypackage.cli:app
Module Path Formats
The directive accepts two module path formats:
Explicit format (
module.path:app_name):.. cyclopts:: mypackage.cli:app .. cyclopts:: myapp.commands:main_app .. cyclopts:: src.cli:cli
This explicitly specifies which
Appobject to document.Automatic discovery (
module.path):.. cyclopts:: mypackage.cli .. cyclopts:: myapp.main
The extension will search the module for an
Appinstance, looking for common names likeapp,cli, ormain.
Directive Options
The directive supports several options to customize the generated documentation:
:heading-level: - Heading Level
Set the starting heading level for the generated documentation (1-6, default: 2):
.. cyclopts:: mypackage.cli:app
:heading-level: 3
This is useful when you need to adjust the heading hierarchy. The default of 2 works well for most cases where the directive is placed under a page title.
:max-heading-level: - Maximum Heading Level
Set the maximum heading level to use (1-6, default: 6):
.. cyclopts:: mypackage.cli:app
:max-heading-level: 4
Headings deeper than this level will be capped at this value. This is useful for deeply nested command hierarchies where you want to prevent headings from becoming too small.
:no-recursive: - Exclude Subcommands
Disable recursive documentation of subcommands (by default, subcommands are included):
.. cyclopts:: mypackage.cli:app
:no-recursive:
When this flag is present, only the top-level commands are documented.
:flatten-commands: - Generate Flat Command Hierarchy
Generate all commands at the same heading level instead of nested hierarchy:
.. cyclopts:: mypackage.cli:app
:flatten-commands:
This creates distinct, equally-weighted headings for each command and subcommand, making them easier to reference and navigate in the documentation. Without this option, subcommands are nested with incrementing heading levels.
:code-block-title: - Render Titles as Inline Code
Render command titles with inline code formatting instead of plain text:
.. cyclopts:: mypackage.cli:app
:code-block-title:
When this flag is present, command titles are rendered with monospace formatting, which can be useful for certain documentation themes or to make command names stand out visually.
:commands: - Filter Specific Commands
Document only specific commands from your CLI application:
.. cyclopts:: mypackage.cli:app
:commands: init, build, deploy
This will only document the specified commands. You can also use nested command paths with dot notation:
.. cyclopts:: mypackage.cli:app
:commands: db.migrate, db.backup, api
db.migrate- Documents only themigratesubcommand underdbdb.backup- Documents only thebackupsubcommand underdbapi- Documents theapicommand and all its subcommands
You can use either underscore or dash notation in command names - they will be normalized automatically.
:exclude-commands: - Exclude Specific Commands
Exclude specific commands from the documentation:
.. cyclopts:: mypackage.cli:app
:exclude-commands: debug, internal-test
This is useful for hiding internal or debug commands from user-facing documentation. Like :commands:, this also supports nested command paths with dot notation.
:skip-preamble: - Skip Description and Usage
Skip the description and usage sections for the target command when filtering to a single command:
.. cyclopts:: mypackage.cli:app
:commands: deploy
:skip-preamble:
When you filter to a single command using :commands: and provide your own section heading in the RST, you may not want the directive to generate the command's description and usage block. Adding :skip-preamble: suppresses these sections while still generating the command's parameters and subcommands.
This is useful when you want to write your own introduction for a command section:
Deployment
==========
Deploy your application to production with these commands.
.. cyclopts:: mypackage.cli:app
:commands: deploy
:skip-preamble:
Without :skip-preamble:, the output would include both your introduction and the command's docstring description, which can be redundant.
:usage-name: - Override the Command Shown in Usage Lines
Replace the app name shown in Usage: lines of the generated documentation with a custom invocation string:
.. cyclopts:: mypackage.cli:app
:usage-name: uv run cli
This is useful when the documented invocation differs from the app's configured name. For example, an App(name="cli", ...) installed as a project entry point might typically be invoked as uv run cli; setting :usage-name: uv run cli renders that in every Usage: block while section headings, anchors, and the table of contents continue to reference the plain cli name.
Automatic Reference Labels
The Sphinx directive automatically generates RST reference labels for all commands, enabling cross-referencing throughout your documentation. The anchor format is cyclopts-{app-name}-{command-path}, which prevents naming conflicts when documenting multiple CLIs.
For example:
- Root application: cyclopts-myapp
- Subcommand: cyclopts-myapp-deploy
- Nested subcommand: cyclopts-myapp-deploy-production
You can reference these commands elsewhere in your documentation using :ref:`cyclopts-myapp-deploy`.
Complete Example
Here's a complete example showing a CLI application and its Sphinx documentation:
CLI Application (myapp/cli.py):
from pathlib import Path
from typing import Optional
from cyclopts import App
app = App(
name="myapp",
help="My awesome CLI application",
version="1.0.0"
)
@app.command
def init(path: Path = Path("."), template: str = "default"):
"""Initialize a new project.
Parameters
----------
path : Path
Directory where the project will be created
template : str
Project template to use
"""
print(f"Initializing project at {path}")
@app.command
def build(source: Path, output: Optional[Path] = None, *, minify: bool = False):
"""Build the project.
Parameters
----------
source : Path
Source directory
output : Path, optional
Output directory (defaults to source/dist)
minify : bool
Minify the output files
"""
output = output or source / "dist"
print(f"Building from {source} to {output}")
if __name__ == "__main__":
app()
Sphinx Configuration (docs/conf.py):
import sys
from pathlib import Path
# Add your package to the path
sys.path.insert(0, str(Path(__file__).parent.parent))
# Extensions
extensions = [
'cyclopts.sphinx_ext',
'sphinx.ext.autodoc', # For API docs
'sphinx.ext.napoleon', # For NumPy-style docstrings
]
# Project info
project = 'MyApp'
author = 'Your Name'
version = '1.0.0'
# HTML theme
html_theme = 'sphinx_rtd_theme'
Documentation File (docs/cli.rst):
CLI Reference
=============
This section documents all available CLI commands.
.. cyclopts:: myapp.cli:app
The above directive will automatically generate documentation for all
commands, including their parameters, types, defaults, and help text.
Advanced Usage
Using Distinct Command Headings
When you want each command to have its own distinct heading for better navigation and referencing:
CLI Command Reference
=====================
.. cyclopts:: myapp.cli:app
:flatten-commands:
:code-block-title:
This generates:
- All commands at the same heading level (not nested)
- Command titles with monospace formatting
- Automatic reference labels for cross-linking
You can then reference specific commands:
See :ref:`cyclopts-myapp-deploy` for deployment options.
The :ref:`cyclopts-myapp-init` command sets up your project.
Selective Command Documentation
Split your CLI documentation across multiple sections or pages:
Database Commands
=================
The following commands manage database operations:
.. cyclopts:: myapp.cli:app
:commands: db
API Management
==============
Commands for controlling the API server:
.. cyclopts:: myapp.cli:app
:commands: api
Development Tools
=================
Utilities for development (excluding internal debug commands):
.. cyclopts:: myapp.cli:app
:commands: dev
:exclude-commands: dev.debug, dev.internal
This approach allows you to:
Organize large CLI applications into logical sections
Document different command groups on separate pages
Exclude internal or debug commands from user documentation
Create targeted documentation for different audiences
Output Formats
While the Sphinx directive uses RST internally, you can also generate documentation programmatically in multiple formats:
from myapp.cli import app
# Generate reStructuredText
rst_docs = app.generate_docs(output_format="rst")
# Generate Markdown
md_docs = app.generate_docs(output_format="markdown")
# Generate HTML
html_docs = app.generate_docs(output_format="html")
This is useful for generating documentation outside of Sphinx, such as for GitHub README files or other documentation systems.
See Also
Help - Customizing help output
Commands - Creating commands and subcommands
Parameters - Parameter types and validation
Sphinx Documentation - Official Sphinx documentation