API Reference
API Reference
tree2guide is usable as a library, not just a CLI. Import it and call the same functions the CLI uses internally.
import tree2guide
Scanner
build_node_tree(root, matcher, options=None, on_progress=None) -> TreeNode
The primary scanner function. Walks the filesystem once and returns a TreeNode tree. All renderers consume this.
from pathlib import Path
import tree2guide
root = Path("./my-project").resolve()
patterns = tree2guide.load_exclude_patterns(root / tree2guide.EXCLUDE_FILENAME)
matcher = tree2guide.ExcludeMatcher(patterns)
options = tree2guide.TreeOptions(max_depth=3, no_hidden=True)
node = tree2guide.build_node_tree(root, matcher, options)
on_progress, if given, is a Callable[[int, int], None] called with
(files_visited, dirs_visited) at most once per second of wall-clock time
during the walk. It is pure instrumentation — the scanner does not know or
care who’s listening — and None (the default) has zero effect on the
returned tree or on any existing caller:
def report(files: int, dirs: int) -> None:
print(f"...{files} files, {dirs} dirs so far", file=sys.stderr)
node = tree2guide.build_node_tree(root, matcher, options, on_progress=report)
build_tree(root, matcher, options=None) -> list[str]
Backward-compatible wrapper. Returns the same connector-prefixed display lines the old API produced. Internally calls build_node_tree() and render_lines().
TreeNode
@dataclass
class TreeNode:
name: str
is_dir: bool
is_symlink: bool = False
symlink_target: str | None = None
children: list[TreeNode] = ...
The internal tree model. One node per filesystem entry. Renderers walk this structure — they never touch the filesystem themselves.
TreeOptions
@dataclass
class TreeOptions:
max_depth: int | None = None # None = unlimited
dirs_only: bool = False
files_only: bool = False
no_hidden: bool = False
sort: str = "dirs-first" # "dirs-first" | "files-first" | "alpha"
Ignore / exclusion
load_exclude_patterns(exclude_file: Path) -> list[str]
Reads a .tree2ignore-style file and returns a list of pattern strings, prefixed with the built-in defaults. Safe to call when the file doesn’t exist — returns only the defaults.
ExcludeMatcher(patterns: list[str])
Compiles a list of pattern strings into GitignoreRule objects.
matcher = tree2guide.ExcludeMatcher(["node_modules", "*.pyc", "!keep.pyc"])
matcher.is_excluded("node_modules", is_dir=True) # True
matcher.is_excluded("keep.pyc", is_dir=False) # False
matcher.is_excluded(rel_path: str, is_dir: bool) -> bool
Returns True if the relative path should be excluded. rel_path uses forward slashes regardless of OS.
GitignoreRule(raw: str)
A single compiled rule. Exposed for advanced use; most callers use ExcludeMatcher directly.
EXCLUDE_FILENAME
The string ".tree2ignore" — the default exclude filename.
DEFAULT_EXCLUDES
The list of patterns always applied before any .tree2ignore content:
[".git", ".tree2ignore", "__pycache__", "*.pyc", ".DS_Store"]
Renderers
All renderers accept a TreeNode and return a str with a trailing newline.
render_markdown(tree, title=None, include_footer=True) -> str
Fenced code block, optional # Title heading, optional attribution footer.
Also accepts a list[str] for backward compatibility.
render_text(tree, title=None) -> str
Plain text, no fences, title as a plain line (no # prefix).
render_json(tree, indent=2) -> str
Pretty-printed JSON. Shape:
{
"name": "src",
"type": "directory",
"children": [
{ "name": "main.py", "type": "file" },
{ "name": "link", "type": "symlink", "target": "/some/path" }
]
}
render_yaml(tree) -> str
Same structure as JSON, output as YAML. No PyYAML dependency.
render_html(tree, title=None, include_footer=True) -> str
Self-contained HTML page. Collapsible folders, expand/collapse all, dark theme, works offline.
render_llm(tree, title=None) -> str
AI-friendly plain-text summary. Calls analyze() internally. No network call, no API key.
LLM analysis
analyze(node: TreeNode) -> LlmSummary
Inspects a TreeNode tree and returns a structured heuristic summary. Single pass over the already-built tree — no extra filesystem I/O.
node = tree2guide.build_node_tree(root, matcher)
summary = tree2guide.analyze(node)
print(summary.detected_stack) # ["Python (pyproject.toml)", "Docker"]
print(summary.file_count) # 34
print(summary.dir_count) # 8
print(summary.notable_flags) # ["Tests directory present", ...]
print(summary.top_level_dirs) # ["src/", "tests/", "docs/"]
print(summary.top_level_files) # ["pyproject.toml", "README.md"]
LlmSummary
@dataclass
class LlmSummary:
detected_stack: list[str] # detected language/framework labels
file_count: int # total files (recursive)
dir_count: int # total directories (recursive)
notable_flags: list[str] # human-readable flag messages
top_level_dirs: list[str] # immediate child directories (with trailing /)
top_level_files: list[str] # immediate child files
Version
tree2guide.__version__ # "1.2.0"