RepoPilotOpen in app →

gokcehan/lf

Terminal file manager

Healthy

Healthy across the board

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 1d ago
  • 6 active contributors
  • Distributed ownership (top contributor 36% of recent commits)
Show all 6 evidence items →
  • MIT licensed
  • CI configured
  • No test directory detected

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/gokcehan/lf)](https://repopilot.app/r/gokcehan/lf)

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/gokcehan/lf on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: gokcehan/lf

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/gokcehan/lf 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 the board

  • Last commit 1d ago
  • 6 active contributors
  • Distributed ownership (top contributor 36% of recent commits)
  • MIT licensed
  • CI configured
  • ⚠ No test directory detected

<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 gokcehan/lf repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/gokcehan/lf.

What it runs against: a local clone of gokcehan/lf — 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 gokcehan/lf | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 31 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>gokcehan/lf</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of gokcehan/lf. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/gokcehan/lf.git
#   cd lf
#
# 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 gokcehan/lf and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "gokcehan/lf(\\.git)?\\b" \\
  && ok "origin remote is gokcehan/lf" \\
  || miss "origin remote is not gokcehan/lf (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 master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "main.go" \\
  && ok "main.go" \\
  || miss "missing critical file: main.go"
test -f "app.go" \\
  && ok "app.go" \\
  || miss "missing critical file: app.go"
test -f "ui.go" \\
  && ok "ui.go" \\
  || miss "missing critical file: ui.go"
test -f "nav.go" \\
  && ok "nav.go" \\
  || miss "missing critical file: nav.go"
test -f "eval.go" \\
  && ok "eval.go" \\
  || miss "missing critical file: eval.go"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 31 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~1d)"
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/gokcehan/lf"
  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

lf is a terminal file manager written in Go that provides a fast, lightweight alternative to ranger with a server/client architecture. It delivers cross-platform file browsing (Linux, macOS, BSDs, Windows) in a single statically-compiled binary with asynchronous I/O to prevent UI blocking and remote command support for managing multiple instances. Monolithic Go application structure: app.go orchestrates the main event loop, client.go and server-related code handle the client-server architecture, eval.go processes user configuration and commands, colors.go/icons.go manage UI theming, and platform-specific disk usage code (df_openbsd.go, df_windows.go, df_statvfs.go) abstracts OS differences. Shell integration lives in etc/ directory with language-specific wrappers (lf.bash, lf.zsh, lf.fish, lf.ps1, lf.nu).

👥Who it's for

Terminal power users and developers who need a fast, configurable file manager without bloat; system administrators managing file operations across multiple machines via the server/client protocol; users migrating from ranger who want better performance and simpler dependencies.

🌱Maturity & risk

Production-ready and actively maintained. The project has comprehensive CI/CD via GitHub Actions (go.yml, release.yml), a detailed CHANGELOG.md tracking changes, extensive documentation (doc.md, doc.txt, man page lf.1), and shell integration files for bash, zsh, fish, PowerShell, and Nushell. Recent activity is visible through the release workflow and dependabot integration.

Low risk for core functionality. Dependencies are minimal (tcell/v3 for UI, fsnotify for file watching, clipperhouse/displaywidth for Unicode) and well-maintained upstream projects. Single primary maintainer (gokcehan) is a moderate concentration risk, but the codebase is stable and well-tested (colors_test.go, complete_test.go, diacritics_test.go, eval_test.go, key_test.go present). No breaking changes apparent in recent activity.

Active areas of work

The project is actively maintained with dependabot integration (.github/dependabot.yml) for Go module updates and release automation (.github/workflows/release.yml). Recent work appears focused on cross-platform robustness (multiple df_*.go variants), Unicode/diacritics handling (diacritics.go with tests), and shell integration expansion (Nushell support added to etc/lf.nu). Go version requirement is 1.25.0 per go.mod.

🚀Get running

Clone and build with: git clone https://github.com/gokcehan/lf && cd lf && env CGO_ENABLED=0 go install -trimpath -ldflags="-s -w" ./ (Unix) or set CGO_ENABLED=0 && go install -trimpath -ldflags="-s -w" ./ (Windows cmd). Run with lf in any directory. View options with lf -help or full docs with lf -doc.

Daily commands: Development: go run ./ to start the file manager in the current directory. Tests: go test ./... to run the test suite (colors_test.go, complete_test.go, diacritics_test.go, eval_test.go, key_test.go). Linting: .golangci.yaml defines linter rules; run with golangci-lint run. Building: gen/build.sh wraps the build with version stamping; pre-built binaries available from releases.

