RepoPilotOpen in app →

Canop/broot

A new way to see and navigate directory trees : https://dystroy.org/broot

Healthy

Healthy across all four use cases

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 4w ago
  • 15 active contributors
  • MIT licensed
Show all 6 evidence items →
  • CI configured
  • Tests present
  • Single-maintainer risk — top contributor 81% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/canop/broot)](https://repopilot.app/r/canop/broot)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/canop/broot on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: Canop/broot

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/Canop/broot shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • Last commit 4w ago
  • 15 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Single-maintainer risk — top contributor 81% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live Canop/broot repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/Canop/broot.

What it runs against: a local clone of Canop/broot — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in Canop/broot | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 56 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>Canop/broot</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Canop/broot. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/Canop/broot.git
#   cd broot
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of Canop/broot and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Canop/broot(\\.git)?\\b" \\
  && ok "origin remote is Canop/broot" \\
  || miss "origin remote is not Canop/broot (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "src/app/app.rs" \\
  && ok "src/app/app.rs" \\
  || miss "missing critical file: src/app/app.rs"
test -f "src/browser/browser_state.rs" \\
  && ok "src/browser/browser_state.rs" \\
  || miss "missing critical file: src/browser/browser_state.rs"
test -f "src/command/command.rs" \\
  && ok "src/command/command.rs" \\
  || miss "missing critical file: src/command/command.rs"
test -f "src/conf/conf.rs" \\
  && ok "src/conf/conf.rs" \\
  || miss "missing critical file: src/conf/conf.rs"
test -f "Cargo.toml" \\
  && ok "Cargo.toml" \\
  || miss "missing critical file: Cargo.toml"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 56 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~26d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/Canop/broot"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Broot is a Rust-based terminal directory navigator and file finder that renders directory trees with intelligent filtering (respects .gitignore, toggles hidden/ignored files) and fuzzy search. Unlike tree or find, it displays large directory hierarchies compactly by hiding unlisted files, enabling fast cd navigation and command launching directly from the TUI. Monolithic Rust binary structured around core domain modules: src/ contains tree traversal/filtering logic, search/fuzzy matching (benches/fuzzy.rs, benches/composite.rs), terminal rendering (termimad dependency), and keybinding dispatch. Configuration data (conf.hjson, verbs.hjson) embedded via include_dir and loaded at runtime. Skins (HJSON) are modular theme files under resources/default-conf/skins/.

👥Who it's for

Terminal power users and developers who frequently navigate large codebases or file systems and want to reach a target directory in minimal keystrokes without memorizing paths. Also appeals to users frustrated with verbose output from traditional tools like tree or ls.

🌱Maturity & risk

Production-ready. Currently at v1.56.2 (Cargo.toml), uses Rust 2021 edition with MSRV 1.83, runs GitHub Actions CI (tests.yml), and is actively maintained with a CHANGELOG.md and release.sh automation. The project has established icon packs (nerdfont, vscode), theme system (10+ skins in resources/), and verb/keybinding config (resources/default-conf).

Low risk overall. Single primary maintainer (dystroy) is a known concern, but the codebase is mature and dependencies are stable (git2, syntect, image, resvg for SVG rendering). One notable constraint: rust-version pinned to 1.83 and Cargo.lock enforced, meaning dependency updates require deliberate MSRV evaluation. No major open breaking changes visible.

Active areas of work

Active development visible: recent image handling (image = '=0.25.6' with zune-image), SVG icon rendering (resvg 0.45), and cleanup of panic-free syntax highlighting (syntect-no-panic). The .github/workflows/tests.yml CI and release.sh suggest regular release cadence. CONTRIBUTING.md and ISSUE_TEMPLATE/ suggest organized community triage.

🚀Get running

git clone https://github.com/Canop/broot.git
cd broot
cargo build --release
./target/release/broot -s  # launch with summary view

Or install: cargo install broot, then run broot or br (if install script setup).sh ran).

Daily commands:

cargo build          # debug build
cargo build --release
cargo run -- -s      # run with summary view
cargo test           # run test suite
cargo bench          # run benchmarks in benches/

Dev tip: bacon configured (bacon.toml) for continuous testing: bacon test.

