Skip to main content

tree2guide

License: MIT Python CI PyPI Downloads

Understand your project's structure in seconds.

Generate clean project trees, AI-ready summaries, and reusable documentation from any directory — all with zero dependencies.

Author: Lawrence Roble (@law4percent) Open-source, MIT licensed. Contributions, issues, and pull requests are welcome.


Why this exists

Many developers start building before they’ve had time to study every architectural principle in depth. tree2guide exists to make project structure easier to see, understand, and improve.

It provides a quick way to visualize folder hierarchies, spot signs of architectural drift, and evaluate whether a codebase is maintaining clear separation of concerns — or simply accumulating complexity over time.

What began as a tool for checking project structure quickly became useful for documentation, onboarding, PR descriptions, AI prompts, and general project analysis. The goal, however, remains the same: help developers catch structural problems early, before they become expensive to untangle.

tree2guide starts as a project structure generator, but its long-term vision is to become the foundation for project understanding — providing structured representations that can power documentation, analysis, automation, and intelligent developer tools.


Why not just use tree?

Feature tree tree2guide
Markdown output ❌ ✅
HTML output (collapsible) ❌ ✅
JSON output ❌ ✅
YAML output ❌ ✅
AI-ready summary ❌ ✅
.tree2ignore (gitignore-style) ❌ ✅
Python library API ❌ ✅
Cross-platform ⚠️ ✅
Zero dependencies N/A ✅

Example Output

Running tree2guide src --stdout:

src/
├── tree2guide/
│   ├── renderers/
│   │   ├── __init__.py
│   │   ├── html.py
│   │   ├── json_renderer.py
│   │   ├── llm.py
│   │   ├── markdown.py
│   │   ├── text.py
│   │   └── yaml_renderer.py
│   ├── __init__.py
│   ├── cli.py
│   ├── ignore.py
│   ├── llm.py
│   └── scanner.py

Running tree2guide . --llm --stdout:

============================================================
PROJECT STRUCTURE SUMMARY: tree2guide
============================================================

DETECTED STACK / LANGUAGE:
  - Python (pyproject.toml)

SIZE:
  Files      : 18
  Directories: 4

TOP-LEVEL LAYOUT:
  Directories:
    src/
    tests/
    docs/
  Files:
    pyproject.toml
    README.md
    LICENSE

NOTABLE FLAGS:
  - Tests directory present
  - GitHub Actions / workflows present
  - LICENSE file present
  - CHANGELOG present

Tested Environments

Verified on Windows 11, macOS 26.2, and Ubuntu via CI. See Tested Environments for full details and known platform-specific issues.


Philosophy

tree2guide follows a few simple principles:

  • One scan, many outputs. The filesystem is walked once; any renderer can consume the result.
  • Zero third-party dependencies. Always. pip install tree2guide is instant.
  • Human-readable first. Markdown is the default because humans read it everywhere.
  • AI-ready by design. The --llm flag produces structured output optimised for AI context windows.
  • CLI and library. Every feature available on the command line is also available as a Python API.
  • Never reads file contents. Only structure and filenames — your code stays on your machine.

Privacy

tree2guide operates entirely on your local machine.

It does:

  • ✅ Read directory structure and filenames
  • ✅ Apply ignore rules
  • ✅ Generate output locally

It does not:

  • ❌ Read file contents
  • ❌ Upload anything
  • ❌ Require an internet connection
  • ❌ Collect telemetry
  • ❌ Send data to any AI service

Installation

pip install tree2guide

Requires Python 3.9+, no other dependencies. Installs a tree2guide command directly — no python prefix needed.

Development setup (for contributors)

macOS / Linux

cd tree2guide
python3 -m venv venv
source venv/bin/activate
pip install -e ".[dev]"

Windows

cd tree2guide
python -m venv venv
venv\Scripts\activate
pip install -e ".[dev]"

Quick Start

# Markdown output (default) — writes docs_tree.md
tree2guide docs

# Plain text
tree2guide . --format text

# JSON
tree2guide . --format json

# Self-contained HTML with collapsible folders
tree2guide . --format html

# AI-ready project summary (no network call, no API key)
tree2guide . --llm