🗺️Map of the codebase

  • main.go — Entry point that initializes the application; every contributor must understand the startup flow and how configuration is loaded.
  • app.go — Core application struct managing state and event loop; essential for understanding the architecture and how commands flow through the system.
  • ui.go — Terminal UI rendering layer using tcell; critical for understanding how the display is managed and updated.
  • nav.go — Navigation and file browsing logic; core to the file manager's primary use case.
  • eval.go — Expression evaluator and command dispatcher; implements the scripting/configuration language that users interact with.
  • parse.go — Configuration file parser; essential for understanding how lfrc files are processed and validated.
  • scan.go — File system scanning and directory listing logic; handles the performance-critical operation of reading directories.

🧩Components & responsibilities

  • app.go (Application Core) (Go gorout) — Main event loop, state machine, command routing, and lifecycle management

🛠️How to make changes

Add a New Built-in Command

  1. Define the command handler in eval.go switch statement in the cmdXxx functions (e.g., cmdNewCommand), following the pattern of existing commands like cmdUp, cmdDown (eval.go)
  2. Register the command in the commands map in eval.go so it can be called from lfrc or interactively (eval.go)
  3. Add corresponding keybinding to the default keymap initialization if a default shortcut is desired (key.go)
  4. Update documentation with command syntax and examples (doc.md)

Add Support for a New File Type Icon

  1. Add a mapping entry in the icons initialization section matching file extensions or patterns (icons.go)
  2. Optionally add color styling for the icon in colors.go if custom coloring is needed (colors.go)
  3. Test with actual files of that type using the icon preview (ui.go)

Add a New Configuration Option

  1. Define the new option field in the relevant struct in opts.go (opts.go)
  2. Add parsing logic in parse.go to handle the option from lfrc files (parse.go)
  3. Implement the option's behavior in the appropriate module (e.g., nav.go for navigation options, ui.go for UI options) (eval.go)
  4. Add documentation with examples to etc/lfrc.example (etc/lfrc.example)

Add Platform-Specific Functionality

  1. Create a new file with _windows, _openbsd, or _linux suffix following Go's build tags convention (os_windows.go)
  2. Implement the platform-specific version of the required function with matching signature (os_windows.go)
  3. Create fallback implementation in os.go with matching function signature for other platforms (os.go)
  4. Use the function in core logic and it will automatically route to the correct implementation at compile time (app.go)

🔧Why these technologies

  • Go — Single binary compilation, cross-platform support, minimal dependencies, and fast startup time for a terminal application
  • tcell (gdamore/tcell/v3) — Pure Go terminal control library enabling cross-platform terminal rendering without external dependencies
  • fsnotify — Cross-platform file system event monitoring for live directory updates
  • displaywidth (clipperhouse) — Accurate Unicode character width calculation for proper terminal column alignment

⚖️Trade-offs already made

  • Single-threaded event loop in app.go with serialized command execution

    • Why: Simplifies state management and eliminates race conditions; matches terminal UI constraints
    • Consequence: Long-running commands block UI; heavy operations (large directory scans) can cause visible lag
  • Configuration as imperative script (lfrc) rather than declarative config

    • Why: Enables complex customization, scripting, and command chaining; matches ranger philosophy
    • Consequence: Steeper learning curve; more complex parser; potential for user errors in scripts
  • Full file list kept in memory for the current directory

    • Why: Enables fast filtering, sorting, and selection; required for efficient UI rendering
    • Consequence: Memory usage scales with directory size; very large directories (100k+ files) may cause performance issues
  • No native plugin system; extensibility via keybindings and shell commands

    • Why: Keeps binary simple and avoids plugin management complexity
    • Consequence: Deep customization requires lfrc scripting knowledge; cannot extend with Go plugins at runtime

