MkDocs Integration

Cyclopts provides builtin MkDocs support.

Warning

The MkDocs plugin is experimental and may have breaking changes in future releases. If you encounter any issues or have feedback, please report them on GitHub.

Quick Start

  1. Install Cyclopts with MkDocs support:

    pip install cyclopts[mkdocs]
    
  2. Add the plugin to your MkDocs configuration (mkdocs.yml):

    plugins:
      - cyclopts
    
  3. Use the directive in your Markdown files:

    ::: cyclopts
        module: mypackage.cli:app
    

Directive Usage

Basic Syntax

The ::: cyclopts directive uses YAML format and accepts a module path to your Cyclopts App object:

::: cyclopts
    module: mypackage.cli:app

Module Path Formats

The directive accepts two module path formats:

  1. Explicit format (module.path:app_name):

    ::: cyclopts
        module: mypackage.cli:app
    
    ::: cyclopts
        module: myapp.commands:main_app
    
    ::: cyclopts
        module: src.cli:cli
    

    This explicitly specifies which App object to document.

  2. Automatic discovery (module.path):

    ::: cyclopts
        module: mypackage.cli
    
    ::: cyclopts
        module: myapp.main
    

    The plugin will search the module for an App instance, looking for common names like app, cli, or main.

Directive Options

The directive supports several options to customize the generated documentation. All options use standard YAML syntax:

module - Module Path (Required)

The module path to your Cyclopts App instance:

::: cyclopts
    module: mypackage.cli:app

This is the only required option.

heading_level - Heading Level

Set the starting heading level for the generated documentation (1-6, default: 2):

::: cyclopts
    module: 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
    module: 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.

recursive - Include Subcommands

Control whether to document subcommands recursively (default: true):

::: cyclopts
    module: mypackage.cli:app
    recursive: false

Set to false to only document the top-level commands.

include_hidden - Show Hidden Commands

Include commands marked with show=False in the documentation:

::: cyclopts
    module: mypackage.cli:app
    include_hidden: true

By default, hidden commands are not included in the generated documentation.

flatten_commands - Generate Flat Command Hierarchy

Generate all commands at the same heading level instead of nested hierarchy:

::: cyclopts
    module: mypackage.cli:app
    flatten_commands: true

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.

generate_toc - Generate Table of Contents

Control whether to generate a table of contents for multi-command apps (default: true):

::: cyclopts
    module: mypackage.cli:app
    generate_toc: false

This is useful when you want to suppress the automatic table of contents, especially when using multiple directives on the same page or when you have your own navigation structure.

code_block_title - Render Titles as Inline Code

Render command titles with inline code formatting (backticks) instead of plain text:

::: cyclopts
    module: mypackage.cli:app
    code_block_title: true

When enabled, command titles are rendered as #### `command-name` instead of #### command-name. This makes command names appear 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
    module: 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
    module: mypackage.cli:app
    commands:
      - db.migrate
      - db.backup
      - api

Or use inline YAML list syntax:

::: cyclopts
    module: mypackage.cli:app
    commands: [db.migrate, db.backup, api]
  • db.migrate - Documents only the migrate subcommand under db

  • db.backup - Documents only the backup subcommand under db

  • api - Documents the api command 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
    module: 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 and inline YAML list syntax.

skip_preamble - Skip Description and Usage

Skip the description and usage sections for the target command when filtering to a single command:

::: cyclopts
    module: mypackage.cli:app
    commands: [deploy]
    skip_preamble: true

When you filter to a single command using commands and provide your own section heading in the Markdown, you may not want the plugin to generate the command's description and usage block. Setting skip_preamble: true 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
    module: mypackage.cli:app
    commands: [deploy]
    skip_preamble: true

Without skip_preamble, the output would include both your introduction and the command's docstring description, which can be redundant.

Complete Example

Here's a complete example showing a CLI application and its MkDocs 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()

MkDocs Configuration (mkdocs.yml):

site_name: MyApp Documentation
site_description: Documentation for MyApp CLI

theme:
  name: readthedocs

plugins:
  - search
  - cyclopts

nav:
  - Home: index.md
  - CLI Reference: cli-reference.md
  - User Guide: guide.md

markdown_extensions:
  - admonition
  - codehilite
  - toc:
      permalink: true

Documentation File (docs/cli-reference.md):

# CLI Reference

This section documents all available CLI commands.

::: cyclopts
    module: myapp.cli:app
    heading_level: 2
    recursive: true

The above directive will automatically generate documentation for all
commands, including their parameters, types, defaults, and help text.

Advanced Usage

Using Flat Command Structure

When you want each command to have its own distinct heading for better navigation:

# CLI Command Reference

::: cyclopts
    module: myapp.cli:app
    flatten_commands: true

This generates all commands at the same heading level (not nested),
making it easier to navigate and reference specific commands.

Selective Command Documentation

Split your CLI documentation across multiple sections or pages:

## Database Commands

The following commands manage database operations:

::: cyclopts
    module: myapp.cli:app
    commands: [db]
    recursive: true

## API Management

Commands for controlling the API server:

::: cyclopts
    module: myapp.cli:app
    commands: [api]
    recursive: true

## Development Tools

Utilities for development (excluding internal debug commands):

::: cyclopts
    module: myapp.cli:app
    commands: [dev]
    exclude_commands: [dev.debug, dev.internal]
    recursive: true

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

See Also