>_EXECUTIVE SUMMARY
lsofrs is a single-binary Rust implementation of lsof. Three platform backends (src/darwin.rs via libproc FFI, src/linux.rs via /proc, src/freebsd.rs via sysctl + procfs) feed a shared Vec<Process> through a composable filter pipeline (src/filter.rs) into one of fourteen output / live-monitor modes. Per-PID FD enumeration runs on rayon's work-stealing pool; every TTY mode shares a TuiMode trait (src/tui_app.rs) for common keybindings, alternate-screen entry/exit, and atomic frame rendering. 23,441 production Rust lines + 8,560 test lines + 1,662 #[test] functions. hyperfine wall-clock: 14.2 ms for the default invocation vs 169.8 ms for lsof 4.91 (~12× speedup), 21× on terse PID output.
Source Distribution — 32,001 lines
Production: 28 files in src/. Tests: 10 integration modules in tests/ + inline #[cfg(test)] blocks in 20 of the production files. Total #[test] count is taken from grep -rh '#[test]' tests/*.rs src/*.rs | wc -l.
~BENCHMARK POSITION
hyperfine wall-clock (10 runs, 3 warmup, ~470 processes / ~5000 open files on macOS). Reproducible from README § PERFORMANCE. The rayon-parallel per-PID enumeration + zero-copy FFI + OnceCell-cached getpwuid together push the steady-state cost below 15 ms.
| Workload | lsofrs (Rust) | lsof 4.91 (C) | lsofng (C) | Speedup vs lsof |
|---|---|---|---|---|
| All open files (default) | 14.2 ms | 169.8 ms | 173.0 ms | 12× |
Network only (-i TCP) |
7.2 ms | 91.7 ms | 88.1 ms | 13× |
Terse PIDs (-t) |
6.9 ms | 101.4 ms | 142.9 ms | 15× |
Structured JSON (-J) |
29.3 ms | 156.1 ms (-F pcfn) |
136.7 ms | 5× |
Where the speedup comes from
Per-PID FD enumeration runs on rayon's work-stealing pool — CPU count = parallel degree. Darwin uses raw #[repr(C)] structs sized to libproc's kernel headers, so the gather pass never allocates per-FD. v4.8.3 added a OnceCell-cached getpwuid path, precomputed canonical filter paths, and removed every per-record allocation from the hot loop (see commit 1464becf31).
Why feature set still beats both incumbents
Modes that ship in lsofrs but neither lsof nor lsofng: unified 7-tab TUI, top-N FD dashboard, summary bar charts, stale-FD finder, listening-ports view, process tree with FD-type breakdown, pipe / unix-socket IPC map, net-by-remote-host view, file-open/close watch, single-PID follow, FD-leak detector, delta highlighting, CSV export, 31 themes with editor.
Single-binary footprint
One static lsofrs / lsf binary — clap derive parser, serde JSON, RFC 4180 CSV, ratatui TUI, crossterm terminal control, nix POSIX bindings, libc FFI, rayon work-stealing, regex selector, chrono timestamps, TOML config — all linked in. 13 direct dependencies, all foundational crates likely to still build cleanly in 2035 (clap, serde, libc, nix, regex, rayon, ratatui, crossterm, chrono, toml, dirs, users, serde_json).
Cross-platform parity
All three platform backends return the same Process + OpenFile + SocketInfo shapes from src/types.rs. Everything above filter.rs is platform-agnostic, so adding a new TUI tab or output format doesn't fan out across three implementations — it ships once.
#SUBSYSTEM BREAKDOWN
Source partitioned by role. TUI & theming dominate at 31.3% of production Rust — tui_tabs.rs alone is 5,308 lines for the unified 7-tab dashboard (mouse, tooltips, theme chooser + editor). Selection / filter is the second-biggest subsystem (2,659 lines) because every selector composes with every other under OR / AND mode with regex, range, and negation grammar.
| Subsystem | Key Files | Lines | % of prod | Share | Description |
|---|---|---|---|---|---|
| TUI & Theming | tui_tabs, tui_app, theme, config | 7,221 | 31.3% | Unified 7-tab dashboard (--tui) with mouse + tooltips + theme chooser/editor (tui_tabs.rs, 5,308); shared TuiMode trait + ratatui framework (tui_app.rs); 31 named palettes via ThemeName enum (theme.rs); TOML config persistence at ~/.lsofrs.conf (config.rs) | |
| Selection / Filter | filter | 2,812 | 12.0% | PID / PGID / user / command / FD / network-spec / path selectors, OR-mode (default) and AND-mode (-a) composition, comma-lists, ranges (0-10), exclusion (^root), regex (/…/), precomputed canonical paths | |
| Platform Gather | darwin, linux, freebsd | 2,908 | 12.6% | macOS libproc FFI with zero-copy #[repr(C)] structs (darwin.rs, 1,253); /proc reader with parallel per-PID rayon (linux.rs, 820); sysctl + procfs decoder including kqueue (freebsd.rs, 835) | |
| Live Modes | top, summary, monitor, follow, watch, leak, delta | 3,787 | 16.4% | Live top-N FD dashboard (top.rs, 1,008); aggregate summary + bars in static and live form (summary.rs, 904); classic full-screen monitor (monitor.rs); single-PID follow (follow.rs); file-open/close watch (watch.rs); circular-buffer FD-leak detector (leak.rs); iteration-diff engine for change highlighting (delta.rs) | |
| Single-Shot Views | tree, ports, stale, pipe_chain, net_map | 2,285 | 9.9% | Process tree with FD inheritance + per-PID type breakdown (tree.rs); listening-ports summary like ss -tlnp (ports.rs); deleted-file FD finder (stale.rs); pipe / unix-socket IPC map (pipe_chain.rs); connections grouped by remote host (net_map.rs) | |
| CLI & Dispatch | cli, main, lib, strutil | 1,722 | 7.5% | clap derive parser with 38 #[arg] attributes and custom help display (cli.rs, 1,341); mode-dispatch entry point including repeat / leak-detect loops (main.rs, 282); library facade gated by #[cfg(target_os)] (lib.rs); safe UTF-8 truncation for fixed-width column display, no mid-codepoint slices (strutil.rs) | |
| Output / Serialization | output, json, csv_out | 1,608 | 7.0% | Columnar + field (-F) formatting with TTY-detected ANSI theming (output.rs, 770); serde-backed JSON array (json.rs, 441); RFC 4180-compliant CSV with proper quoting (csv_out.rs, 397) | |
| Type System | types | 867 | 3.8% | Shared cross-platform data shapes: Process, OpenFile, SocketInfo, NetSpec, FdType, theme enums — 11 public struct / enum definitions, all #[derive(Serialize, Deserialize)] for the JSON contract | |
| Tests | tests/*.rs + #[cfg(test)] inline | 8,560 | 25.8% | 1,662 #[test] functions across 10 integration modules (tests/) + 20 inline #[cfg(test)] blocks. Covers JSON / CSV contracts (233 tests in json_and_csv_contracts.rs), CLI dispatch (177 in integration.rs, 86 in cli_combinations.rs, 63 in dispatch_contracts.rs), library smoke / filter semantics / color output / binary aliasing | |
| TOTAL (incl. tests) | 32,001 | 100% | |||
$TOP 20 FILES BY SIZE
The 20 largest files account for 84.2% of the codebase (Rust under src/ + tests/). tui_tabs.rs is by far the largest single file — the entire 7-tab dashboard, mouse handling, tooltips, and theme picker live there. The four largest test modules (json_and_csv_contracts, integration, cli_combinations, dispatch_contracts) cover 6,602 lines — every flag combination, every JSON shape, every CSV escape rule.
| File | Lines | Role |
|---|---|---|
| src/tui_tabs.rs | 5,308 | Unified 7-tab TUI dashboard (TOP / SUMMARY / PORTS / TREE / NET-MAP / PIPES / STALE), mouse handling, hover & right-click tooltips, theme chooser + 6-color editor, bottom-bar segments with verbose tooltips, atomic frame rendering |
| src/filter.rs | 2,812 | Selection & filter composition: PID / PGID / user / command / FD / network-spec / path selectors with comma-lists, ranges, exclusion, regex; OR (default) and AND (-a) modes; precomputed canonical filter paths (v4.8.3 perf path) |
| tests/json_and_csv_contracts.rs | 2,581 | 233 #[test] functions pinning every JSON field, every CSV escape rule, every per-flag output shape — refactors can’t silently break downstream consumers |
| tests/integration.rs | 2,090 | 177 end-to-end tests: full binary invocation, every flag, every output mode |
| src/cli.rs | 1,343 | clap derive args (38 #[arg] attributes, 20 short flags), custom help display, mode-flag groupings, version printing |
| src/darwin.rs | 1,253 | macOS libproc FFI: proc_listpids, proc_pidinfo, proc_pidfdinfo, proc_pidpath; zero-copy #[repr(C)] structs sized to kernel headers; per-PID FD scan parallelized with rayon |
| tests/cli_combinations.rs | 1,142 | 86 tests covering every selector / mode combinator (-a -p -u -i AND mode, regex command match, range FDs, exclusion) |
| src/top.rs | 1,009 | Live top-N FD dashboard: sort cycling (FDs → PID → USER → REG → SOCK → PIPE → OTHER → DELTA → CMD), distribution bar column, delta tracking, +/- to grow / shrink N |
| src/theme.rs | 1,005 | 31 named cyberpunk palettes (NeonSprawl, BladeRunner, Matrix, SolarFlare, …) via the ThemeName enum with display name + 6-color resolver; custom-palette support persisted through config.rs |
| src/summary.rs | 905 | Aggregate FD breakdown with bar charts, top-N processes, per-user totals; doubles as a live TUI mode under --summary -r N via the shared TuiMode trait |
| src/types.rs | 972 | Cross-platform shared shapes: Process, OpenFile, SocketInfo, NetSpec, FdType, etc. — 11 public structs / enums, all serde-serializable for the JSON contract |
| src/freebsd.rs | 835 | FreeBSD gather: sysctl(KERN_PROC_FILEDESC) + /proc when mounted, FreeBSD-specific socket / kqueue / shm decoding |
| src/linux.rs | 820 | Linux gather: /proc/<pid>/{stat,status,fd,fdinfo} reader, /proc/net/{tcp,tcp6,udp,udp6,unix} parser for socket decoding; parallelized per-PID with rayon |
| tests/dispatch_contracts.rs | 789 | 63 tests pinning the mode-dispatch matrix in main.rs: which mode wins when multiple flags are passed, exit-code contracts, alternate-screen lifecycle |
| src/output.rs | 770 | Columnar + field (-F) formatting, TTY-detected ANSI theming, cyberpunk header swap (PROCESS/PRC/H4XOR on TTY, COMMAND/PID/USER when piped), Unicode-safe column widths via strutil.rs |
| src/net_map.rs | 608 | Network connections grouped by remote host: aggregates each peer’s open-socket count, supports JSON output and per-user filtering |
| src/delta.rs | 577 | Iteration-diff engine for change highlighting: stable record IDs, additions in green, removals in red, used by --delta -r N and all live modes |
| src/tui_app.rs | 564 | Shared TuiMode trait + ratatui scaffold: alternate-screen entry/exit, common keybindings (1-9, p pause, ? help, c/C theme, x border, / filter, y copy, e export, q quit), atomic frame rendering |
| src/tree.rs | 556 | Hierarchical process tree with FD inheritance, per-PID type breakdown ([REG:12 IPv4:3 PIPE:2]), notable-file listing inline; JSON tree with nested children |
| src/ports.rs | 450 | Listening-ports summary like ss -tlnp but cross-platform (macOS + Linux + FreeBSD); supports JSON output and per-user filtering |
| TOP 20 SUBTOTAL | 26,069 | 81.9% of 32,001-line Rust slice |
@EXECUTION PIPELINE
One invocation flows through three stages: gather (platform-specific FFI, parallel per-PID), filter (composable selectors, AND/OR mode), output (one of: columnar TTY, columnar plain, JSON, CSV, field, or live TUI). The shared Process / OpenFile shape from src/types.rs means every backend feeds every output mode without intermediate marshaling.
argv ──▶ cli.rs (clap derive, 38 args)
│
▼
┌────────────────┐
│ main.rs │ mode dispatch:
│ (282 lines) │ tui / top / summary -r / monitor /
│ │ watch / follow / leak-detect /
│ │ tree / ports / stale / pipe-chain /
│ │ net-map / csv / json / field / list
└────────┬───────┘
│
┌──────────┴──────────┐
│ │
▼ ▼
#[cfg(target_os = …)] filter.rs (2,659 lines)
┌───────────┐ - PID / PGID / USER / CMD
│ darwin.rs │ - FD range / exclusion
│ (1,253) │ - network spec (4|6|TCP|UDP|:port)
│ libproc │ - path canonicalization
│ FFI │ - AND mode (-a) / OR mode (default)
│ repr(C) │ - regex via /…/
└─────┬─────┘
│
┌───────────┐
│ linux.rs │
│ (820) │
│ /proc fs │ ┌──────────────────────┐
│ rayon │ ──▶ │ Vec<Process> │
│ per-PID │ │ (types.rs, 867 ln) │
└─────┬─────┘ │ Process │
│ │ ├─ OpenFile │
┌───────────┐ │ │ ├─ FdType │
│freebsd.rs │ │ │ └─ SocketInfo │
│ (835) │ │ └─ command/uid/… │
│sysctl+proc│ └──────────┬───────────┘
└───────────┘ │
▼
┌─────────────────────────────┐
│ output dispatch │
├─────────────────────────────┤
│ output.rs - columnar/TTY │
│ json.rs - serde JSON │
│ csv_out.rs - RFC 4180 │
│ tui_app.rs - TuiMode trait │
│ └─ tui_tabs, top, │
│ summary, monitor, │
│ follow, watch, leak │
└─────────────────────────────┘
&TYPE SYSTEM
Eleven public struct / enum definitions in src/types.rs (867 lines) carry every fact between the gather, filter, and output layers. All of them #[derive(Serialize, Deserialize)] so the JSON contract is one derive macro — no hand-rolled escaping, no schema drift.
Process
Per-PID record: pid, ppid, pgid, uid, user, command, open_files: Vec<OpenFile>. Populated by each platform backend, consumed by every filter and output mode.
OpenFile
One row of lsof output: fd, fd_kind, fd_type (FdType enum), device, size_off, node, name, optional SocketInfo when the FD is a socket.
FdType
Enum of the file-descriptor classes lsofrs decodes: REG, DIR, CHR, BLK, FIFO, PIPE, IPv4, IPv6, unix, KQUEUE, POSIX_SHM, POSIX_SEM, plus platform-specific extras.
SocketInfo
Decoded socket facts: protocol (TCP/UDP/unix), local_addr + local_port, remote_addr + remote_port, state (LISTEN/ESTABLISHED/…). Drives --ports, --net-map, and -i filtering.
NetSpec
Parsed form of the -i argument: address-family (any/4/6), protocol (any/TCP/UDP), host, port. One parsed predicate filters against every SocketInfo.
FilterOptions
The composed selector bundle handed to filter.rs: lists of PIDs / users / commands / FDs / paths / net-specs, plus AND-vs-OR mode bit. Single owner of every selector flag.
OutputFormat
Enum chosen by cli.rs: Columnar, Field(<chars>), Json, Csv, Terse. main.rs picks the right serializer per variant.
ThemeName
31-variant enum of named cyberpunk palettes (NeonSprawl, BladeRunner, Matrix, …). ThemeName::ALL is the canonical iteration order used by the theme chooser.
LsofTheme
Resolved 6-color palette ready for ratatui: header / row / accent / good / warn / bad. Built from a ThemeName or from a custom palette loaded out of ~/.lsofrs.conf.
SortColumn / SortDir
Cycled by s / r in the top dashboard. Drives all live-mode column ordering through the shared TuiMode trait.
DeltaState
Iteration-to-iteration diff bookkeeping consumed by delta.rs. Tracks which records are NEW (green), GONE (red), or UNCHANGED so live modes can highlight churn.
%MODES MATRIX
Fifteen distinct entry points dispatched from main.rs based on which flag is set. Single-shot modes print and exit; live modes share tui_app.rs's TuiMode trait for common keybindings and atomic frame rendering.
| Flag | Module | Lines | Mode | Description |
|---|---|---|---|---|
(default) | output.rs | 770 | single-shot | Columnar output (cyberpunk on TTY, plain when piped); the original lsof default |
--tui | tui_tabs.rs | 5,308 | live (TuiMode) | Unified 7-tab dashboard with mouse + tooltips + theme picker + theme editor |
--top [N] | top.rs | 1,008 | live (TuiMode) | Live top-N processes sorted by FD count with distribution bars + delta |
--summary [-r N] | summary.rs | 904 | both | Aggregate stats + bar charts; -r N turns it into a live TuiMode |
--monitor / -W | monitor.rs | 288 | live (TuiMode) | Classic full-screen alternate-buffer monitor (top(1)-style) |
--watch FILE | watch.rs | 369 | live (stream) | Timestamped +OPEN / -CLOSE events for a single path |
--follow PID | follow.rs | 192 | live | Single-PID FD tracker; new opens +NEW green, closes -DEL red |
--leak-detect[=I,N] | leak.rs | 339 | live | Per-PID FD-count sampler with circular buffer; flags monotonically increasing counts |
--tree | tree.rs | 556 | single-shot | Hierarchical process tree with per-PID FD-type breakdown |
--ports | ports.rs | 450 | single-shot | Listening-ports summary like ss -tlnp, cross-platform |
--stale | stale.rs | 313 | single-shot | Deleted-file FD finder (disk-space leak / zombie-handle detector) |
--pipe-chain | pipe_chain.rs | 358 | single-shot | Pipe + unix-socket IPC topology between processes |
--net-map | net_map.rs | 608 | single-shot | Network connections grouped by remote host |
--csv | csv_out.rs | 397 | single-shot | RFC 4180-compliant CSV export |
--json / -J | json.rs | 441 | single-shot | Serde-backed JSON array (full OpenFile shape) |
--delta -r N | delta.rs | 577 | live (repeat) | Color-coded diff between iterations (green=new, red=gone) |
-F <chars> | output.rs | — | single-shot | Per-record field output (p=pid, c=cmd, f=fd, n=name, …) — lsof-compatible |
-t | output.rs | — | single-shot | Terse PIDs-only output (scripting path) |
!DEPENDENCY AUDIT
Thirteen direct dependencies, all foundational crates from the durable-by-design tier (libc, nix, serde, clap, regex, rayon, chrono) with one TUI layer (ratatui + crossterm). Picked for "will this still build cleanly in 2035" — no curl-pipe-bash installers, no flaky build scripts, no nightly-only features.
| Crate | Version | Purpose |
|---|---|---|
clap | 4.x (derive) | CLI parsing with derive macros — backs cli.rs's 38 #[arg] attributes |
serde | 1.x (derive) | Trait-driven serialization for JSON + TOML config; one derive macro pins the JSON contract |
serde_json | 1.x | JSON serializer used by --json / -J |
crossterm | 0.29 | Terminal control (alternate screen, raw mode, key/mouse events) under every live mode |
libc | 0.2 | Raw FFI types for Darwin libproc structs and POSIX getpwuid |
nix | 0.31 | Safe POSIX bindings — signal, term, ioctl, user, fs, net, hostname feature set |
users | 0.11 | Username lookup wrapped in a OnceCell cache (v4.8.3 hot-path optimization) |
regex | 1.x | Regex matcher for command-name selectors via /…/ grammar |
chrono | 0.4 | Timestamps for --watch open/close events and live-mode footers |
rayon | 1.x | Work-stealing thread pool for per-PID FD enumeration — CPU count = parallel degree |
ratatui | 0.30 | TUI rendering primitives (widgets, layouts, frame) under tui_app.rs's TuiMode trait |
toml | 1.1 | Config-file parser for ~/.lsofrs.conf (theme persistence + custom palettes) |
dirs | 6.x | OS-correct home-directory lookup for ~/.lsofrs.conf |
| TOTAL | 13 direct | All from the foundational / durable tier — no nightly, no proc-macro-heavy frameworks, no opinionated DI containers |
?TEST SURFACE
1,662 #[test] functions across 10 integration modules and 20 inline #[cfg(test)] blocks. The integration suite is contract-heavy: every JSON field, every CSV escape, every CLI flag combination is pinned so refactors can't silently shift output shape.
| Test Module | Lines | #[test] | Focus |
|---|---|---|---|
| tests/json_and_csv_contracts.rs | 2,581 | 233 | Every JSON field, every CSV escape, every per-flag output shape |
| tests/integration.rs | 2,090 | 177 | End-to-end binary invocation, every flag, every output mode |
| tests/cli_combinations.rs | 1,142 | 86 | Selector / mode combinator matrix (-a -p -u -i, regex, ranges) |
| tests/dispatch_contracts.rs | 789 | 63 | Mode-dispatch precedence in main.rs, exit-code contracts, alternate-screen lifecycle |
| tests/library_smoke.rs | 393 | 28 | Library-crate facade smoke tests (pub mod cli; pub mod types; pub mod filter; …) |
| tests/json_wrappers.rs | 391 | 43 | JSON envelope shapes for the structured modes (summary, ports, tree, …) |
| tests/filters_and_paths.rs | 268 | 26 | Path canonicalization, FD-range parsing, exclusion grammar |
| tests/json_shape.rs | 147 | 13 | Top-level JSON shape pins for the default --json output |
| tests/color_output.rs | 146 | 6 | TTY-vs-piped ANSI behavior — cyberpunk on TTY, plain when piped |
| tests/lsf_binary.rs | 52 | 5 | lsf short-form alias contract — same binary, same behavior, both bin targets in Cargo.toml |
| tests/ subtotal | 8,560 | 680 | 10 integration modules |
| + inline #[cfg(test)] in src/ | — | 947 | 20 modules with inline test blocks (filter.rs alone has 208 inline tests) |
| TOTAL | 8,560+ | 1,662 | Pinned contracts across CLI, JSON, CSV, filters, dispatch, color, library facade |
*SHIPPING ARTIFACTS
Two binaries from one source
Cargo.toml declares both [[bin]] name = "lsofrs" and [[bin]] name = "lsf" at the same src/main.rs path. The short form is a quicker-to-type alias — same code, same behavior, both end up on PATH after cargo install lsofrs.
Man page
310-line roff page at lsofrs.1 — every flag documented, copy with sudo cp lsofrs.1 /usr/local/share/man/man1/ then man lsofrs.
Zsh completion
101-line #compdef lsofrs script at completions/_lsofrs; drop into any fpath entry (e.g. /usr/local/share/zsh/site-functions/) and reload via compinit.
Library crate
The lsofrs crate also exposes a library facade (pub mod cli; pub mod types; pub mod filter; pub mod output; pub mod json; pub mod csv_out; …) gated by #[cfg(target_os)] so downstream tools can reuse the gather + filter + serialize stack without shelling out. Documented on docs.rs/lsofrs.
Config persistence
~/.lsofrs.conf is a TOML file written by src/config.rs. Stores the last-used --tui tab, the active ThemeName, and any custom 6-color palettes built in the in-app editor (C).
CI
GitHub Actions workflow at .github/workflows/ci.yml — rustfmt, clippy, test on stable. Rust toolchain pinned to stable via rust-toolchain.toml with rustfmt + clippy components required.
=INVARIANTS
Constraints the codebase enforces or relies on. Listed here so future changes know which lines are load-bearing.
Single gather shape
All three platform backends must return Vec<Process> using the same Process / OpenFile / SocketInfo types from src/types.rs. Every output mode + filter consumes the same shape — no per-platform output branches.
TTY-detected coloring only
Output coloring + cyberpunk headers (H4XOR, CL4SS, T4RGET) are gated by std::io::IsTerminal. Pipelines always get plain ASCII headers and no ANSI escapes — safe for downstream tools like jq, awk, spreadsheets.
JSON contract is pinned
233 tests in tests/json_and_csv_contracts.rs + 43 in tests/json_wrappers.rs + 13 in tests/json_shape.rs = 289 JSON-shape tests. Renaming a field in OpenFile breaks the build until tests are updated — downstream consumers can't be silently broken.
No mid-codepoint slices
src/strutil.rs provides safe UTF-8 truncation for fixed-width column display. Output code never slices bytes by index — international filenames + emoji process names display cleanly without panics.
One shared TuiMode trait
Every live mode (--tui, --top, --summary -r, --monitor, …) implements the TuiMode trait in src/tui_app.rs. Adding a new keybinding once propagates everywhere; no per-mode reimplementations of q / p / ? / c.
OR mode is the default
Selectors compose with OR by default; -a switches the whole predicate to AND. This matches lsof's grammar so existing scripts port directly — pinned by tests in cli_combinations.rs.
Zero-allocation hot loop
v4.8.3 removed every per-record allocation from the gather loop: OnceCell-cached getpwuid, precomputed filter paths, no per-FD intermediate Vec. This is what bought the 12× default-mode speedup over lsof 4.91 — future PRs touching darwin.rs / linux.rs / filter.rs hot paths should re-bench with hyperfine.
Both binaries always ship together
Cargo.toml has [[bin]] name = "lsofrs" and [[bin]] name = "lsf" at the same src/main.rs path. tests/lsf_binary.rs pins this aliasing — lsf must remain a name-only alias forever; behavior divergence is a regression.
>>WHERE NEXT
- Docs index — quickstart, mode catalog, selection grammar, JSON shape, interactive controls.
- README — install, every flag with examples, full benchmark table, screenshots.
- docs.rs/lsofrs — rustdoc for the library crate.
- lsofrs.1 — full man page (also
man lsofrsafter install). - Issues — bug reports, feature requests, perf regressions.
- crates.io/crates/lsofrs — releases, downloads, version history.