Introducing hls: The Terminal Native’s Directory Browser
The standard ls command is one of the most frequently typed commands in computing history. It is fast, ubiquitous, and reliable. But as development workflows have evolved, the filesystem has become a much more complex place. We now live inside Git repositories, deal with heavily optimized filesystems like APFS and ext4, and encounter files completely divorced from their conventional file extensions.
Enter hls (Hacker’s ls).
Built as a lightweight, drop-in companion for your daily workflow, hls takes the speed and standard interface of traditional POSIX commands and supercharges it with modern telemetry. It doesn’t rely on massive external frameworks or languages; it is a single, dependency-free C binary designed to answer the specific questions terminal users ask every day.
Here is what it does, and why you might want to alias your standard ls to use it.
Version Control Visibility (-G)
If you spend your days in the terminal, you likely suffer from “Git Status Fatigue”—the habit of typing git status every time you change directories just to orient yourself.
By passing the -G flag, hls natively queries your working tree and displays standard two-character Git badges (e.g., M for modified, ?? for untracked, A for added) directly next to the filenames.
$ hls -G M main.c ?? test.log README.md
Why it’s useful: It merges filesystem navigation with version control awareness. You immediately see what needs to be staged or committed without running a secondary command.
The Integrated Tree View (-T)
Visualizing deeply nested directories usually means reaching for a secondary tool like tree. But tree doesn’t usually share the same formatting flags, coloring, or metadata as your directory lister.
The -T flag instructs hls to render a hierarchical, box-drawn graph of your directory structure. Because it’s built into hls, it composes perfectly with all other flags. You can view a tree structure that includes long file permissions, sizes, and Git status all at once.
Why it’s useful: Context. You get the recursive mapping of tree combined with the rich metadata of ls -l, while safely avoiding the infinite loops that often happen when traversing circular symbolic links.
True Disk Allocation Analytics (-s)
Standard directory tools lie about file sizes. A file might report a logical size (st_size) of 10 GB, but because it is a “sparse file” (a file with massive blocks of empty zeroes, common in database allocations or virtual machine images), it might actually be consuming zero bytes of physical disk space.
The -s flag looks past the logical length and queries the physical blocks allocated by the filesystem. If a file is sparse, hls explicitly flags it and shows you the efficiency percentage.
$ hls -l -s -rw-r--r-- 1 bill users 10.0G [0% sparse] Oct 19 14:00 database.img
Why it’s useful: When managing backups, VM images, or running out of disk space, knowing the difference between “apparent size” and “actual physical footprint” prevents catastrophic miscalculations.
Content-Type Sniffing (-M)
In Unix, file extensions (like .txt or .pdf) are polite suggestions, not enforced rules. A file named data.csv might actually be a compiled executable, and a file with no extension at all might be a shell script.
When you pass the -M flag, hls opens regular files, peeks at the first 32 bytes of content (the “magic numbers”), and identifies what the file actually is.
$ hls -l -M -rwxr-xr-x 1 bill users 12K Oct 19 build_script (script text) -rw-r--r-- 1 bill users 84K Oct 19 data.csv (SQLite database)
Why it’s useful: It completely eliminates the need to run the file command on suspicious or ambiguously named files, saving keystrokes and preventing you from accidentally trying to cat a compiled binary into your terminal.
Extended Attributes (-@)
Modern operating systems tag files with invisible metadata. On macOS, this is often the com.apple.quarantine bit that prevents downloaded scripts from executing. On Linux, it might be an SELinux security context or user-defined labels.
Standard ls -l will append a cryptic @ or + symbol if these exist, leaving you to manually run xattr or getfattr to figure out what they actually are. hls -@ expands them inline, indenting the extended attribute keys cleanly under the parent file.
Why it’s useful: When a script inexplicably refuses to run despite having +x permissions, or when a file transfer behaves strangely, surfacing extended metadata immediately reveals the invisible rules governing that file.
Everyday Workflows
hls was designed so its flags compose elegantly. For everyday command-line navigation, here are a few ways to combine them into powerful workflows:
The Hacker’s Default
$ hls -lG
Renders a standard long list, but with Git statuses cleanly aligned on the left margin. Perfect for active development directories.
The Deep Dive
$ hls -lGMT
Recursively prints the directory as a tree (-T), showing full permissions and human-readable sizes (-l), annotating every file’s Git status (-G), and revealing the true file type regardless of its extension (-M).
The Built-in Manual
Because terminal life should be self-contained, hls doesn’t require you to install a separate man page to your system directories.
$ hls -m
This command generates a cleanly formatted, system-style manual page directly to standard output, ready to be piped into a pager like less for quick reference.
Summary
hls isn’t trying to reinvent the paradigm of listing files; it’s simply bringing the tool up to speed with the modern filesystem. By collapsing the functionality of ls, git status, tree, file, and xattr into a single, high-performance binary, it strips away terminal friction and lets you focus on the actual work.