██▓ ██████ ▒█████ █████▒██████ ██████
▓██▒ ▒██ ▒ ▒██▒ ██▒▓██ ▒██ ▒ ▒██ ▒
▒██░ ░ ▓██▄ ▒██░ ██▒▒████ ░▓██▄ ░ ▓██▄
▒██░ ▒ ██▒▒██ ██░░▓█▒ ░▒ ██▒ ▒ ██▒
░██████▒▒██████▒▒░ ████▓▒░░▒█░ ▒██████▒▒██████▒▒
░ ▒░▓ ░▒ ▒▓▒ ▒ ░░ ▒░▒░▒░ ▒ ░ ▒ ▒▓▒ ▒ ░ ▒▓▒ ▒ ░
░ ░ ▒ ░░ ░▒ ░ ░ ░ ▒ ▒░ ░ ░ ░▒ ░ ░ ░▒ ░ ░
░ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ░
░ ░ ░ ░ ░ ░
"Rewritten in Rust. Faster. Safer. The same cyberpunk soul."
// WHAT IS THIS
lsofrs — List System Open Files in Rust — v4.2.0
A Rust rewrite of lsofng, the modernized lsof diagnostic tool. Maps the invisible topology between processes and the files they hold open: regular files, directories, sockets, pipes, devices, kqueues — anything the kernel touches.
If a process has a file descriptor, lsofrs sees it.

