lx — file Lister eXtended
lx is a modern file lister for Unix — a replacement for the standard
ls command.
But… lx is a file lister with personality! 🌟
Upgrading from an earlier 0.x release? See
docs/UPGRADING.mdfor breaking changes per release, with migration notes and the reasoning behind each change.
Highlights
🌟 Personalities
Shell aliases have been wrapping ls in user-preferred flags for
forty years. lx takes the idea and promotes it into a feature:
a personality is a named bundle of settings, activated by the
name you call lx under. Symlink lx to ll and ll behaves
like a long-view lx. Create symlinks named la, tree or du
— it Just Works, no shell aliases required.
Same data, three personalities, three completely different views. No aliases.
Personalities can inherit from each other, pick formats and themes, bundle filter rules, and activate conditionally based on environment variables (different behaviour inside SSH, in a specific terminal, on a particular host, …).
lx ships with compiled-in personalities so it works the way you'd
expect out of the box — and you can override or extend any of them from
your config file.
A CLI you can predict
lx's flag surface is designed to be orthogonal. Every long view
column has the same three things: a flag to add it, a --no-*
counterpart to hide it, and a sort key to sort on that column. Learn
a flag once, and you can guess the rest:
Short flags aim to be guessable mnemonics — -u for --user, -g for
--group, -m for --modified.
Related actions share a letter in different cases: -b and -B
modify the file size column to show raw byte counts or Binary size
prefixes, respectively. -d (list directories as files) pairs with
-D (list only directories).
View detail compounds: -l fulfils its historical role of showing more
detail in a "long" view, but using it multiple times (-ll / -lll) increases
the amount of detail shown. Similarly -t, -tt and -ttt show progressively
more timestamp fields.
CLI flags are divided into four disjoint classes that stay out of each other's way.
Zero config, or every detail
Out of the box: no config file needed. The compiled-in defaults use only
the 8/256-colour ANSI palette, so a fresh lx looks the same on
a twenty-year-old serial console as it does on a modern
Ghostty — identical columns, identical layout, sensible
colours. And it works on a light or dark background.
lx --init-config generates a config file that documents the defaults
without altering them, so you can go from zero-config to fully-tuned
without ever crossing a behavioural discontinuity.
When you want more: lx may be the most flexibly configurable
ls-like around. You've already seen personalities as symlinks;
they come alive inside lx's config file, where they're
just one of five kinds of composable section. The others —
formats, themes, styles, and file-type classes — have their own
inheritance or pattern-matching rules, and everything combines freely:
[] # a theme…
= "catppuccin-mocha" # …based on a curated preset
= "dev" # …with its own file-name styling
[]
= "#ff8700" # every source file in orange
= "bold yellow" # this exact filename in bold yellow
[] # a personality using the theme
= "ll" # …based on a builtin personality
= "work"
[[]] # conditional: only inside SSH
= true
= "never" # …disable all colour
Sounds and looks too complicated? Ignore it! lx offers powerful
features from the get-go, with no configuration. The complexity hides
until you need it.
There's more:
- A suite of flags (
--show-configand--dump-*) lets you inspect and troubleshoot your configuration. lx --upgrade-configmigrates schemas between releases automatically.lxships with curated example themes which you can drop in aconf.ddirectory.
Version control integration
lx has built-in backends for both Git
and Jujutsu, with VCS auto-detection. Per-file status
optionally appears in long views, and you can choose to exclude files matched
on repository ignore rules.
The jj backend is opt-in at compile time to keep the default binary small — Homebrew and pre-built release binaries include it.
Fast, even on slow filesystems
A big tree shouldn't make lx feel sluggish. When computing recursive sizes,
lx walks each directory once. An in-memory cache catches cases where the
same directory would otherwise be visited repeatedly.
On high-latency filesystems like NFS, where every extra stat()
round-trip costs real milliseconds, lx 0.9 lists large trees in
roughly a tenth of the wall time earlier lx releases took.
lx 0.10 keeps that NFS work and adds a second round of
traversal-engine improvements aimed at deep local trees: lazy metadata,
a smarter xattr strategy, and other optimisations make deep tree
traversal 2–7× faster than it was in 0.9.
A fine manual
For a more in-depth walkthrough of everything above, see the user guide!
But you don't need to! lx works exactly as you'd expect a good CLI
citizen to. If you get stuck there's --help and man pages.
Installation
Homebrew (macOS and Linux)
Installs the lx binary (with jj support), man pages, and shell
completions.
From crates.io
The crate is published as lx-ls
on crates.io. The installed binary is still called lx.
Pre-built binaries and man pages
Download from the GitHub releases page for macOS (Intel and Apple Silicon) and Linux (x86_64 and aarch64). All release binaries include jj support.
Put both man pages in your man path, or view with man <file>.
Build from source
lx requires Rust 1.94 or later.
If you have just, the included Justfile
automates installation, man pages, personality symlinks, and
completions — run just -l to see the recipes.
Documentation
docs/GUIDE.md— the user guide: personalities, configuration, themes, VCS, daily usage, shell completions.docs/UPGRADING.md— breaking changes per release, with migration notes and justifications.man lx— command reference (installed alongside the binary; mdoc source inman/lx.1).man lxconfig.toml— configuration file reference (mdoc source inman/lxconfig.toml.5).CHANGELOG.md— release notes.lx --help— online flag reference.
Known limitations
- jj support is opt-in at compile time. Release binaries
(Homebrew, GitHub releases) include it;
cargo installdefaults to git-only. Build with--features jjto enable. - Old config files can be migrated to the current schema with
lx --upgrade-config(a.bakof the original is saved automatically). Files written for older 0.x releases load unchanged where possible; the migration only kicks in for the oldest formats or where new sections are being injected. - The crate name on crates.io is
lx-ls; the binary is stilllx. lxis an experiment under active development. The CLI surface is not yet stable.
Acknowledgements
lx stands on the shoulders of giants.
It is built on the foundations of exa
by Benjamin Sago (ogham). The core file system, output rendering, and
column system are all based on his work, and that of his contributors.
Thank you! 🌟
Several features were inspired by
eza, the active community
fork of exa maintained by Christina Sørensen and collaborators.
These were reimplemented from scratch for lx and sometimes differ
from their eza counterparts.
Licence
MIT — same as the original exa. See LICENCE.
Pronunciation
lx is pronounced "alex". Or "ell-ex". Really, you choose.