sayanarijit/xplr
A hackable, minimal, fast TUI file explorer
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 5mo ago
- ✓15 active contributors
- ✓MIT licensed
Show all 7 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Slowing — last commit 5mo ago
- ⚠Concentrated ownership — top contributor handles 72% 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.
[](https://repopilot.app/r/sayanarijit/xplr)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/sayanarijit/xplr on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: sayanarijit/xplr
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:
- 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. - 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.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/sayanarijit/xplr 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 5mo ago
- 15 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Slowing — last commit 5mo ago
- ⚠ Concentrated ownership — top contributor handles 72% 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 sayanarijit/xplr
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/sayanarijit/xplr.
What it runs against: a local clone of sayanarijit/xplr — 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 sayanarijit/xplr | 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 | Last commit ≤ 165 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of sayanarijit/xplr. If you don't
# have one yet, run these first:
#
# git clone https://github.com/sayanarijit/xplr.git
# cd xplr
#
# 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 sayanarijit/xplr and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "sayanarijit/xplr(\\.git)?\\b" \\
&& ok "origin remote is sayanarijit/xplr" \\
|| miss "origin remote is not sayanarijit/xplr (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"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 165 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~135d)"
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/sayanarijit/xplr"
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).
⚡TL;DR
xplr is a terminal UI file explorer written in Rust that lets users navigate filesystems interactively with a keyboard-driven interface, extensible via Lua scripting. It bridges command-line utilities and GUI file managers by acting as a hackable orchestrator for filesystem operations, rendering real-time visual feedback using the Ratatui TUI framework and supporting custom layouts, key bindings, and plugins. Single-binary Rust project: src/ contains the main application code organized by concern (likely state management, input handling, rendering, Lua integration), benches/criterion.rs provides performance benchmarks, and docs/en/src/ houses comprehensive mdBook documentation. Lua scripts are vendored via mlua with optional vendored-lua feature flag. Configuration lives in YAML via serde_yaml, and the binary is distributed via Cargo/crates.io with Nix support.
👥Who it's for
Terminal power users and CLI developers who want a modern, scriptable file explorer alternative to standard shell commands and traditional GUI file managers; users building custom filesystem automation workflows through xplr's Lua plugin system and integration hooks.
🌱Maturity & risk
Actively maintained at v1.1.0 with comprehensive CI/CD via GitHub Actions (ci.yml, cd.yml, book.yml, nix-cache.yml) and published on crates.io. The project has solid documentation in docs/en/src/, LTO-optimized release builds, and proper Nix packaging support (default.nix). This is production-ready software with ongoing development, though as a single-maintainer TUI tool it depends on the maintainer's availability.
Moderate risk: the repo has 28+ direct dependencies (mlua for Lua VM, ratatui for TUI, serde_yaml for config, rayon for parallelism) which increases attack surface. Single maintainer (Arijit Basu) creates continuity risk. Breaking changes between minor versions are possible given the 'hackable' nature—users customizing Lua scripts or keybindings may need updates. No visible issue count in metadata provided, but large Lua plugin ecosystem (seen in docs) means ecosystem fragmentation risk.
Active areas of work
Project is in active maintenance mode at v1.1.0 (Cargo.toml). CI workflows execute on pushes/PRs. The book.yml workflow suggests ongoing documentation updates. The RELEASE.md file indicates structured versioning and release procedures. Based on the file structure, recent focus areas likely include: plugin ecosystem expansion (docs for awesome-plugins.md, awesome-integrations.md, awesome-hacks.md), Lua integration features, and TUI rendering improvements via ratatui upgrades.
🚀Get running
git clone https://github.com/sayanarijit/xplr.git
cd xplr
cargo build --release
./target/release/xplr
Daily commands:
cargo build --release
./target/release/xplr
Or for development: cargo run (debug build). Performance testing: cargo bench --bench criterion.
🗺️Map of the codebase
- src/main.rs: Entry point; contains or orchestrates the main event loop, TUI initialization, and Lua VM setup
- Cargo.toml: Defines all 28+ dependencies, vendored-lua feature flag, and release optimization profile (lto, strip)
- docs/en/src/SUMMARY.md: Navigation map for the mdBook documentation; shows all user-facing feature areas and configuration surfaces
- .github/workflows/ci.yml: CI pipeline defining build, test, and lint targets across platforms
- default.nix: Nix package definition for reproducible builds and NixOS distribution
- benches/criterion.rs: Performance benchmarks using criterion; run with
cargo benchto catch regressions
🛠️How to make changes
For new features: src/ likely contains input.rs (key binding logic), config.rs (YAML parsing), rendering code (Ratatui widgets). For Lua integration: interact with mlua bindings (check how current Lua callbacks are exposed). For docs: edit docs/en/src/ markdown files—see docs/en/src/SUMMARY.md for structure. For plugins: users add Lua scripts following the docs/en/src/installing-plugins.md pattern. For tests: add integration tests using assert_cmd (seen in dev-dependencies).
🪤Traps & gotchas
- Lua version specificity: mlua is configured with luajit feature (not pure Lua)—Lua scripts must be LuaJIT-compatible; pure Lua 5.4 features will not work. 2. Vendored Lua: The default feature vendored-lua embeds LuaJIT; disabling it requires system LuaJIT/Lua installed, adding complexity. 3. YAML config fragility: Configuration is strict serde_yaml (serde_yaml 0.9); invalid YAML in user configs will cause silent parse failures or panic—no graceful fallback shown. 4. Terminal capability assumption: Ratatui uses crossterm which may behave differently across terminal emulators; some color/unicode features may not render on legacy terminals. 5. Single-threaded event loop assumption: rayon is used for file operations, but the TUI loop is likely single-threaded; concurrent Lua script execution may cause deadlocks—check mlua Lua thread safety.
💡Concepts to learn
- Lua VM Sandboxing — xplr embeds a Lua 5.1/LuaJIT VM (via mlua 0.11) to run user scripts safely; understanding how Rust exposes functions to Lua and restricts capabilities is critical for extending xplr without security risks
- Terminal User Interface (TUI) Rendering — xplr uses Ratatui (formerly tui-rs) for crossterm-based rendering; understanding layout constraints, widget composition, and event loops is essential for adding new UI panels or modifying the visual layout
- ANSI Color Escapes to TUI Widget Mapping — xplr uses ansi-to-tui 7.0 to convert raw ANSI escape codes (from lscolors, shell output) into Ratatui color/style objects; this is how external tool output integrates visually
- Declarative Configuration via YAML + Serde — xplr's entire config (keybindings, layouts, filtering rules) is declarative YAML (via serde_yaml 0.9); contributors must understand how YAML maps to Rust structs and how validation works
- Parallel File Operations via Rayon — xplr uses rayon 1.11 for data-parallelism when traversing large directories; understanding work-stealing thread pools is crucial for diagnosing slow filesystem traversal or memory issues
- Natural Order Sorting (Natord) — xplr uses natord 1.0 to sort file names in human-friendly order (e.g., file1, file2, file10) rather than lexicographic; this is transparent to users but affects all directory listings
- Vendored vs. System Lua Dependencies — xplr's default vendored-lua feature compiles LuaJIT into the binary via mlua/vendored, eliminating runtime Lua dependencies but increasing binary size; disabling it requires users to install LuaJIT—this affects distribution and reproducibility
🔗Related repos
jvgrootveld/ranger— ranger is a Python-based VI-keybind TUI file manager; xplr modernizes this concept with Rust/Lua and better extensibilitygokcehan/lf— lf is a Go-written minimalist file manager with VI keys; xplr is a more hackable alternative with Lua scripting vs. static configClementTsang/bottom— bottom is a system monitor TUI using Rust + ratatui; xplr uses the same TUI stack for file exploration, showing ecosystem maturitycasey/just— just is a modern task runner; users often pair xplr with just for executing file-based workflows from the TUIBurntSushi/ripgrep— ripgrep (rg) is a fast line-search CLI tool; xplr integrates with ripgrep and similar utilities as per awesome-integrations.md
🪄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 integration tests for Lua plugin system (mlua integration)
The repo uses mlua (0.11) for Lua scripting and has extensive plugin documentation (docs/en/src/writing-plugins.md, docs/en/src/lua-function-calls.md), but there are no visible integration tests in the benches/ or test directories. Given that plugins are a core extensibility feature, adding tests would catch regressions in the Lua API surface and ensure plugin compatibility across versions.
- [ ] Create tests/lua_integration.rs with test cases for mlua function calls
- [ ] Add tests for plugin loading from xdg/home directories (xdg crate integration)
- [ ] Test Lua serialization with serde via mlua for config parsing
- [ ] Add tests to verify environment variable passing to Lua scripts (docs mention env-vars-and-pipes.md)
- [ ] Run tests in CI workflow (.github/workflows/ci.yml)
Add missing documentation for xplr.util Lua module
The file structure shows docs/en/src/xplr.util.md exists but no other Lua module docs are visible (no xplr.config.md, xplr.fm.md, etc.). Since the project is Lua-hackable and the README links to documentation, documenting all exposed Lua modules would be high-value for plugin developers. This requires investigating what Lua APIs are exposed in src/ and documenting them.
- [ ] Audit src/ code for all Lua-exposed functions and types (mlua exports)
- [ ] Create docs/en/src/xplr.config.md documenting config API
- [ ] Create docs/en/src/xplr.fm.md documenting file manager state API
- [ ] Update docs/en/src/SUMMARY.md to include new Lua module pages
- [ ] Add examples for each Lua module in docs
Add benchmark suite for file listing and filtering performance
The repo has benches/criterion.rs but it appears minimal. Given that xplr is positioned as 'minimal, fast' and handles sorting/filtering (docs show docs/en/src/sorting.md, filtering.md), adding benchmarks for directory traversal, filtering, and column rendering would prevent performance regressions. The rayon dependency (1.11) suggests parallel operations that should be benchmarked.
- [ ] Expand benches/criterion.rs with benchmarks for directory listing performance
- [ ] Add benchmarks for regex filtering (regex crate 1.12) on large file lists
- [ ] Add benchmarks for sorting operations (natord crate suggests natural sorting)
- [ ] Add benchmarks for column rendering (lscolors integration) with ANSI colors
- [ ] Document benchmark results in RELEASE.md for version releases
🌿Good first issues
- Add integration tests for key bindings: The CI setup exists (ci.yml, assert_cmd in dev-dependencies) but benches/criterion.rs only has performance tests. Create tests/integration_test.rs covering the default key bindings listed in docs/en/src/default-key-bindings.md against a mock filesystem.
- Document the Lua API reference: docs/en/src/ has configuration.md and configure-key-bindings.md but no dedicated 'Lua API reference' listing all exposed Rust functions callable from Lua scripts. Generate or write src/lua/api_docs.md and link it in SUMMARY.md.
- Add MIME type filtering examples: The codebase has mime_guess 2.0 as a dependency and filtering.md in docs, but no concrete examples showing how to filter by file type (e.g., 'show only .rs files') in Lua or YAML config. Add a docs/en/src/filtering-by-mime-type.md section with runnable examples.
⭐Top contributors
Click to expand
Top contributors
- @sayanarijit — 72 commits
- @ElSamhaa — 12 commits
- @duganchen — 3 commits
- @doums — 2 commits
- @Copilot — 1 commits
📝Recent commits
Click to expand
Recent commits
1751065— use cargo_bin!() (#769) (sayanarijit)db0e781— Fix docs links (#767) (sayanarijit)f20c1da— Fix link (sayanarijit)7b30fa6— v1.1.0 (sayanarijit)5d144e2— Optimize performance using rayon (#754) (sayanarijit)bed95bf— Replace deprecated markdown link checker with maintained fork and add Linkspector (#765) (Copilot)17ff805— add udisks.xplr to awesome plugins (#763) (LordMZTE)058fc85— Minor cleanup (sayanarijit)df09cab— Create file or dir using :cc (#759) (sayanarijit)5adec2b— allow reading of luajit bytecode as init files (#757) (LyxHuston)
🔒Security observations
- Medium · Lua Script Execution Risk —
Cargo.toml - [dependencies.mlua] with features=['luajit', 'serialize', 'send']. The codebase integrates mlua with luajit for executing Lua scripts. While this provides extensibility, it introduces potential security risks if user-supplied or untrusted Lua scripts are executed without proper sandboxing. The 'vendored-lua' feature compiles Lua from source, which is good for supply chain security, but runtime script execution from plugins could be exploited. Fix: Implement strict Lua script sandboxing, validate and verify plugin sources before execution, provide clear documentation about plugin security implications, and consider implementing a plugin signing/verification mechanism. - Medium · Regular Expression Denial of Service (ReDoS) Potential —
Cargo.toml - [dependencies] regex = '1.12'. The codebase uses the 'regex' crate (version 1.12) for pattern matching operations. While regex 1.12 uses the 'regex-automata' engine which is resistant to catastrophic backtracking, user-controlled regex patterns (potentially from configuration or filters) could still cause performance degradation if not properly validated. Fix: Validate and limit regex patterns from user input, implement timeouts for regex operations, document regex pattern constraints in configuration documentation, and consider using regex pattern whitelisting for critical operations. - Low · Unsafe Dependencies via libc —
Cargo.toml - [dependencies] libc = '0.2'. Direct dependency on 'libc' (version 0.2) provides low-level system calls. While necessary for terminal UI operations, any unsafe code using libc requires careful auditing. The codebase appears to be using it for legitimate TUI purposes, but unsafe code blocks should be minimized. Fix: Minimize unsafe code blocks using libc, thoroughly review any unsafe { } blocks in the codebase, maintain updated libc versions, and add comments explaining why unsafe code is necessary. - Low · Command Execution via 'which' Crate —
Cargo.toml - [dependencies] which = '8.0'. The 'which' crate (version 8.0) is used to locate executables in system PATH. If file paths or command names derived from user input are passed to this crate without proper validation, it could lead to command injection or execution of unintended binaries. Fix: Validate and sanitize any user-supplied input before using with the 'which' crate, maintain a whitelist of allowed commands, avoid constructing command names from untrusted sources, and use absolute paths when possible. - Low · YAML Deserialization Risks —
Cargo.toml - [dependencies] serde_yaml = '0.9'. The 'serde_yaml' crate (version 0.9) is used for configuration parsing. YAML deserialization can be vulnerable if it processes untrusted or malicious YAML files, potentially leading to code execution through certain YAML features. Fix: Only deserialize YAML from trusted configuration sources, avoid deserializing YAML from user-uploaded files without validation, implement strict type checking during deserialization, and consider using a more restrictive data format like JSON for untrusted sources. - Low · JSON Deserialization —
Cargo.toml - [dependencies] serde_json = '1.0'. The 'serde_json' crate is used for JSON processing. While generally safer than YAML, deserializing large or deeply nested JSON from untrusted sources could cause denial-of-service through memory exhaustion. Fix: Implement size limits on JSON inputs, validate JSON structure before full deserialization, implement timeout mechanisms for JSON parsing operations, and monitor memory usage during JSON processing. - Low · Path Traversal via path-absolutize —
Cargo.toml - [dependencies] path-absolutize = '3.1'. The 'path-absolutize' crate is used for path resolution. Improper validation of file paths could lead to directory traversal attacks if the application processes user-supplied paths without adequate checks. Fix: Validate and canonicalize all user-supplied file paths, implement path containment checks to prevent traversal outside intended directories, use Path::canonicalize() to resolve symlinks, and reject paths containing suspicious patterns like '..'.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.