// JACK IN — BUILD FROM SOURCE
Or install directly:
Install the man page:
// USAGE
Network Filters
Output Formats
Selection Combinators
// ADVANCED MODES
Top-N Dashboard (--top)
Live auto-refreshing dashboard of the top processes sorted by FD count. Like iotop for file descriptors — shows FD type distribution bars, delta tracking, and per-process breakdowns.
Top-specific keys: s cycle sort, r reverse, +/- show more/fewer, b toggle bar, d toggle delta. See Interactive Controls for common keys.
File Watch (--watch FILE)
Monitor who opens and closes a specific file over time. Prints timestamped +OPEN/-CLOSE events as they happen — like a lightweight inotifywait / fs_usage for a single path.
Each event shows timestamp, open/close tag, PID, user, FD, and command. When piped, prints a single snapshot and exits.
Stale FDs (--stale)
Find file descriptors pointing to deleted files — a common source of disk space leaks, zombie file handles, and security issues.
Listening Ports (--ports)
Quick "what's listening where" summary — like ss -tlnp but cross-platform (macOS + Linux).
Pipe Chain (--pipe-chain)
Trace pipe and unix socket pairs between processes — visualize the IPC topology.
Network Map (--net-map)
Group network connections by remote host — see which servers your system talks to and how many connections each has.
CSV Export (--csv)
Pure CSV output for pipelines, spreadsheets, and data analysis. RFC 4180-compliant quoting.
Process Tree (--tree)
Hierarchical process tree view with FD counts, type breakdowns, and network connection counts. Like pstree meets lsof.
Each node shows: PID, user, FD count, command name, type breakdown ([REG:12 IPv4:3 PIPE:2]), and network connection count. Notable files (sockets, pipes) are listed inline under each process.
Live Monitor (--monitor / -W)
Full-screen alternate-buffer display like top(1). Auto-refreshes with interactive controls.
Controls: s=sort, r=reverse, f=filter, p=pause, ?=help, q=quit
Follow Mode (--follow PID)
Watch a single process's FDs in real-time. New opens highlighted +NEW in green, closes -DEL in red.
FD Leak Detection (--leak-detect)
Monitors per-process FD counts over time. Flags processes with monotonically increasing FD counts.
Summary / Statistics (--summary)
Aggregate FD breakdown with bar charts, top processes, per-user totals. Add -r N for live auto-refreshing TUI mode.
Delta Highlighting (--delta)
Color-code changes between repeat iterations. New FDs in green, gone in red.
// CYBERPUNK THEME
When output goes to a TTY, lsofrs activates cyberpunk-themed column headers and ANSI coloring:
| Piped | TTY |
|---|---|
| COMMAND | PROCESS |
| PID | PRC |
| USER | H4XOR |
| TYPE | CL4SS |
| DEVICE | DEV/ICE |
| SIZE/OFF | BYT3/0FF |
| NODE | N0DE |
| NAME | T4RGET |
When piped or redirected, plain headers and no colors are used — safe for scripts.
// INTERACTIVE CONTROLS
All live TUI modes (--top, --summary -r, and future modes) share a common keybinding framework via the TuiMode trait.
Common keys (available in all live modes):
| Key | Action |
|---|---|
1-9 |
Set refresh interval (seconds) |
</> |
Fine-adjust refresh interval (±1s) |
p |
Pause/resume data collection |
?/h |
Toggle help overlay |
q/Esc/Ctrl-C |
Quit |
--top additional keys:
| Key | Action |
|---|---|
s |
Cycle sort column (FDs→PID→USER→REG→SOCK→PIPE→OTHER→DELTA→CMD) |
r |
Reverse sort order |
+/- |
Show more/fewer processes (±5) |
b |
Toggle distribution bar column |
d |
Toggle delta column |
Non-TTY (piped) output always does a single-shot print and exits — no TUI, no key handling.
// ARCHITECTURE
src/
├── main.rs # CLI entry point, dispatch, repeat/leak-detect loops
├── cli.rs # clap argument definitions + custom help display
├── types.rs # Core data structures (Process, OpenFile, SocketInfo, etc.)
├── darwin.rs # macOS libproc FFI — process/FD enumeration (rayon parallel)
├── linux.rs # Linux /proc filesystem — process/FD enumeration (rayon parallel)
├── freebsd.rs # FreeBSD sysctl + procfs — process/FD enumeration
├── filter.rs # Selection & filtering (PID, user, command, FD, network)
├── output.rs # Columnar & field output formatting, ANSI theming
├── json.rs # JSON serialization via serde
├── monitor.rs # Live full-screen mode (crossterm alternate screen)
├── follow.rs # Single-process FD tracking with status transitions
├── leak.rs # Circular-buffer leak detector
├── delta.rs # Iteration-diff engine for change highlighting
├── summary.rs # Aggregate statistics with bar charts
├── tree.rs # Process tree view with FD inheritance
├── tui_app.rs # Shared TUI framework (TuiMode trait, crossterm)
├── top.rs # Live top-N FD dashboard (TuiMode)
├── watch.rs # File watch — monitor opens/closes over time
├── stale.rs # Stale FD finder — deleted files still held open
├── ports.rs # Listening ports summary (like ss -tlnp)
├── pipe_chain.rs # Pipe/socket IPC topology between processes
├── csv_out.rs # CSV export (RFC 4180)
└── net_map.rs # Network connections grouped by remote host
lsofrs.1 # Man page (roff)
completions/
└── _lsofrs # Zsh completion function
Shell Completions
Zsh completions are provided in completions/_lsofrs. To install:
# or symlink into your fpath
# then reload
&&
Platform Support
Supports macOS/Darwin (libproc FFI), Linux (/proc filesystem), and FreeBSD (sysctl + procfs). Platform modules are gated behind #[cfg(target_os)]. Process gathering is parallelized with rayon.
Key Design Decisions
- Zero-copy FFI: Raw
repr(C)structs matched to Darwin kernel headers. No intermediate parsing. - Parallel gathering: Per-PID FD enumeration parallelized with rayon.
- Streaming output: Processes are gathered, filtered, and printed in a single pass.
- Shared TUI framework:
TuiModetrait — all live modes get common keybindings, alternate screen, and atomic frame rendering. - serde for JSON: Derive-based serialization, no hand-rolled escaping.
- clap for CLI: Derive-based argument parsing with full help generation.
// PERFORMANCE
Benchmarked on macOS with hyperfine (10 runs, 3 warmup, ~900 processes / ~8000 open files, rayon parallel gathering):
All Open Files (default)
| Tool | Mean | Min–Max | Speedup |
|---|---|---|---|
| lsofrs (Rust) | 58 ms | 40–111 ms | — |
| lsof 4.91 (C) | 5,555 ms | 5,194–8,343 ms | 95x slower |
| lsofng (C) | 13,202 ms | 11,299–16,336 ms | 226x slower |
Network Connections (-i TCP)
| Tool | Mean | Min–Max | Speedup |
|---|---|---|---|
| lsofrs | 9 ms | 9–10 ms | — |
| lsof 4.91 | 5,117 ms | 5,098–5,229 ms | 555x slower |
| lsofng | 10,520 ms | 10,097–13,792 ms | 1,141x slower |
Terse Output (-t, PIDs only)
| Tool | Mean | Min–Max | Speedup |
|---|---|---|---|
| lsofrs | 14 ms | 12–16 ms | — |
| lsofng | 149 ms | 133–216 ms | 10x slower |
| lsof 4.91 | 273 ms | 249–298 ms | 19x slower |
Structured Output (-J JSON / -F field)
| Tool | Mean | Min–Max | Speedup |
|---|---|---|---|
lsofrs -J |
41 ms | 40–42 ms | — |
lsofng -J |
164 ms | 142–336 ms | 4x slower |
lsof -F pcfn |
5,552 ms | 5,171–7,391 ms | 134x slower |
The rayon-parallelized per-PID FD enumeration combined with zero-copy FFI structs gives lsofrs a 95–1,141x advantage over traditional lsof implementations.
// LICENSE
MIT License — Jacob Menke
// CREDITS
Rust rewrite of lsofng by Jacob Menke, which itself is a modernized fork of the original lsof by Vic Abell.