sphinx-source-tree

Ship entire project source code and directory tree with your Sphinx documentation.

PyPI Version Supported Python versions Build Status Documentation Status llms.txt - documentation for LLMs MIT Coverage

Generate a reStructuredText (.rst) file that contains:

  1. An ASCII directory tree of your project.

  2. A literalinclude directive for every source file you select.

The result is a single .rst document ready to be included in a Sphinx documentation build, specifically for the llms.txt, providing full project context for LLMs.

Prerequisites

Python 3.10+

Installation

uv pip install sphinx-source-tree

Usage

Quick start

Run in your project root:

sphinx-source-tree

This writes docs/source_tree.rst with the full tree and literalinclude blocks for .js, .json, .md, .py, .rst, .toml, .yaml and .yml files.

Print to stdout instead:

sphinx-source-tree --stdout

CLI reference

sphinx-source-tree [OPTIONS]
-p, --project-root PATH

Project directory. Default: current directory.

-d, --depth N

Maximum tree depth. Default: 10.

-o, --output PATH

Output .rst file. Default: docs/source_tree.rst.

-e, --extensions EXT [EXT ...]

File suffixes to include via literalinclude. Default: .js .json .md .py .rst .toml .yaml .yml.

-i, --ignore PAT [PAT ...]

Glob patterns to ignore (matched against both the relative path and the bare file name).

-w, --whitelist DIR [DIR ...]

Restrict output to these directories. Ignored when --include-all is active.

--include-all / --no-include-all

Include everything regardless of whitelist. Default: on.

-t, --title TEXT

RST section title. Default: Project source-tree.

--linenos / --no-linenos

Attach :linenos: to literalinclude directives. Default: off.

--stdout

Write to stdout instead of the output file.

-V, --version

Show version and exit.

Configuration via pyproject.toml

All CLI options (except --stdout and --version) can be set under [tool.sphinx-source-tree] in your project’s pyproject.toml. CLI arguments always take precedence.

Single-file example:

[tool.sphinx-source-tree]
depth = 4
output = "docs/source_tree.rst"
extensions = [".py", ".rst", ".toml"]
ignore = ["__pycache__", "*.pyc", ".git", "*.egg-info"]
whitelist = ["src", "docs"]
include-all = false
title = "Source listing"
linenos = true
extra-languages = {".vue" = "vue", ".svelte" = "svelte"}

Key names use hyphens (include-all) to follow TOML/PEP 621 convention; they are normalised internally.

Multiple output files

You can generate several .rst files in one run by adding [[tool.sphinx-source-tree.files]] entries. Top-level settings act as shared defaults; each entry can override any of them.

[tool.sphinx-source-tree]
# Shared defaults — applied to every file unless overridden
depth = 10
ignore = ["__pycache__", "*.pyc", ".git", "*.egg-info"]
linenos = false

[[tool.sphinx-source-tree.files]]
output = "docs/source_tree.rst"
title = "Full project source"
# inherits depth, ignore, linenos from the section above

[[tool.sphinx-source-tree.files]]
output = "docs/api_tree.rst"
title = "API source"
extensions = [".py"]
whitelist = ["src"]
include-all = false
depth = 5            # overrides the shared default

[[tool.sphinx-source-tree.files]]
output = "docs/docs_tree.rst"
title = "Documentation files"
extensions = [".rst", ".md"]
whitelist = ["docs"]
include-all = false

The merge priority is: built-in defaults < top-level ``[tool.sphinx-source-tree]`` < per-file ``[[…files]]`` entry < CLI arguments.

When no [[files]] entries are present the tool behaves exactly as before, so existing configurations are fully backward compatible.

Per-file inclusion options

You can restrict how much of each file is shown by attaching Sphinx literalinclude range options to individual files. The following options are supported:

  • :lines: — explicit line numbers or ranges (e.g. 1-20, 30)

  • :start-at: — include from the first line that contains the marker

  • :start-after: — include from the line after the marker

  • :end-before: — include up to, but not including, the marker line

  • :end-at: — include up to and including the marker line

Via pyproject.toml (flat)

