colorls (Rust)
A fast, production-ready Rust rewrite of colorls
(the Ruby gem): a beautified ls with Nerd Font icons, per-type colors,
git status, and a tree view. Same purpose as upstream colorls — not a
line-for-line port — rebuilt from scratch as a single static binary with a
YAML config-override system that plays the same role as upstream's
~/.config/colorls/*.yaml files.
Cross-platform: Linux, macOS, and Windows. No Ruby, no gems, no runtime
dependencies beyond an optional git binary on PATH for --gs.
Supported platforms
Every tagged release (vX.Y.Z) builds and publishes prebuilt binaries for:
| OS | Targets |
|---|---|
| Linux (glibc) | x86_64, aarch64, armv7 (armhf, e.g. Raspberry Pi), i686 |
| Linux (musl, static) | x86_64, aarch64, armv7 |
| Android / Termux | aarch64 (arm64, most phones), armv7 (armv7l, older 32-bit devices), i686, x86_64 (emulators) |
| macOS | x86_64 (Intel), aarch64 (Apple Silicon) |
| Windows | x86_64, i686, aarch64 (Windows-on-ARM, e.g. Surface Pro X) |
See Releases for
prebuilt archives, or build from source for anything not listed (any target
rustc/cross supports should work — the code has no target-specific
unsafe/FFI beyond standard library and users/colored, both of which
are cross-platform).
Install
Cargo
Build from source
Requires Rust 1.75+ (matches the toolchain used for the project's other
Rust tools). cargo build alone works — no native system libraries are
required (git status is invoked via git on PATH at runtime, not linked).
# binary at target/release/colorls (colorls.exe on Windows)
Cross-compiling for another target locally (with the target installed via
rustup, or via cross for targets
that need a foreign C toolchain, e.g. Android or musl/ARM):
# or, for targets needing a cross-toolchain (Android, musl, ARM, ...):
Termux (Android)
Termux runs standard Android NDK (*-linux-android) binaries directly,
since Termux itself targets bionic libc the same way an NDK build does.
Download the aarch64-linux-android archive (or armv7-linux-androideabi
for older 32-bit devices) from Releases, then:
Owner/group columns in -l show numeric uid/gid on Android/Termux instead
of resolved names (bionic doesn't expose the conventional multi-user
passwd/group database glibc/musl provide, so there's no name to resolve).
--init-config, git status (--gs, if git is installed via pkg install git), and everything else behaves identically to the Linux build.
Every build produces two identical binaries: colorls and lls. Same
code, same flags, same everything — lls is just a shorter, collision-free
name for the common case of an old Ruby colorls/colorls.bat already
sitting on PATH (as e.g. where colorls on Windows would show if you've
ever gem install colorls'd). --help/--version on each reports its own
name, not the other one's.
Copy target/release/colorls and/or target/release/lls (.exe on
Windows) anywhere on PATH. There is no installer and no required config —
it works with sane defaults out of the box. To alias it over the real
ls/dir, add to your shell profile:
On Windows (PowerShell profile):
function ls { lls @args }
function ll { lls -l @args }
Usage
colorls [OPTIONS] [PATHS]...
| Flag | Meaning |
|---|---|
-a, --all |
show hidden entries, including . and .. |
-A, --almost-all |
show hidden entries, without ./.. |
-l, --long |
long listing: permissions, owner, size, date |
-1, --oneline |
one entry per line |
--tree[=N] |
tree view, default depth 3 |
--gs, --git-status |
show per-entry git status column, plus a branch header above the listing |
--sd, --group-directories-first |
directories before files |
--sf, --sort-files |
files before directories |
-t |
sort by modification time, newest first |
-S, --sort-size |
sort by size, largest first |
-X, --sort-extension |
sort by extension |
-r, --reverse |
reverse the active sort order |
-R, --recursive |
recurse into sub-directories (flat, ls -R style) |
--light / --dark |
color theme |
--report |
print a directory/file/size summary after listing |
--no-icons / --icons |
disable/force-enable Nerd Font icons |
| `--color <auto | always |
--config <PATH> |
use a specific config dir (or its config.yaml) |
--init-config |
write default config files, without clobbering existing ones |
--print-config-dir |
print the resolved config directory and exit |
-q, --quiet |
suppress non-fatal warnings |
-v, -vv |
increase verbosity |
Run colorls --help for the full, always-up-to-date list.
Nerd Font required for icons. If your terminal font doesn't include
Nerd Font glyphs, icons render as boxes/?.
Either install a Nerd Font, or run with --no-icons.
Configuration
colorls looks for a config directory in this order:
--config <path>(a directory, or aconfig.yamlfile inside one)$COLORLS_CONFIGenvironment variable- Platform default:
- Linux:
~/.config/colorls - macOS:
~/Library/Application Support/colorls - Windows:
%APPDATA%\colorls - Android/Termux:
$HOME/.config/colorls(Termux's own$HOME, since the platform's usual directory-resolution APIs need JNI and aren't available to a plain native binary)
- Linux:
Run once to scaffold it:
This writes eight files (only the ones missing — existing files are never overwritten):
| File | Purpose |
|---|---|
config.yaml |
default behaviour (theme, icons on/off, git status on/off, sort options, --report, tree depth) |
dark_colors.yaml / light_colors.yaml |
category → color name, e.g. dir: bright_cyan |
icons.yaml |
file extension → Nerd Font glyph |
filenames.yaml |
exact filename (e.g. dockerfile, readme.md) → glyph, takes priority over extension |
folders.yaml |
folder name (e.g. node_modules, .git) → glyph |
aliases.yaml |
file extension → color category (source_code, image, document, ...) |
extension_colors.yaml |
file extension → color name directly, highest priority (see below) |
Any key you add to these files overrides the built-in default for that key
only — you don't need to redefine everything, just the entries you want to
change. Example, to make .rs files render in bright red instead of the
default source-code color:
# ~/.config/colorls/aliases.yaml
rs: dead_link # (or add a new category + matching color entry)
or simpler, just recolor an entire category in dark_colors.yaml:
source_code: bright_red
dir: "#00FFFF"
document: FFFF00
Coloring one specific extension without touching its whole category
aliases.yaml + dark_colors.yaml/light_colors.yaml color by category
(all "compressed" files share one color, all "source_code" files share
another). If you want a single extension to have its own color without
inventing a whole new category, use extension_colors.yaml instead — it's
checked first, before category resolution even runs:
# ~/.config/colorls/extension_colors.yaml
zip: bright_red
jar: bright_green
bz2: bright_yellow
gz: yellow
log: bright_black
7z: "#FF5500"
rar: 00AAFF
This is exactly how the built-in defaults keep archive formats visually
distinct from each other out of the box (.zip/.rar/.7z red, .gz/
.bz2/.xz yellow, .tar magenta, .jar green) instead of every archive
type sharing the single "compressed" category color. Any extension not
listed here just falls back to its category color as usual.
Hex colors
Anywhere a color name is accepted — dark_colors.yaml, light_colors.yaml,
and extension_colors.yaml — you can use a 24-bit hex color instead of a
named one:
# ~/.config/colorls/extension_colors.yaml
zip: FF8800 # bare hex — recommended, see gotcha below
jar: "#00FF88" # quoted hex also works
log: "#666" # 3-digit shorthand, quoted (each digit doubled: 666 -> 666666)
YAML gotcha: an unquoted # starts a comment, so zip: #FF0000
silently parses as an empty value, not the color you meant — colorls will
warn you about exactly this (without crashing or discarding the rest of
the file) if it happens. Either quote the value (zip: "#FF0000") or drop
the # entirely (zip: FF0000); both are treated identically.
Hex colors render as true 24-bit color on terminals that advertise
COLORTERM=truecolor (most modern terminals — Windows Terminal, iTerm2,
GNOME Terminal, kitty, alacritty, ...) and automatically degrade to the
nearest of the 16 named colors otherwise, so they still look reasonable
on older terminals instead of breaking.
config.yaml example:
theme: dark
icons: true
git_status: true
group_directories_first: true
sort_files_first: false
report: false
tree_depth: 4
long: false
all: false
Every config.yaml key has a matching CLI flag; the CLI flag always wins
when both are given, so config.yaml only sets your personal defaults.
Design notes
- Git status shells out to
git status --porcelain=v1 --ignoredrather than linkinglibgit2; this keeps the build dependency-free and avoids the native-toolchain headacheslibgit2-based crates cause when cross-compiling for Windows.--gsis silently disabled (with a one-line warning, suppressible with-q) whengitisn't onPATHor the target isn't inside a work tree. - Broken pipes (
colorls | head, output redirected then closed early) exit cleanly instead of panicking — all output goes through a small writer that treatsBrokenPipeas a normal, silent exit(0). - Color is force-synced with
colored::control::set_overrideso--color=always/--color=neverare honored even when stdout isn't a TTY (piped intohead, redirected to a file, etc.) instead of being silently overridden by the crate's own auto-detection. - Owner/group columns are populated on Unix via the
userscrate and show-on Windows, which has no equivalent POSIX uid/gid concept.
