treedocs is a Swift CLI that keeps a version-controlled architectural map of a repository in treedocs.yaml. It mirrors the filesystem, stores human-readable descriptions, and helps detect documentation drift.
- Scans a repository into a nested YAML tree
- Treats nested
treedocs.yamlfiles as documentation boundaries for delegated subtrees - Stores project metadata, documentation, references, and internal links
- Defines the
treedocs.yamlcontract with JSON Schema for reusable validation - Reconciles disk changes back into the YAML state
- Imports folder and README-file documentation from
README.mdYAML frontmatter - Fails CI-style checks when the tree is stale or descriptions are missing
- Renders a documented tree and resolves links for inspection
- Finds relevant paths from a query for shell workflows
treedocs currently supports macOS 13 and newer. Windows and Linux are not supported yet; please open a GitHub issue if you want either platform supported.
GitHub Releases are the canonical release record. Package-manager distribution builds from source instead of shipping prebuilt binaries, so installing through Homebrew, Mint, or mise requires a Swift 6.2-capable build environment.
From a local checkout:
swift run treedocs --helpOr build a release binary:
swift build -c release
.build/release/treedocs --helpInstall or run the released CLI with Mint:
mint install DandyLyons/treedocs@0.2.0
mint run DandyLyons/treedocs@0.2.0 --helpMint builds Swift executable packages from source and links installed tools through its configured Mint bin path.
Homebrew distribution uses the dedicated DandyLyons/homebrew-tap repository, which can host formulae for multiple DandyLyons tools.
Install with Homebrew:
brew install DandyLyons/tap/treedocsDevelopment builds from main are also available:
brew install DandyLyons/tap/treedocs --HEADInstall the released CLI with mise's Swift Package Manager backend:
MISE_EXPERIMENTAL=true mise use -g spm:DandyLyons/treedocs@0.2.0To track the latest release:
MISE_EXPERIMENTAL=true mise use -g spm:DandyLyons/treedocsmise uses SwiftPM artifact bundles when releases publish them. treedocs does not currently ship prebuilt artifact bundles, so mise builds from source. The mise spm: backend is currently experimental, so set MISE_EXPERIMENTAL=true when installing.
treedocs init
treedocs sync
treedocs check
treedocs inspect Sources/treedocs --recursive
treedocs update README.md "Project overview"
treedocs update Sources/treedocs/Core --add-reference DOCS/schema-cli-usage.md
treedocs createDoc Sources/treedocs/Core/
treedocs createDoc Sources/ --recursive
treedocs show . --full-descriptions
treedocs explore Sources/ --full-descriptions
treedocs ls
treedocs ls Sources/treedocs
treedocs path renderershow and explore truncate long descriptions by default. Use --full-descriptions or -f to render complete descriptions for files and folders.
Run treedocs --help for the full command surface.
Commands with interactive workflows open terminal UI by default when stdin and stdout are attached to a TTY. For example, treedocs sync lets you fill missing descriptions before saving when it is run from an interactive terminal.
Use -n, --non-interactive to opt out explicitly in scripts or local automation:
treedocs sync --non-interactive
treedocs sync -nNon-TTY contexts, such as CI and redirected input/output, skip interactive UI automatically.
Schema 0.3.0-WIP adds exact-folder documentation source overrides:
schema_version: 0.3.0-WIP
overrides:
documentation_sources:
.github/: FOLDER.md
.: PROJECT.mdEach value is a filename inside that folder. Overrides never inherit: .github/workflows/ still uses README.md. A coexisting README.md remains an ordinary tree entry and contributes no frontmatter. Explicit missing or excluded sources are errors; use treedocs createDoc .github/ to create a missing source. Configuration changes never rename or delete files.
The Markdown contract is separate from the state schema: file: describes the selected file, and legacy readme: remains accepted with every supported state version. If both occur, their supported metadata must agree; otherwise reconcile them manually before running treedocs. Updates preserve existing key spellings. New stubs use file:.
createREADME and --populate-readmes remain aliases for createDoc and --populate-docs. See the staging contract for details.
treedocs init and treedocs sync discover selected documentation filenames (implicitly README.md) through the normal scanner, so ignore rules and nested treedocs.yaml boundaries still apply. A nested README can document both its containing folder and the README file:
---
description: Core scanning and reconciliation logic.
references:
- ../../DOCS/architecture.md
file:
description: How the core implementation is organized.
references:
- "[Architecture](../../DOCS/architecture.md)"
tree:
ReadmeDocumentation.swift:
description: Parses and reconciles supported README frontmatter.
Persistence:
_doc:
description: Transactional storage infrastructure.
TransactionalFileWriter.swift:
description: Writes coordinated changes with rollback on failure.
---
# CoreTop-level description and references describe the containing folder. Values under file describe the README.md file itself. The optional tree mapping describes any sparse subset of descendants: file metadata appears on the file entry, directory metadata is stored under _doc, and nested mappings may recurse to any depth. Tree paths are relative to the README's folder and cannot escape its subtree.
Local references are resolved relative to the README's folder; HTTPS URLs are preserved. Other frontmatter keys and the Markdown body are retained when treedocs updates supported metadata.
The repository-root README can document its own file through file.*. Root-folder documentation is deferred because the current 0.2.0 tree format has no root _doc entry; top-level folder fields there produce a non-failing warning. _link is not imported from README frontmatter.
When any number of READMEs and treedocs.yaml disagree about the same path and field, interactive sync presents every distinct value once. The selected value is written to treedocs.yaml and every README that already expresses that field. Non-interactive sync reports all conflicts, writes nothing, and exits nonzero. treedocs check reports pending imports and conflicts without modifying files.
README trees remain sparse by default: an omitted descendant means that README has no opinion and is not treated as a deletion. Explicitly populate missing descriptions from the resolved treedocs.yaml tree with one of these scopes:
treedocs sync --populate-docs children
treedocs sync --populate-docs recursivechildren adds immediate child descriptions and recursive adds every owned descendant description. Population applies only to recognized READMEs that already contain supported treedocs frontmatter; it never introduces frontmatter into a plain README. Ignore rules and nested treedocs.yaml ownership boundaries still apply. A recognized README without a usable file.description receives a sensible file-description default in treedocs.yaml.
Materialize existing directory documentation from treedocs.yaml as a structured README stub:
treedocs createDoc Sources/treedocs/Core/
treedocs createDoc Sources/ --recursivecreateDoc copies a documented nested folder's non-blank description and de-duplicated references into top-level frontmatter, makes local references relative to the generated README, and always adds a deterministic file.description plus a level-one directory heading. A root README uses the project name and only file.* metadata because the current schema has no root-folder _doc.
Recursive creation includes the requested directory, respects the standard excludes and configured ignore files, and stops below nested treedocs.yaml boundaries. Existing exact selected source files are skipped without being read or changed. Direct targets below a nested root must use that root with --path. All output is rolled back if a later creation fails, treedocs.yaml remains unchanged, and the command recommends treedocs sync after it creates files.
treedocs can run from a Git pre-commit hook so commits stop when treedocs.yaml is stale or incomplete. This repository vends a suggested hook at contrib/hooks/pre-commit; users are responsible for reviewing and installing it in their own repositories.
Install the suggested hook for the current repository:
install -m 755 contrib/hooks/pre-commit .git/hooks/pre-commitThe hook runs:
treedocs sync --non-interactivetreedocs sync --non-interactive reconciles fixable filesystem drift without opening terminal UI. If sync changes treedocs.yaml, the hook stops the commit so you can review and stage the updated state:
git add treedocs.yaml
git committreedocs sync also reports remaining issues such as missing descriptions after reconciliation. Git hooks block commits when a command exits non-zero; treedocs validation commands use non-zero exits for blocking issues when check_severity resolves to error, which is the default.
Set TREEDOCS_BIN if the executable is not available as treedocs on PATH:
TREEDOCS_BIN=/path/to/treedocs git committreedocs uses Rainbow for ANSI-styled terminal output. Rainbow enables colors for supported TTY output and returns plain text for unknown output targets, such as most redirected output.
Rainbow also respects standard color environment controls: set NO_COLOR to disable color output, or FORCE_COLOR to force color output. treedocs does not currently provide a dedicated --no-color flag.
treedocs.yaml contains:
schema_version: the semver treedocs file-format schema versionproject: metadata such asname,version, andlast_updatedoverrides: project-local config overridessignature: a deterministic structural hash of the scanned treetree: the documented filesystem mirror
The YAML format is defined by a canonical JSON Schema so the CLI, tests, editors, CI workflows, and external agents can validate the same structure. Generated files include a managed YAML language-server header comment that points editor tooling at the matching public schema URL. treedocs regenerates this header whenever it saves treedocs.yaml; arbitrary YAML comments are not preserved.
schema_version identifies the treedocs.yaml file-format schema and follows semver, such as 0.2.0. project.version is different: it is the documented project's own version and is not used to resolve the treedocs schema.
Directory entries use _doc for their description. Object-form metadata uses _description and _references. Entries can also include _link. Compact string descriptions are still valid.
YAML comments in treedocs.yaml, other than the managed language-server schema header, are not preserved when the CLI loads and rewrites the file. Store durable notes as descriptions or references instead of comments.
Example:
# yaml-language-server: $schema=https://dandylyons.github.io/treedocs/schemas/0.2.0/treedocs.schema.json
schema_version: "0.2.0"
project:
name: treedocs
version: 0.0.0
last_updated: 2026-04-30
signature: sha256:...
tree:
Sources:
_doc: Source files for the CLI
treedocs:
Core:
_doc:
_description: Core scanning, rendering, and config logic
_references:
- DOCS/schema-cli-usage.md
README.md: Project overviewConfiguration is merged in this order:
- Built-in defaults
~/.config/treedocs/config.yaml.treedocs/config.yamltreedocs.yamloverrides
Supported config areas include:
- Ignore behavior:
exclude,use_gitignore - Rendering:
max_description_length,indent_size,align_columns - Validation:
check_severity,auto_init_empty - UI/metadata:
theme,icons,ai_provider,ai_model
Ignore sources are combined from:
- Standard excludes such as
.git,.build,.swiftpm,.treedocs,.agents,.opencode, andnode_modules .gitignore.treedocs/.treedocs_ignore
When a child folder contains its own treedocs.yaml, that file owns documentation for the child folder's descendants. The parent scan still records the child folder as a directory, but it does not recursively include the child's files or subdirectories.
For example, if Vendor/Plugin/treedocs.yaml exists, the parent treedocs.yaml owns Vendor/Plugin/ as a delegated directory entry while Vendor/Plugin/treedocs.yaml owns Vendor/Plugin/Sources/ and other descendants.
The project site is deployed to https://dandylyons.github.io/treedocs/ from the static files in site/.
GitHub Pages is published by the Deploy GitHub Pages workflow in .github/workflows/pages.yml. The workflow uses GitHub Actions deployment rather than branch or folder publishing, so Pages configuration and deployment behavior stay version controlled.
The canonical JSON Schema is stored in the public versioned site path at site/schemas/0.2.0/treedocs.schema.json and bundled into the CLI for offline validation. The current schema version is tracked as the semver value CURRENT_TREEDOCS_JSONSCHEMA_VERSION in .env.schema using Varlock syntax. The published schema endpoints are:
https://dandylyons.github.io/treedocs/schemas/0.2.0/treedocs.schema.jsonhttps://dandylyons.github.io/treedocs/schemas/latest/treedocs.schema.json
Versioned schema URLs are immutable after release. The latest endpoint is generated by the Pages workflow during deployment and may move forward when a new schema version is released.
Schema release checklist:
- Add the new immutable schema directory, such as
site/schemas/0.2.0/. - Update the schema
$idto the new versioned public URL. - Update
Package.swiftso the CLI bundles the new versioned schema. - Update
.env.schemaCURRENT_TREEDOCS_JSONSCHEMA_VERSIONsoschemas/latest/treedocs.schema.jsonis copied from the new schema version. - Do not edit already-published versioned schema files after release.
- Run
swift buildand focused schema validation tests locally before release.
swift build
swift test
swift test --filter "Workflow"
swift test --filter "Schema and Config"
swift test --filter "Scanner and Signature"
swift test --filter "IgnoreMatcher"Source layout:
Sources/treedocs/Commands/: CLI subcommandsSources/treedocs/Core/: services and filesystem logicSources/treedocs/Models/: YAML and config modelsTests/treedocsTests/: Swift Testing suites
md-utils is a sister project maintained and designed by the same author. Where treedocs tracks repository structure and path-level documentation, md-utils provides a Swift library, CLI, and Agent Skill for parsing, querying, and rewriting Markdown files.
The two tools are designed to complement each other, and planned integration will connect treedocs repository maps with md-utils Markdown operations.