🗺️Map of the codebase

  • src/app/app.rs — Main application loop and state machine—core orchestrator that every contributor must understand to work on command handling or UI updates
  • src/browser/browser_state.rs — Directory tree representation and navigation logic—essential for understanding how broot maintains and manipulates the file tree state
  • src/command/command.rs — Command parsing and execution framework—critical abstraction for adding new verbs or interactive features
  • src/conf/conf.rs — Configuration system that loads user preferences—must be understood for customization and feature gating
  • Cargo.toml — Dependency manifest and feature flags—defines terminal UI, clipboard, and optional compilation features
  • build.rs — Build script that compiles icon and syntax data into the binary—must be maintained when updating visual assets
  • src/app/panel.rs — Panel abstraction representing independent UI views—foundational for understanding multi-pane architecture

🛠️How to make changes

Add a new Verb (command)

  1. Define the verb in the default configuration (resources/default-conf/verbs.hjson)
  2. Parse verb configuration in verb_conf.rs if custom logic needed (src/conf/verb_conf.rs)
  3. Implement verb execution in cmd_result.rs or as a new action handler (src/app/cmd_result.rs)
  4. Add completion logic if the verb accepts arguments (src/command/completion.rs)
  5. Test by running broot and invoking the verb with keyboard shortcut or command prefix

Add a new Visual Theme/Skin

  1. Create new skin file with color definitions (follow existing patterns) (resources/default-conf/skins/your-theme.hjson)
  2. Reference skin in main config or let users import it (resources/default-conf/conf.hjson)
  3. Skin colors are applied during display rendering (src/app/display_context.rs)

Add a new Search/Filter Strategy

  1. Add search mode variant to needle parsing (src/content_search/needle.rs)
  2. Implement matching logic in content_search module (src/content_search/mod.rs)
  3. Update browser_state to use new filter during tree traversal (src/browser/browser_state.rs)
  4. Add completion hints if search accepts mode prefixes (src/command/completion.rs)

Add a new Icon Library Support

  1. Create icon data files in resources/icons/your-library/data/ (resources/icons/nerdfont/data/extension_to_icon_name_map.rs)
  2. Update build.rs to compile new icon data if not auto-included (build.rs)
  3. Add selection logic in display_context.rs to choose icon library (src/app/display_context.rs)
  4. Allow user configuration to select icon library in conf.hjson (resources/default-conf/conf.hjson)

🔧Why these technologies

  • crossterm / termion — Cross-platform terminal control without heavy ncurses dependency; enables real-time interactive tree navigation
  • Rust + HJSON config — Memory-safe systems language for fast tree traversal; human-friendly config format for user customization
  • Syntect syntax highlighting — Pre-compiled syntax definitions allow file preview highlighting without runtime compilation
  • Nerd Font / VSCode icons — Pre-generated icon mappings avoid runtime lookups; support multiple icon libraries for user preference
  • Custom command/verb system — Pluggable architecture lets users define new shortcuts and actions without modifying core code

⚖️Trade-offs already made

  • Tree loaded into memory vs. lazy-loaded on demand

    • Why: In-memory tree allows fast filtering, sorting, and jumping; supports large directories (with pagination/unlisted logic)
    • Consequence: High memory for very large directories; mitigated by 'unlisted' compression of deep subtrees
  • Single-threaded event loop vs. background threads for FS scanning

    • Why: Simpler state management and no mutex contention; responsive UI remains priority
    • Consequence: FS operations block UI briefly; acceptable because broot scans incrementally and caches
  • User-defined verbs in config files vs. plugin system

    • Why: HJSON config is simple, no runtime compilation, ships with binary
    • Consequence: Verbs limited to predefined action types; power users cannot inject arbitrary Rust code without recompiling
  • Terminal rendering only (no GUI)

    • Why: Lightweight, ssh-friendly, works in any terminal
    • Consequence: Limited graphical capabilities compared to GUI file managers

