tree2md 0.7.0

Like the tree command, but outputs in Markdown. Optionally embed file contents as code blocks.
tree2md-0.7.0 is not a library.

tree2md

Crates.io License: MIT

Like the tree command, but outputs in Markdown. Scans directories and prints a Markdown-formatted tree. Optionally embed file contents as syntax-highlighted code blocks.


Table of Contents


Quick Start

# Install
cargo install tree2md

# Show directory tree (no file contents)
tree2md src > PROJECT_STRUCTURE.md

# Include file contents as code blocks
tree2md src -c > PROJECT_STRUCTURE.md

Clipboard helpers:

# macOS
tree2md src -c | pbcopy
# Linux
tree2md src -c | xclip -selection clipboard
# Windows
tree2md src -c | clip

Why tree2md vs. tree

Capability tree tree2md
Output Markdown ✖︎
Embed file contents (code blocks) ✖︎
Syntax highlighting hints ✖︎
Respect .gitignore ◯*
Filter by extension / glob
Drive via stdin (authoritative/merge)
Flat output for file collections ✖︎
Truncate by bytes / lines ✖︎
Security boundary (--restrict-root) ✖︎
Fast, single-binary (Rust)

* depending on platform/flags; tree2md respects .gitignore by default.


Features

  • Markdown-formatted directory trees
  • Optional file contents as fenced code blocks (with language hints)
  • Extension filters and glob patterns
  • Honors .gitignore by default (use --no-gitignore to disable)
  • Truncate large files by bytes or lines
  • Hidden files/dirs shown by default (use --exclude-hidden to hide)
  • .git/ directory is always excluded for safety and cleanliness
  • Read paths from stdin (newline or NUL-delimited)
  • Flat output for discrete file sets
  • Security guardrail with --restrict-root
  • Fast & efficient (Rust)

Installation

From crates.io

cargo install tree2md

From source

git clone https://github.com/zawakin/tree2md.git
cd tree2md
cargo build --release
# Binary at: ./target/release/tree2md

Pre-built binaries

Download from the releases page.

Available for:

  • Linux (x86_64)
  • macOS (Apple Silicon)
  • Windows (x86_64)

Usage

Common recipes

# Quick overview without contents
tree2md .

# Generate README-style docs with contents
tree2md src -c > PROJECT_STRUCTURE.md

# Filter by extensions
tree2md src -e .rs,.toml

# Find with glob patterns (repeatable)
tree2md -f "*.rs" -f "src/**/*.rs"

# Exclude hidden files (shown by default)
tree2md --exclude-hidden

# Truncate embedded contents (lines or bytes)
tree2md -c --max-lines 80
tree2md -c --truncate 2000

# 7) Combine filters + contents + truncation
tree2md -f "src/**/*.rs" -c --max-lines 100

Git-friendly

# Only Git-tracked TypeScript files
git ls-files "*.ts" | tree2md --stdin -c

# Recently changed files
git diff --name-only HEAD~1 | tree2md --stdin

All options (cheat sheet)

Basic

  • -c, --contents — include file contents as code blocks
  • -t, --truncate <N> — truncate file content to first N bytes
  • --max-lines <N> — limit file content to first N lines
  • -e, --include-ext <EXTS> — comma-separated list (e.g. .go,.py)
  • -f, --find <PATTERN> — glob pattern (repeatable), e.g. "src/**/*.rs"
  • --exclude-hidden — exclude hidden files/dirs (dotfiles)
  • --no-gitignore — ignore .gitignore files and include all files
  • -h, --help / -V, --version

Note: The .git/ directory is always excluded regardless of flags.

Stdin mode

  • --stdin — read newline-delimited paths from stdin
  • --restrict-root <DIR> — ensure all paths stay within this directory
  • --expand-dirs — expand directories received via stdin
  • --flat — render a flat list (no tree)

Display & paths

  • --display-path <relative|absolute|input> — default: relative
  • --strip-prefix <PREFIX> — remove prefix from display paths (repeatable)
  • --root-label <LABEL> — custom label for the root (e.g. ".", "PROJECT_ROOT")

Stdin mode (precise control)

Use stdin when you already have an exact file list (CI pipelines, git ls-files, ripgrep, find).

# Only use files from stdin (no directory scanning)
git ls-files "*.ts" | tree2md --stdin -c

# Expand directories that appear in stdin
printf '%s\n' src tests | tree2md --stdin --expand-dirs

# Enforce a project boundary (security)
rg -l "TODO" | tree2md --stdin --restrict-root "$(pwd)"

Flat mode is great for discrete file collections:

fzf -m | tree2md --stdin --flat -c

Display & path controls

# Show absolute paths
tree2md --display-path absolute .

# Strip a common prefix from printed paths
find ~/projects/myapp -type f | tree2md --stdin --strip-prefix ~/projects

Example output

## File Structure
- my_project/
  - src/
    - main.rs
    - lib.rs
  - Cargo.toml
  - README.md

### src/main.rs
```rust
fn main() {
    println!("Hello, world!");
}
```

### src/lib.rs
```rust
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}
```

Supported languages

Language detection for fenced code blocks (non-exhaustive):

  • Rust (.rs), Go (.go), Python (.py)
  • JavaScript (.js), TypeScript (.ts, .tsx)
  • HTML (.html), CSS (.css, .scss, .sass)
  • SQL (.sql), Shell (.sh)
  • TOML (.toml), YAML (.yaml, .yml)
  • JSON (.json), Markdown (.md)

Performance & security

  • Designed to be fast and memory-efficient.
  • Use --truncate / --max-lines for very large files.
  • Prefer --respect-gitignore to avoid noise.
  • Use --restrict-root in scripts/CI to prevent path escapes.

Build from source

Requirements:

  • Rust 1.70 or later
  • Cargo
git clone https://github.com/zawakin/tree2md.git
cd tree2md

# Build release
cargo build --release

# Run tests
cargo test

# Install locally
cargo install --path .

Contributing

Issues and PRs are welcome. Please include a clear description and, if possible, tests.


License

MIT License