Add a [tool.sphinx-source-tree.file-options] table whose keys are file paths relative to the project root. This mapping is used by all output files that do not select a named profile:

[tool.sphinx-source-tree.file-options]
"src/app.py" = {"end-before" = "# *** Tests ***"}
"src/utils.py" = {"start-after" = "# -- public API --"}
"src/models.py" = {"lines" = "1-60"}

This produces literalinclude blocks such as:

.. literalinclude:: ../src/app.py
   :language: python
   :caption: src/app.py
   :end-before: # *** Tests ***

Option keys may be written with either hyphens (end-before) or underscores (end_before); both are accepted and normalised to the hyphenated form that Sphinx expects. Unknown option keys emit a warning to stderr and are ignored.

Via pyproject.toml (named profiles)

When you need different inclusion rules for different output files — for example a full source tree and a compact one for LLMs — define named profiles under [tool.sphinx-source-tree.file-options-profiles] and select one per [[files]] entry with file-options-profile:

[tool.sphinx-source-tree]
ignore = ["__pycache__", "*.pyc", ".git"]

# "full" profile — no restrictions (empty table = include everything)
[tool.sphinx-source-tree.file-options-profiles.full]

# "compact" profile — trim each file at its test boundary
[tool.sphinx-source-tree.file-options-profiles.compact]
"src/app.py" = {"end-before" = "# ********** Tests **********"}
"src/models.py" = {"end-before" = "# ********** Tests **********"}
"src/utils.py" = {"lines" = "1-60"}

[[tool.sphinx-source-tree.files]]
output = "docs/source_tree_full.rst"
title = "Full project source"
file-options-profile = "full"

[[tool.sphinx-source-tree.files]]
output = "docs/source_tree.rst"
title = "Compact source for LLMs"
file-options-profile = "compact"

Resolution order:

  1. If file-options-profile names a key in file-options-profiles, that profile’s mapping is used.

  2. If the name is not found, a warning is printed to stderr and the tool falls back to the top-level file-options table.

  3. If no profile is specified, the top-level file-options table is used directly (fully backward compatible).

Via the Python API

Pass the file_options keyword argument to generate() with the already-resolved mapping for that output file. Profile selection happens in _generate_from_cfg; when calling generate() directly simply pass whichever dict applies:

from pathlib import Path
from sphinx_source_tree import generate

compact_options = {
    "src/app.py": {"end-before": "# *** Tests ***"},
    "src/utils.py": {"start-after": "# -- public API --"},
}

rst = generate(
    project_root=Path("."),
    output=Path("docs/source_tree2.rst"),
    file_options=compact_options,
)

Absolute paths are also accepted as keys and are resolved relative to project_root automatically.

Python API

You can also call the generator from Python:

from pathlib import Path
from sphinx_source_tree import generate

rst = generate(
    project_root=Path("."),
    output=Path("docs/source_tree1.rst"),
    depth=5,
    extensions=[".py", ".rst"],
    ignore=["__pycache__", "*.pyc"],
    title="My project source",
)
Path("docs/source_tree.rst").write_text(rst)

generate() returns the RST content as a string and never writes to disk, so you can post-process or redirect as needed.

Lower-level helpers are also importable:

  • build_tree() – ASCII tree string.

  • collect_files() – list of Path objects to include.

  • detect_language() – suffix-to-Sphinx-language mapping.

  • load_config() – read [tool.sphinx-source-tree] from pyproject.toml.

Documentation

Tests

Run the tests:

pytest -vvv

Writing documentation

Keep the following hierarchy.

=====
title
=====

header
======

sub-header
----------

sub-sub-header
~~~~~~~~~~~~~~

sub-sub-sub-header
^^^^^^^^^^^^^^^^^^

sub-sub-sub-sub-header
++++++++++++++++++++++

sub-sub-sub-sub-sub-header
**************************

License

MIT

Support

For security issues contact me at the e-mail given in the Author section.

For overall issues, go to GitHub.

Author

Artur Barseghyan <artur.barseghyan@gmail.com>

Project documentation

Contents: