sphinx-source-tree ****************** Ship entire project source code and directory tree with your Sphinx documentation. [image: PyPI Version][image][image: Supported Python versions][image][image: Build Status][image][image: Documentation Status][image][image: llms.txt - documentation for LLMs][image][image: MIT][image][image: Coverage][image] 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. "--order PATH [PATH ...]" Explicit ordering for the "literalinclude" listing. The files listed here appear **first**, in the given sequence; all remaining collected files follow in their default sorted order. Has no effect on the ASCII directory tree. "--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"} order = ["README.rst", "pyproject.toml", "src/app.py"] 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. Controlling listing order ------------------------- By default, "literalinclude" blocks are emitted in alphabetical order. The "order" option lets you pin specific files to the top of the listing while leaving all other files in their default sorted order. Note: "order" affects only the "literalinclude" source-code listing. The ASCII directory tree is always rendered in its natural sorted order and is unaffected by this setting. **Via** "pyproject.toml" **(top-level)** The top-level "order" list is shared by all output files (or inherited by "[[files]]" entries that do not set their own): [tool.sphinx-source-tree] order = [ "README.rst", "pyproject.toml", "src/app.py", ] **Via** "[[tool.sphinx-source-tree.files]]" Each "[[files]]" entry can define its own "order", which overrides the top-level value for that output file only: [tool.sphinx-source-tree] ignore = ["__pycache__", "*.pyc"] [[tool.sphinx-source-tree.files]] output = "docs/source_tree.rst" title = "Full project source" # no order — uses default alphabetical listing [[tool.sphinx-source-tree.files]] output = "docs/llm_tree.rst" title = "Source for LLMs" order = ["src/core.py", "src/models.py", "src/utils.py"] **Via the CLI** sphinx-source-tree --order src/core.py src/models.py src/utils.py **Via the Python API** Pass the "order" keyword argument to "generate()": from pathlib import Path from sphinx_source_tree import generate rst = generate( project_root=Path("."), output=Path("docs/source_tree_ordered.rst"), extensions=[".py", ".rst"], order=[ "README.rst", "src/app.py", ], ) Path("docs/source_tree_ordered.rst").write_text(rst) Files listed in "order" that do not match any collected file (because they are excluded by extension or ignore rules, or simply do not exist) emit a warning to stderr and are silently skipped. 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 ============= * Documentation is available on Read the Docs. 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 Project documentation ===================== Contents: Table of Contents ^^^^^^^^^^^^^^^^^ * sphinx-source-tree * Prerequisites * Installation * Usage * Quick start * CLI reference * Configuration via pyproject.toml * Multiple output files * Controlling listing order * Per-file inclusion options * Python API * Documentation * Tests * Writing documentation * License * Support * Author * Project documentation * Security Policy * Reporting a Vulnerability * Supported Versions * Contributor guidelines * Developer prerequisites * Code standards * Requirements * Virtual environment * Documentation * Testing * Pull requests * Questions * Issues * Contributor Covenant Code of Conduct * Our Pledge * Our Standards * Enforcement Responsibilities * Scope * Enforcement * Enforcement Guidelines * Attribution * Release history and notes * 0.2.3 * 0.2.2 * 0.2.1 * 0.2 * 0.1 * Package * sphinx_source_tree module * Indices and tables