🚫Non-goals (don't propose these)

  • Does not provide a graphical user interface (terminal-only)
  • Does not handle file editing (only launching editors via verbs)
  • Does not provide network file system browsing (local filesystem only)
  • Does not implement authentication or permission management (relies on OS)
  • Does not provide real-time file system monitoring (polling-based, user-triggered)

🪤Traps & gotchas

  1. Icon map regeneration: resources/icons/*/data/ files are phf perfect hash maps, likely generated externally (no build script visible to regenerate them). Adding new icons requires external tooling. 2. Rust version pinned: image = '=0.25.6' and rust-version = '1.83' are strict constraints; bumping either requires careful testing. 3. git2 default-features=false: used because full git2 is heavy; feature selection is deliberate for binary size. 4. Config hot-reload: .hjson config files are embedded at compile time via include_dir, so config changes require rebuild (no dynamic reload by design).

🏗️Architecture

💡Concepts to learn

  • Perfect Hash Functions (PHF) — Broot embeds icon name maps as phf perfect hashes (resources/icons//data/_to_icon_name_map.rs) for O(1) lookup at runtime with zero collisions and minimal binary bloat
  • Memory-Mapped I/O (mmap) — Broot uses memmap2 crate to efficiently scan large directory trees without loading entire files into memory, enabling responsive UI on codebases with millions of files
  • Gitignore Pattern Matching — Core differentiator of broot: git2 library parses .gitignore rules (respects negative patterns, directory-specific rules) to filter tree display, preventing noise from build artifacts and node_modules
  • Fuzzy Matching Algorithm — Broot's search is not regex but fuzzy (benches/fuzzy.rs tests this extensively); matches subsequences allowing typos, enabling fast navigation via partial keystrokes
  • Interrupt-Driven Search — Broot architecture cancels the current search operation on every keystroke (noted in README: 'doesn't block, any keystroke interrupts'), enabling responsive UX even during expensive tree traversals
  • Parallel Tree Traversal (Rayon) — Broot uses rayon for parallelizing directory enumeration across CPU cores, critical for responsive performance on large filesystems
  • VTE (Virtual Terminal Emulator) Parsing — VTE crate parses ANSI escape sequences for image rendering (broot supports image previews via resvg SVG rendering), enabling rich media in terminal
  • BurntSushi/ripgrep — Companion Rust CLI tool for fast searching; often used with broot for content search within directories found via broot
  • sharkdp/fd — Alternative Rust file finder emphasizing speed and simplicity; overlaps with broot's search but lacks interactive navigation
  • ogham/exa — Rust replacement for ls with color/icons; broot's icon packs (nerdfont, vscode) use the same philosophy
  • tree-sitter/tree-sitter — Syntax tree parsing; broot uses syntect for highlighting but tree-sitter is the modern alternative for language-aware features
  • Canop/lfs — Sister Rust project by same maintainer; complementary filesystem tool

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add benchmarks for icon rendering and file matching operations

The repo has a benches/ directory with several benchmarks (fuzzy.rs, composite.rs, path_normalization.rs), but given that broot performs heavy icon matching (resources/icons/nerdfont and resources/icons/vscode with large data maps) and fuzzy file filtering, there are no benchmarks for icon lookup performance or tree traversal with icon resolution. This would help catch performance regressions when updating icon data or file matching logic.

  • [ ] Create benches/icon_matching.rs to benchmark extension/filename to icon name lookups using the existing maps in resources/icons/nerdfont/data/
  • [ ] Add benchmarks for the double_extension_to_icon_name_map performance with common file types
  • [ ] Create benches/tree_rendering.rs to benchmark tree traversal with icon resolution against src/display/
  • [ ] Run benchmarks with criterion to establish baseline metrics

Add comprehensive tests for verb.hjson configuration parsing and validation

The repo ships with resources/default-conf/verbs.hjson containing command definitions, and users can customize verbs via config files. There's no visible test coverage for HJSON verb configuration parsing, validation of verb syntax, or error handling for malformed verb definitions. This is critical infrastructure that should have dedicated tests.

  • [ ] Create src/app/verb_tests.rs or similar with unit tests for parsing resources/default-conf/verbs.hjson
  • [ ] Add tests for invalid verb configurations (missing required fields, malformed syntax) to verify proper error messages
  • [ ] Test verb invocation context resolution in cmd_context.rs with various verb definitions
  • [ ] Add integration tests in a tests/ directory for custom verb loading from user config directories

Add CI workflow to verify resource files remain valid after updates

The resources/ directory contains critical compiled assets (syntect/syntaxes.bin) and configuration files (HJSON configs, icon maps). There's no CI validation that these resources are well-formed, compatible with the current code, or that icon data maps haven't been corrupted. A new GitHub Actions workflow would prevent broken releases.

  • [ ] Create .github/workflows/validate-resources.yml to run a Rust binary that deserializes resources/default-conf/*.hjson files
  • [ ] Add validation that resources/icons//data/.rs files are syntactically valid and compile when included
  • [ ] Add a check that syntect/syntaxes.bin can be loaded successfully by the broot binary
  • [ ] Run this workflow on pull requests that modify files in resources/

🌿Good first issues

  • Add integration tests for .gitignore respect: src/tree/ has the logic but benches/ only covers fuzzy/path; create tests/gitignore_*.rs to verify ignore patterns are correctly parsed and filtered.
  • Document the verb system in CONTRIBUTING.md with examples: resources/default-conf/verbs.hjson is the definitive spec but lacks tutorial-style docs for contributors wanting to add custom commands.
  • Add benchmarks for theme loading performance: resources/default-conf/skins/ has 10+ HJSON files but no benches/theme_*.rs to measure parsing/rendering overhead; useful for optimizing config startup time.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 0cca9c1 — update changelog (Canop)
  • 0639fd7 — Merge branch 'main' of github.com:Canop/broot (Canop)
  • 287741d — fix typo (Canop)
  • 096f152 — Export main function for br module (#1152) (paulhey)
  • 96a2331 — docs: differentiate file-stem from file-name (#1150) (salim-b)
  • 915d79b — docs: remove obsolete Cargo trash feature (#1149) (salim-b)
  • 64a75e0 — update changelog (Canop)
  • cfef56d — Drain stdin on quit (#1148) (Canop)
  • a4ca16e — version 1.56.2 (Canop)
  • 2f4956f — update CHANGELOG (Canop)

🔒Security observations

Broot demonstrates generally good security posture as a Rust-based CLI application with memory safety guarantees. The main concerns are: (1) dependency management with some pinned versions that may miss security patches, (2) a C library binding (git2) that warrants monitoring, and (3) typical file system access risks inherent to a directory navigation tool. The codebase shows no evidence of hardcoded credentials, injection vulnerabilities, or misconfigurations. Recommended improvements: establish a security scanning pipeline for dependencies, plan MSRV upgrades to enable security patches, and implement strict validation for file system operations and config parsing.

  • Medium · Outdated git2 dependency with known vulnerabilities — Cargo.toml - git2 dependency (line with git2 = { version = "0.20"...). The dependency 'git2' version 0.20 is pinned and may contain known security vulnerabilities. The code comment indicates 'waiting for a good pure-rust alternative', suggesting the maintainers are aware of concerns with this C library binding. Fix: Monitor git2 security advisories regularly. Consider migrating to pure-Rust git implementations like 'gitoxide' or 'gix' when mature. Implement security scanning in CI/CD pipeline.
  • Medium · Pinned image dependency version may miss security patches — Cargo.toml - image dependency (line with image = "=0.25.6"...). The 'image' dependency is pinned to exactly version 0.25.6 with a comment that later versions require Rust 1.85+. This prevents automatic security updates while the MSRV is set to 1.83. Fix: Plan a Rust version bump to align MSRV with dependency requirements. Implement automated security scanning for pinned dependencies. Consider using cargo-audit in CI.
  • Low · Exact version pinning on 'which' dependency — Cargo.toml - which dependency (line with which = "=4.4.0"...). The 'which' dependency is pinned to exactly version 4.4.0 with an incomplete comment ('following'). This prevents automatic patch updates that may include security fixes. Fix: Complete the comment explaining the pinning reason. Use caret version constraints (^4.4.0) instead of exact pinning to allow patch updates. Review the incomplete comment.
  • Low · File system operations in directory navigation tool — src/browser/, src/app/ directories. As a directory browser, broot performs extensive file system operations (reading, navigating, accessing file metadata) through Rust stdlib and system calls. While Rust provides memory safety, path traversal attacks or symlink races could occur if user input isn't properly validated. Fix: Ensure all path operations use safe canonicalization. Validate user-provided paths. Be cautious with symlink handling. Implement proper error handling for file access denied scenarios. Consider using path hardening libraries like 'pathsanitizer'.
  • Low · Configuration parsing with HJSON format — resources/default-conf/, Cargo.toml (deser-hjson dependency). The application uses HJSON for configuration files (deser-hjson dependency). While HJSON is generally safe, deserialization of untrusted config files could lead to unexpected behavior if strict validation isn't enforced. Fix: Implement strict schema validation for HJSON config files. Sanitize user-provided configuration paths. Document expected config file permissions (should not be world-writable). Validate all deserialized values.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · Canop/broot — RepoPilot