|
| 1 | +# TreeMapper |
| 2 | + |
| 3 | +[](https://pypi.org/project/treemapper/) |
| 4 | +[](https://pypi.org/project/treemapper/) |
| 5 | +[](https://github.com/nikolay-e/treemapper/blob/main/LICENSE) |
| 6 | + |
| 7 | +**Export your codebase for AI/LLM context in one command.** |
| 8 | + |
| 9 | +```bash |
| 10 | +pip install treemapper |
| 11 | +treemapper . -o context.yaml # paste into ChatGPT/Claude |
| 12 | +``` |
| 13 | + |
| 14 | +## Why TreeMapper? |
| 15 | + |
| 16 | +Unlike `tree` or `find`, TreeMapper exports **structure + file |
| 17 | +contents** in a format optimized for LLM context windows: |
| 18 | + |
| 19 | +```yaml |
| 20 | +name: myproject |
| 21 | +type: directory |
| 22 | +children: |
| 23 | + - name: main.py |
| 24 | + type: file |
| 25 | + content: | |
| 26 | + def hello(): |
| 27 | + print("Hello, World!") |
| 28 | + - name: utils/ |
| 29 | + type: directory |
| 30 | + children: |
| 31 | + - name: helpers.py |
| 32 | + type: file |
| 33 | + content: | |
| 34 | + def add(a, b): |
| 35 | + return a + b |
| 36 | +``` |
| 37 | +
|
| 38 | +## Usage |
| 39 | +
|
| 40 | +```bash |
| 41 | +treemapper . # YAML to stdout + token count |
| 42 | +treemapper . -o tree.yaml # save to file |
| 43 | +treemapper . -o # save to tree.yaml (default) |
| 44 | +treemapper . -o - # explicit stdout output |
| 45 | +treemapper . -f json # JSON format |
| 46 | +treemapper . -f txt # plain text with indentation |
| 47 | +treemapper . -f md # Markdown with fenced code |
| 48 | +treemapper . -f yml # YAML (alias) |
| 49 | +treemapper . --no-content # structure only |
| 50 | +treemapper . --max-depth 3 # limit directory depth |
| 51 | +treemapper . --max-file-bytes 10000 # skip files > 10KB |
| 52 | +treemapper . --max-file-bytes 0 # no limit |
| 53 | +treemapper . -i custom.ignore # custom ignore patterns |
| 54 | +treemapper . --no-default-ignores # disable default ignores |
| 55 | +treemapper . --log-level info # log level |
| 56 | +treemapper . -c # copy to clipboard |
| 57 | +treemapper . -c -o tree.yaml # clipboard + save to file |
| 58 | +treemapper -v # show version |
| 59 | +``` |
| 60 | + |
| 61 | +## Diff Context Mode |
| 62 | + |
| 63 | +Smart context selection for git diffs — automatically finds the |
| 64 | +minimal set of code fragments needed to understand a change: |
| 65 | + |
| 66 | +```bash |
| 67 | +treemapper . --diff HEAD~1..HEAD # recent changes |
| 68 | +treemapper . --diff main..feature # feature branch |
| 69 | +treemapper . --diff HEAD~1 --budget 30000 # limit tokens |
| 70 | +treemapper . --diff HEAD~1 --full # all changed code |
| 71 | +``` |
| 72 | + |
| 73 | +Uses graph-based relevance propagation (Personalized PageRank) |
| 74 | +to select the most important context within a token budget. |
| 75 | +Understands imports, type references, config dependencies, and |
| 76 | +co-change patterns across 13+ programming languages. |
| 77 | + |
| 78 | +Output format: |
| 79 | + |
| 80 | +```yaml |
| 81 | +name: myproject |
| 82 | +type: diff_context |
| 83 | +fragment_count: 5 |
| 84 | +fragments: |
| 85 | + - path: src/main.py |
| 86 | + lines: "10-25" |
| 87 | + kind: function |
| 88 | + symbol: process_data |
| 89 | + content: | |
| 90 | + def process_data(items): |
| 91 | + ... |
| 92 | +``` |
| 93 | +
|
| 94 | +Options: |
| 95 | +
|
| 96 | +| Flag | Default | Description | |
| 97 | +|------------|---------|----------------------------------| |
| 98 | +| `--budget` | 50000 | Maximum output tokens | |
| 99 | +| `--alpha` | 0.60 | PPR damping factor | |
| 100 | +| `--tau` | 0.08 | Stopping threshold | |
| 101 | +| `--full` | false | Include all changed code | |
| 102 | + |
| 103 | +## Token Counting |
| 104 | + |
| 105 | +Token count and size are always displayed on stderr: |
| 106 | + |
| 107 | +```text |
| 108 | +12,847 tokens (o200k_base), 52.3 KB |
| 109 | +``` |
| 110 | + |
| 111 | +For large outputs (>1MB), approximate counts with `~` prefix: |
| 112 | + |
| 113 | +```text |
| 114 | +~125,000 tokens (o200k_base), 5.2 MB |
| 115 | +``` |
| 116 | + |
| 117 | +Uses tiktoken with `o200k_base` encoding (GPT-4o tokenizer). |
| 118 | + |
| 119 | +## Clipboard Support |
| 120 | + |
| 121 | +Copy output directly to clipboard with `-c` or `--copy`: |
| 122 | + |
| 123 | +```bash |
| 124 | +treemapper . -c # copy (no stdout) |
| 125 | +treemapper . -c -o tree.yaml # copy + save to file |
| 126 | +``` |
| 127 | + |
| 128 | +**System Requirements:** |
| 129 | + |
| 130 | +- **macOS:** `pbcopy` (pre-installed) |
| 131 | +- **Windows:** `clip` (pre-installed) |
| 132 | +- **Linux (Wayland):** `wl-copy` |
| 133 | +- **Linux (X11):** `xclip` or `xsel` |
| 134 | + |
| 135 | +## Python API |
| 136 | + |
| 137 | +```python |
| 138 | +from treemapper import map_directory |
| 139 | +from treemapper import to_yaml, to_json, to_text, to_markdown |
| 140 | +
|
| 141 | +tree = map_directory( |
| 142 | + path, # directory path |
| 143 | + max_depth=None, # limit traversal depth |
| 144 | + no_content=False, # exclude file contents |
| 145 | + max_file_bytes=None, # skip large files |
| 146 | + ignore_file=None, # custom ignore file |
| 147 | + no_default_ignores=False,# disable default ignores |
| 148 | +) |
| 149 | +
|
| 150 | +yaml_str = to_yaml(tree) |
| 151 | +json_str = to_json(tree) |
| 152 | +text_str = to_text(tree) |
| 153 | +md_str = to_markdown(tree) |
| 154 | +``` |
| 155 | + |
| 156 | +## Ignore Patterns |
| 157 | + |
| 158 | +Respects `.gitignore` and `.treemapperignore` automatically. |
| 159 | +Use `--no-default-ignores` to include everything. |
| 160 | + |
| 161 | +- Hierarchical: nested ignore files at each directory level |
| 162 | +- Negation patterns: `!important.log` un-ignores a file |
| 163 | +- Anchored patterns: `/root_only.txt` matches only in root |
| 164 | +- Output file is always auto-ignored |
| 165 | + |
| 166 | +## Content Placeholders |
| 167 | + |
| 168 | +- `<file too large: N bytes>` — exceeds `--max-file-bytes` |
| 169 | +- `<binary file: N bytes>` — binary file detected |
| 170 | +- `<unreadable content: not utf-8>` — not valid UTF-8 |
| 171 | +- `<unreadable content>` — permission denied or I/O error |
| 172 | + |
| 173 | +## Development |
| 174 | + |
| 175 | +```bash |
| 176 | +pip install -e ".[dev]" |
| 177 | +pytest |
| 178 | +pre-commit run --all-files |
| 179 | +``` |
| 180 | + |
| 181 | +## License |
| 182 | + |
| 183 | +Apache 2.0 |
0 commit comments