Stop Squinting at ls Output! Meet nuls
Let me paint you a picture we've all lived through. You cd into a directory packed with dozens of files—configs, logs, executables, hidden dotfiles scattered like landmines. You type ls -la and get... a wall of text. Monochrome filenames blur together. You squint to spot the directories. You pipe to awk just to parse dates. You run git status separately because who knows what's modified? We've accepted this as "fine" for forty years. But what if I told you a single Rust-powered tool could transform this daily friction into something almost... joyful?
Enter nuls—the NuShell-inspired ls replacement that's making terminal veterans abandon their aliases and new developers wonder how they ever lived without it. This isn't just another colorized ls clone. It's a complete reimagining of how directory listings should work in 2024: rich tables, human-readable everything, git intelligence baked in, and a visual hierarchy that actually respects your brain's pattern-matching abilities. Built by Cesar Ferreira and available right now, nuls delivers the kind of polished developer experience we usually only dream about.
Ready to never run ls | grep again? Let's dive deep.
What is nuls?
nuls is a modern directory listing tool written in Rust that replicates and dramatically extends the functionality of the traditional Unix ls command. Inspired by the acclaimed Nushell project's approach to structured data visualization, nuls transforms raw filesystem metadata into beautiful, information-dense tables that you can actually read at a glance.
The project lives at github.com/cesarferreira/nuls and has been gaining serious traction among developers who spend hours daily in terminal environments. Cesar Ferreira, the creator, identified a genuine pain point: while Nushell itself offers stunning table outputs, not everyone wants to switch shells. What if you could get that same visual polish inside Bash, Zsh, Fish, or any POSIX-compatible shell?
That's the genius of nuls. It's shell-agnostic, distributed via cargo for the Rust ecosystem, packaged for Nix users, and designed with zero configuration required. The "Nu" in nuls isn't just branding—it's a philosophy of treating command output as structured, navigable, visually encoded information rather than raw character streams.
Why is it trending now? Three converging forces: the Rust CLI renaissance (tools like ripgrep, fd, and bat have proven developers crave better Unix primitives), the mainstreaming of Nushell's design language, and a genuine fatigue with parsing ls -la output after decades of unchanged behavior. nuls arrives at the perfect moment.
Key Features That'll Make You Switch
Let's dissect what makes nuls genuinely special—not just "prettier ls," but functionally superior:
Box-Drawn Tables with Semantic Color Coding
Unlike ls which dumps space-separated columns, nuls renders proper Unicode box-drawing tables with colored borders and headers. Your eyes instantly locate boundaries. The teal/green header bar anchors your scan pattern. This isn't decoration—it's visual hierarchy as information architecture.
Intelligent File Type Tagging
Every entry gets color-coded by semantic category: directories in authoritative blue, regular files in light gray, executables in attention-grabbing red, dotfiles in amber, and config/documentation files in yellow. No more ls -F trailing slashes or file command detours. The type is immediately apparent from chromatic context.
Human-Readable Sizes with Smart Scaling
nuls auto-formats byte counts into KB, MB, GB, TB without the -h flag dance. The scaling is contextually appropriate—you won't see "0.00 TB" for a 500-byte file. This sounds trivial until you realize how many cognitive cycles you waste comparing "1433600" versus "1400K" versus "1.4M" across ls invocations.
Recency-Driven Temporal Colors
Here's where nuls gets genuinely clever. The "modified" column doesn't just show relative times ("2 hours ago", "3 days ago")—it color-encodes recency: fresh files glow green, aging through yellow and orange to red for stale content, finally graying out for ancient history. Future-dated files (it happens!) appear in distinctive blue. At a glance, you can spot what's actively changing in a project versus archaeological artifacts.
Inline Git Intelligence
Pass -g and nuls queries repository status, appending concise annotations like main.rs (+15 -2) or (clean) directly in the name column. No context switch to git status, no parsing git diff --stat. The information density here is absurdly productive for developers working in tracked directories.
Familiar Flag Compatibility
-a for hidden files, -l accepted for muscle memory (though output is inherently long-form), -t for time-sorted, -r for reverse. nuls respects your existing neural pathways while delivering superior output.
Real-World Use Cases Where nuls Dominates
1. Daily Development Navigation
You're exploring a new codebase. With nuls, directories visually pop in blue, you instantly spot the Cargo.toml or package.json in config-yellow, and the recency colors reveal which files saw recent action. The cognitive load of orientation plummets.
2. DevOps Log Triage
SSH'd into a server with /var/log exploding with files? nuls -t shows newest-first with age-coloring—red files are your urgent suspects, green ones just rotated. No ls -lt | head -20 pipeline required.
3. Git Repository Audits
Running nuls -g before commits gives you a complete workspace picture: modified files with their delta counts, untouched files marked clean, all in one screen. It's like git status and ls had a superior offspring.
4. Configuration Management
Dotfiles repositories, ~/.config spelunking, Ansible playbook directories—anywhere hidden files matter. nuls -a renders dotfiles in distinctive amber, making them instantly distinguishable without the .* pattern matching mental tax.
Step-by-Step Installation & Setup Guide
Prerequisites
You'll need Rust's toolchain (cargo) for standard installation, or Nix for declarative setups.
Method 1: Crates.io (Recommended)
# Install directly from published crate
cargo install nuls
This fetches the latest release, compiles the Rust binary, and places it in ~/.cargo/bin/ (ensure this directory is in your PATH).
Method 2: Build from Source
# Clone the repository
git clone https://github.com/cesarferreira/nuls.git
cd nuls
# Install local build, forcing overwrite of any existing version
cargo install --path . --bin nuls --force
# Optional: install to custom prefix (e.g., user-local without sudo)
cargo install --path . --bin nuls --force --root ~/.local
The --path . tells cargo to use the local Cargo.toml, --bin nuls specifies the binary target, and --force ensures clean upgrades.
Method 3: Nix (Flakes)
# Ephemeral test—no installation persistence
nix run github:cesarferreira/nuls
For permanent installation via flake.nix:
# In your flake inputs
inputs = {
nuls = {
url = "github:cesarferreira/nuls";
inputs.nixpkgs.follows = "nixpkgs"; # Pin to your nixpkgs version
};
};
# Reference in outputs
outputs = { self, nixpkgs, nuls, ... }: {
# your other outputs
};
# In configuration.nix or home.nix
{ inputs, ... }: {
environment.systemPackages = with pkgs; [
inputs.nuls.packages.${system}.default
];
}
The inputs.nixpkgs.follows line prevents duplicate nixpkgs evaluations, keeping your flake lockfile lean.
Shell Integration
Add to ~/.bashrc, ~/.zshrc, or equivalent:
# Replace ls entirely (bold—ensure you're comfortable first!)
alias ls="nuls"
# Conservative: keep both available
alias nls="nuls"
# Common convenience aliases with your preferred defaults
alias lst="nuls -t" # Always sort by modification time
alias lsa="nuls -a" # Always show hidden files
alias lsat="nuls -at" # Hidden + time-sorted
alias lsg="nuls -g" # Always show git status
alias lsag="nuls -ag" # Hidden + git (my personal favorite)
REAL Code Examples from the Repository
Let's examine actual usage patterns from the nuls README, with detailed breakdowns of what happens under the hood.
Example 1: Basic Listing
nuls
What executes: nuls scans the current directory, categorizes each entry by type, queries modification times, formats sizes human-readably, and renders the complete table. No flags needed—the default output is already "long-form" compared to traditional ls.
Behind the scenes: The tool uses Rust's std::fs for directory iteration, chrono for temporal calculations, and custom Unicode box-drawing characters (─│┌┐└┘├┤┬┴┼) for table construction. The default sort places directories first, then alphabetical files—a sane default for navigation.
Example 2: Revealing Hidden Files
nuls -a
Critical difference from ls -a: While ls -a dumps . and .. at the top (usually noise), nuls treats these specially or omits them based on context, focusing on actual dotfiles like .gitignore, .env, .zshrc. The amber coloration makes them pop without dominating the visual field.
Practical impact: In a typical project with 15 visible files and 8 hidden configs, you can now instantly distinguish operational files from infrastructure. No more "wait, is .dockerignore present?" scanning sessions.
Example 3: Time-Based Discovery
nuls -t
nuls -tr
The -t flag switches sort from directory-first/alphabetical to modification-time descending (newest first). Combined with recency-coloring, this creates a temporal heatmap of your directory.
The -r modifier reverses any active sort, so -tr shows oldest first—useful for finding forgotten files that might need cleanup.
Color progression explained:
- Green: Modified within minutes (actively changing)
- Yellow: Hours old (today's work)
- Orange: Days old (this week's context)
- Red: Weeks old (stale, possibly abandoned)
- Gray: Months/years old (archival, reference only)
- Blue: Future timestamp (clock skew or intentional)
Example 4: Git-Aware Workflow
nuls -g
nuls -lag
The -g flag activates nuls's most powerful feature. It executes a git status query behind the scenes, then annotates tracked files:
┌─────────────────────────────────────┐
│ name │ size │ modified │
├─────────────────────────────────────┤
│ src/main.rs (+15 -2) │ 4KB │ 2m ago │ ← green: very recent
│ Cargo.toml (clean) │ 2KB │ 1h ago │ ← yellow: stable
│ README.md (+8) │ 8KB │ 2d ago │ ← orange: pending changes
└─────────────────────────────────────┘
The +15 -2 notation means 15 lines added, 2 deleted since last commit. (clean) indicates zero changes. This inline annotation eliminates the ls → git status → git diff --stat workflow entirely.
nuls -lag combines all (-a), long-form (implicit), and git (-g). It's the "show me everything about this directory" command.
Example 5: Familiar Muscle Memory
nuls -la
Compatibility note: The -l flag exists purely for familiarity—nuls output is already long-form by default. This prevents the "ls: invalid option -- 'l'" friction when your fingers autopilot. It's a thoughtful design decision that respects migration pain.
Advanced Usage & Best Practices
Optimize Your Aliases for Context
Don't just alias ls—create contextual aliases:
# Development directories: always show git + hidden
alias devls='nuls -ag'
# Log directories: time-sorted, no git (not repos)
alias logls='nuls -t'
# Quick home directory scan
alias homels='nuls -a'
Color Control for Piping When scripting, force predictable output:
nuls --color=never | grep pattern # strip ANSI for processing
nuls --color=always | less -R # preserve colors through pager
Performance Considerations
The -g flag adds git overhead—noticeable in massive repositories (10k+ files). For /usr/bin-scale directories, raw nuls is faster than ls -la due to Rust's efficiency and parallelized metadata collection.
Integration with File Managers
Some terminal file managers (nnn, ranger) allow custom directory preview commands. Configure nuls as your previewer for consistent visual language across tools.
Comparison with Alternatives
| Tool | Tables | Git Inline | Recency Colors | Human Sizes | Shell Agnostic | Install Size |
|---|---|---|---|---|---|---|
nuls |
✅ Full box-drawn | ✅ Native | ✅ 6-grade scale | ✅ Auto | ✅ Any shell | ~2MB |
ls (GNU) |
❌ Space-separated | ❌ None | ❌ None | ❌ -h flag |
✅ Any shell | ~150KB |
lsd |
✅ Tree-ish | ❌ None | ❌ Age only | ✅ Auto | ✅ Any shell | ~3MB |
exa / eza |
✅ Grid/tables | ✅ Separate column | ❌ Fixed colors | ✅ Auto | ✅ Any shell | ~2MB |
| Nushell built-in | ✅ Excellent | ✅ Native | ✅ Similar | ✅ Auto | ❌ Nushell only | ~20MB+ shell |
colorls |
✅ Basic | ❌ None | ❌ None | ❌ Manual | ✅ Ruby dep | ~50MB+ Ruby |
Why nuls wins: exa/eza comes closest but separates git status into distinct columns, consuming horizontal space. nuls's inline annotation is more compact. lsd lacks git integration entirely. Nushell's ls is gorgeous but requires shell migration. nuls delivers 90% of Nushell's visual power with zero shell commitment.
FAQ
Q: Will nuls break my existing scripts that parse ls output?
A: Yes—intentionally. ls output was never meant for scripting (use find, stat, or ls with --quoting-style=escape). nuls prioritizes human readability over machine parseability. Keep ls available for legacy scripts.
Q: Does nuls work on Windows?
A: As a Rust project, it compiles for Windows, though terminal support for Unicode box-drawing varies. Windows Terminal and modern ConHost handle it well; legacy CMD may degrade gracefully to ASCII approximations.
Q: How does -g handle untracked files or non-git directories?
A: Untracked files show no annotation. In non-git directories, -g silently produces standard output—no errors, no slowdown from failed git queries.
Q: Can I customize the color palette? A: Currently, colors are fixed per the documented palette. The author has indicated configuration file support is a potential future direction. For now, the curated palette is optimized for common terminal themes.
Q: Is nuls suitable for CI/CD pipelines?
A: Use --color=never for log readability. However, nuls shines in interactive use; for pure automation, find or ls remain more appropriate.
Q: How does performance compare for directories with 100,000+ files?
A: Rust's zero-cost abstractions and nuls's efficient table buffering keep it responsive. Initial directory reads are filesystem-bound; rendering is typically sub-100ms even at scale.
Q: Can I contribute or request features? A: Absolutely—the project is MIT-licensed and actively maintained. Issues and PRs welcome at the GitHub repository.
Conclusion
We've tolerated ls for decades because "it works." But "works" isn't "delights." nuls proves that even the most entrenched Unix primitives deserve reimagining for modern developer cognition. The combination of semantic color encoding, inline git intelligence, human-centric defaults, and genuine visual beauty transforms a command you run fifty times daily from friction into flow.
After weeks of daily driving nuls, I've found myself actually enjoying directory exploration—a sentence I never expected to write. The recency colors alone have caught stale configuration drift I would have missed. The git integration has streamlined my commit workflow. And honestly? My terminal just looks better.
Don't let another day of squinting at ls -la pass. Install nuls now:
cargo install nuls
Then alias it, explore with -g, sort with -t, and discover what you've been missing. Star the project, file issues, and join the growing community of developers who've upgraded their most fundamental tool. Your terminal—and your eyes—will thank you.