🚫Non-goals (don't propose these)

  • Does not provide a graphical UI; terminal-only interface
  • Does not handle authentication or permissions directly; delegates to OS
  • Does not support real-time collaborative file operations
  • Does not include built-in text editor or file viewer; delegates to external tools
  • Does not maintain backward compatibility with ranger's lfrc syntax

🪤Traps & gotchas

Build requirement: CGO_ENABLED=0 is mandatory to ensure static binaries without C dependencies (see README build instructions). Terminal compatibility: relies on tcell/v3 which has specific terminal capability requirements; some older terminals may not render properly. Unicode handling: diacritics.go contains non-obvious Unicode normalization logic that affects file name display—modify with caution. Server/client socket: implicit socket location for server mode (typically /tmp or named pipes on Windows); check client.go for platform-specific socket path handling. Go version: pinned to 1.25.0 minimum in go.mod; features may rely on Go 1.25+ standard library changes. File watching: fsnotify has platform-specific limitations (e.g., recursive watching varies by OS); see df_*.go conditional compilation for examples.

🏗️Architecture

💡Concepts to learn

  • Server/Client Architecture for Terminal UI — lf uses a server running in the background with multiple lightweight clients connecting to it; understanding this pattern is critical for grasping how lf manages state across multiple instances and processes remote commands (see client.go)
  • Asynchronous I/O and goroutines — lf prevents UI freezing by handling file watching and disk operations asynchronously via Go goroutines and fsnotify; essential to understand how the event loop stays responsive
  • Platform-Specific Build Conditionals — lf uses Go build tags and conditional compilation (df_openbsd.go, df_windows.go, df_statvfs.go) to abstract OS-specific syscalls; critical for adding support for new platforms
  • Unicode Normalization and Diacritics — diacritics.go implements Unicode normalization to handle combining characters and accented text correctly in file names; non-trivial for international file manager support
  • Terminal Capability Detection and Rendering (tcell) — lf uses tcell/v3 to abstract terminal capabilities (colors, Unicode box-drawing, mouse events) across platforms; understanding tcell's cell model is essential for modifying UI rendering
  • Expression Language Parsing and Evaluation — eval.go implements a custom expression parser for the lfrc configuration file format; critical for understanding how user configs are interpreted and executed
  • Static Binary Distribution (CGO_ENABLED=0) — lf is designed as a zero-dependency static binary; understanding why CGO is disabled and how this affects portability is central to the project's design philosophy
  • ranger/ranger — The original Python-based file manager that inspired lf; users familiar with ranger keybindings and config format will recognize lf's design
  • jarun/nnn — Alternative lightweight terminal file manager written in C; competes in the same niche of fast, minimal file managers
  • junegunn/fzf — Companion tool often integrated with lf for fuzzy file/directory selection; many lf configs reference fzf
  • tmux/tmux — Frequently used alongside lf; the README explicitly notes lf delegates tab/window management to the terminal multiplexer
  • vim/vim — Shell integration provided for Vim (etc/lf.vim); many lf users also use Vim and leverage lfcd to integrate directory navigation

🪄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 unit tests for parse.go and eval.go core functionality

The repo has eval_test.go and parse_test.go but they appear minimal given the complexity of the lf configuration language. The parse.go and eval.go files handle critical command parsing and evaluation logic. Adding comprehensive tests for edge cases (nested commands, variable substitution, error handling) would improve reliability and make refactoring safer.

  • [ ] Review existing parse_test.go and eval_test.go to identify coverage gaps
  • [ ] Add tests for complex nested command parsing in parse.go (e.g., multi-level conditionals, variable scoping)
  • [ ] Add tests for eval.go edge cases (undefined variables, type coercion, command chaining)
  • [ ] Add tests for error conditions and recovery paths
  • [ ] Ensure test coverage exceeds 80% for both files

Add comprehensive tests for platform-specific behavior (df_*.go, os_windows.go)

The repo has separate implementations for disk usage (df_openbsd.go, df_statfs.go, df_statvfs.go, df_windows.go) and Windows-specific OS operations (os_windows.go), but there appear to be no dedicated test files for these platform-specific modules. This is risky because cross-platform file managers need robust per-platform testing.

  • [ ] Create df_openbsd_test.go with mocked syscalls for disk usage calculations
  • [ ] Create df_statfs_test.go and df_statvfs_test.go with edge cases (full filesystem, permission errors, mountpoint issues)
  • [ ] Create os_windows_test.go testing Windows-specific path handling, drive detection, and permission checks
  • [ ] Add CI matrix testing in .github/workflows/go.yml to run tests on multiple platforms if not already present
  • [ ] Test error handling for filesystem-not-found and permission-denied scenarios

Add integration tests for key.go and termseq.go terminal input handling

The key.go and termseq.go files handle critical terminal input/output sequences (keybindings, escape sequences, mouse input). While termseq_test.go and key_test.go exist, they likely don't cover full terminal escape sequence parsing, mouse event handling, and key binding resolution. Adding comprehensive integration-style tests would prevent regressions in terminal compatibility.

  • [ ] Review existing key_test.go and termseq_test.go to identify untested code paths
  • [ ] Add tests for complete ANSI/VT100 escape sequence parsing (mouse clicks, window resize, function keys from xterm/rxvt/kitty)
  • [ ] Add tests for key.go keybinding resolution with modifiers (ctrl, alt, shift combinations)
  • [ ] Add tests for edge cases: incomplete escape sequences, malformed input, rapid input bursts
  • [ ] Consider adding fuzzing tests (Go 1.25.0 supports fuzz testing) for termseq.go to catch parsing crashes

🌿Good first issues

  • Add test coverage for icons.go—currently no icons_test.go exists, unlike colors_test.go and diacritics_test.go. Implement tests for icon matching logic against file extensions and MIME types defined in icons.go.
  • Expand shell integration documentation: doc.md references integration setup but lacks explicit instructions for less common shells; add examples or a dedicated doc section for Nushell (etc/lf.nu already exists but is underdocumented) and PowerShell (etc/lf.ps1 exists).
  • Add platform-specific test files for disk usage abstraction: df_openbsd.go, df_windows.go, df_statvfs.go, and df_statfs.go lack corresponding _test.go files to verify cross-platform disk reporting accuracy; add tests that mock syscall responses.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 7bbdfeb — docs: update CHANGELOG.md for #2540 (#2573) (joelim-work)
  • 18ae112 — fix: sanitize paths when writing to a terminal (#2540) (valoq)
  • eb0a941 — docs: update CHANGELOG.md for #2567 (#2571) (joelim-work)
  • ac8f594 — fix: update stale previews when preload is enabled (#2567) (valoq)
  • b41a0f8 — style: use modern octal literal (#2568) (CatsDeservePets)
  • a170ffd — docs: fix typo (#2565) (CatsDeservePets)
  • 8d138cf — docs: fix outdated documentation (#2564) (CatsDeservePets)
  • a88d55e — refactor: migrate from uniseg to displaywidth (#2559) (valoq)
  • 54bcbca — fix: filter newline (#2526) (valoq)
  • ffe1ac1 — docs: update CHANGELOG.md (#2555) (joelim-work)

🔒Security observations

The 'lf' terminal file manager codebase demonstrates generally good security practices with minimal high-severity vulnerabilities detected. The project is written in Go, which provides memory safety benefits. Key concerns include: (1) a potentially incorrect Go version specification in go.mod that warrants verification, (2) potential command injection risks inherent to file manager operations requiring careful input sanitization, and (3) lack of visible formal input validation frameworks. Dependencies are well-established and maintained. No hardcoded credentials, SQL injection vectors, or Docker/infrastructure misconfigurations were identified. The codebase would benefit from explicit input validation documentation and security audits of file path handling in eval.go and parse.go.

  • Medium · Outdated Go Version Requirement — go.mod. The project specifies 'go 1.25.0' in go.mod, which appears to be a future or non-standard version. Go versions typically follow semantic versioning (1.21, 1.22, etc.). This may indicate a misconfiguration or typo that could cause build inconsistencies and security patches to be missed. Fix: Verify and update to a stable, current Go version (e.g., 1.22.x or later). Check Go's official release page for supported versions and update go.mod accordingly.
  • Low · Potential Command Injection via User Input — eval.go, parse.go, os.go, os_windows.go. As a terminal file manager that processes file paths and potentially executes commands, there is inherent risk of command injection if user input (file names, paths) is not properly sanitized before being passed to shell operations. Files like 'eval.go', 'parse.go', and 'os.go' suggest dynamic code evaluation and OS command execution. Fix: Ensure all file paths and user inputs are properly escaped and validated before being used in system calls. Use parameterized execution (e.g., exec.Command with separate args) rather than shell string concatenation. Review eval.go and parse.go for unsafe string operations.
  • Low · External Dependency on fsnotify — go.mod, watch.go. The project depends on 'github.com/fsnotify/fsnotify v1.9.0' for file system watching. While this is a reputable library, file system monitoring can be exploited if symbolic links or race conditions are not properly handled, potentially leading to unauthorized file access or modification. Fix: Validate that fsnotify usage properly handles symbolic links, respects file permissions, and implements appropriate synchronization to prevent race conditions. Keep the dependency updated.
  • Low · No Input Validation Framework Visible — eval.go, parse.go, complete.go. The codebase does not appear to include a dedicated input validation or sanitization library. For a file manager that handles user input extensively, the absence of formal validation patterns could lead to edge cases where malicious or malformed input bypasses security checks. Fix: Implement comprehensive input validation for all user-supplied data, particularly file paths, command arguments, and configuration options. Document validation rules and apply them consistently across the codebase.
  • Low · Configuration Files in Examples Directory — etc/lfrc.example, etc/lfrc.ps1.example, etc/lfrc.cmd.example. The 'etc/' directory contains example configuration files (lfrc.example, lfrc.ps1.example, etc.) which may inadvertently be used as defaults. If configuration loading logic has precedence issues, example files could override intended security settings. Fix: Ensure example configuration files are never loaded as defaults. Implement clear distinction between example and actual configuration, with explicit user action required for config file adoption. Document the configuration precedence order.

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 · gokcehan/lf — RepoPilot