# Print to stdout instead of writing a file
tree2guide . --stdout

# Pipe to clipboard
tree2guide . --stdout | pbcopy      # macOS
tree2guide . --stdout | clip        # Windows

Command Reference

tree2guide <target_folder> [options]
Flag Description
-o, --output Output file path (default: <folder>_tree.<ext> based on format)
--exclude-file Use a specific exclude file instead of auto-detecting .tree2ignore
--title Add a heading above the tree
--no-footer Omit the author/license footer (markdown and html only)
--stdout Print to stdout instead of writing a file
--format {markdown,text,json,yaml,html,llm} Output format (default: markdown)
--llm Shorthand for --format llm — AI-friendly project summary
--max-depth N Limit recursion depth
--dirs-only Only show directories
--files-only Only show files (directories shown as scaffolding only)
--no-hidden Skip dotfiles/dotfolders without needing .tree2ignore entries
--sort {dirs-first,files-first,alpha} Sort order within each folder (default: dirs-first)
--no-progress Suppress scan progress and completion telemetry (stderr only) on large directories
--version Print the installed version and exit

Symlinks are rendered as name -> target and never followed — avoids infinite loops.

On large directories, tree2guide prints periodic progress (Scanning... N files, N dirs) and a final Scan complete. summary to stderr — never stdout — so piping (--stdout | your-tool) is unaffected. Fast scans print nothing extra. Use --no-progress to suppress this entirely.

Default output filenames

Format Output file
markdown <folder>_tree.md
text <folder>_tree.txt
json <folder>_tree.json
yaml <folder>_tree.yaml
html <folder>_tree.html
llm <folder>_llm.txt

The .tree2ignore file

The #1 rule: where it goes

.tree2ignore must sit directly inside the folder you pass as the target. Patterns are written relative to that folder — never include the target folder's name as a prefix.

# .tree2ignore lives at docs/.tree2ignore
tree2guide docs
# correct — relative to docs/
api
_drafts

# wrong — only correct if you ran: tree2guide .
docs/api
docs/_drafts

Pattern syntax (real .gitignore rules)

Pattern Meaning
build Matches a file or folder named build at any depth
build/ Same, but only matches directories
/build Matches build only at the root of the target (anchored)
*.log Matches all files ending in .log, anywhere
**/android/key.properties Matches that exact path at any depth
!keep-this Negates — re-includes something an earlier rule excluded
# comment Ignored

Patterns evaluate top to bottom — later rules override earlier ones, same as Git.

Whitelist example

Show only admin/, hide everything else:

*
!admin
!admin/**

Copy your .gitignore directly

The matching engine reimplements Git's rules exactly — copy your .gitignore into .tree2ignore and it will behave identically.


Defaults (always excluded, no setup needed)

  • .git
  • .tree2ignore
  • __pycache__
  • *.pyc
  • .DS_Store

Library API

tree2guide works as an importable library, not just a CLI:

import tree2guide
from pathlib import Path

root = Path("./my-project").resolve()
patterns = tree2guide.load_exclude_patterns(root / tree2guide.EXCLUDE_FILENAME)
matcher = tree2guide.ExcludeMatcher(patterns)

# Build the tree once
tree = tree2guide.build_node_tree(root, matcher)

# Render to any format
print(tree2guide.render_markdown(tree, title="My Project"))
print(tree2guide.render_text(tree))
print(tree2guide.render_json(tree))
print(tree2guide.render_yaml(tree))
print(tree2guide.render_html(tree, title="My Project"))
print(tree2guide.render_llm(tree, title="My Project"))

# Get the heuristic summary directly
summary = tree2guide.analyze(tree)
print(summary.detected_stack)
print(summary.file_count, summary.dir_count)
print(summary.notable_flags)

Public API surface

Name Description
build_node_tree(root, matcher, options=None, on_progress=None) Scan filesystem → TreeNode. on_progress(files, dirs), if given, is called at most once per second during the walk — pure instrumentation, None by default with zero effect
build_tree(root, matcher, options=None) Backward-compatible wrapper → list[str]
TreeNode Internal tree model (dataclass)
TreeOptions Scanner options (max_depth, dirs_only, sort, etc.)
ExcludeMatcher Evaluates .tree2ignore patterns
GitignoreRule Single compiled pattern rule
load_exclude_patterns(path) Parse a .tree2ignore file
analyze(node) Heuristic analysis → LlmSummary
LlmSummary Detected stack, file/dir counts, notable flags
render_markdown(tree, ...) Markdown string
render_text(tree, ...) Plain text string
render_json(tree) JSON string
render_yaml(tree) YAML string
render_html(tree, ...) Self-contained HTML string
render_llm(tree, ...) LLM-optimised plain text string

Project Structure

tree2guide/
├── .github/
│   └── workflows/
│       └── ci.yml
├── docs/                        # GitHub Pages docs site
│   ├── _config.yml
│   ├── index.md
│   ├── installation.md
│   ├── quickstart.md
│   ├── tree2ignore.md
│   ├── cli.md
│   ├── examples.md
│   ├── api.md
│   └── contributing.md
├── src/
│   └── tree2guide/
│       ├── __init__.py          # public API surface
│       ├── cli.py               # argparse + entry point
│       ├── ignore.py            # GitignoreRule, ExcludeMatcher
│       ├── llm.py               # analyze(), LlmSummary
│       ├── scanner.py           # build_node_tree(), TreeNode, TreeOptions
│       └── renderers/
│           ├── __init__.py
│           ├── html.py
│           ├── json_renderer.py
│           ├── llm.py
│           ├── markdown.py
│           ├── text.py
│           └── yaml_renderer.py
├── tests/
│   ├── test_ignore.py
│   ├── test_llm.py
│   ├── test_markdown_renderer.py
│   ├── test_renderers.py
│   └── test_scanner.py
├── CHANGELOG.md
├── LICENSE
├── README.md
└── pyproject.toml

Architecture: Scanner → Tree Model → Renderer. The scanner builds a TreeNode once; each renderer transforms the same object into a different format. Adding a new output format means writing a new renderer — no changes to the scanner or CLI needed.


Troubleshooting

"No exclude file found at .../.tree2ignore" → .tree2ignore must be directly inside the folder you passed as the target.

Patterns aren't excluding anything → Check for a stray prefix. If you ran tree2guide docs, write api not docs/api.

I want to exclude everything except one folder

*
!keepme
!keepme/**

--stdout produces garbled characters on Windows → Pipe directly to clipboard instead: tree2guide . --stdout | clip


Contributing

Pull requests, feature ideas, and bug reports are welcome. See CONTRIBUTING for the full guide, architecture walkthrough, and how to add a new renderer or stack signal.

Open stretch goals:

  • Browser playground (Pyodide/WASM)
  • Interactive HTML viewer from JSON output
  • --format csv — flat path list with type column
  • File size annotations
  • Character class patterns in .tree2ignore ([abc], [!abc])
  • Windows CI in the test matrix

License

MIT — see LICENSE for details.


Built and maintained by Lawrence Roble.

Metadata

Release files for tree2guide 1.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tree2guide 1.2.2
File Size Uploaded
tree2guide-1.2.2.tar.gz 35.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tree2guide 1.2.2
File Interpreter ABI Platform
tree2guide-1.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 63.3 kB

Release files / tree2guide-1.2.2.tar.gz

Download URL tree2guide-1.2.2.tar.gz
Size 35.8 kB
Tags Source
SHA-256 checksum
How to use checksums
6fd127532a75808e3f2631dcd39dcb90a4dbd146947977557af92d58051c8066
BLAKE2b-256 checksum
How to use checksums
487eb883bbd641b4d337cc9d20a4019852a657c5b19d842b0b3f0b30c42a41fa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.7

Release files / tree2guide-1.2.2-py3-none-any.whl

Download URL tree2guide-1.2.2-py3-none-any.whl
Size 27.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0e345e85d146112eef2a37ca2503af267dde2c72ae0ae54a0f0dbd4d255c0d90
BLAKE2b-256 checksum
How to use checksums
8017bff2d55fb9c30f08584003913af718f00014d8fd98308f4d6c2fa1e46fa0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.7

Release history Release notifications | RSS feed

This release

1.2.2 This release

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page