← All posts

CLI

Zoxide: The Smarter cd Command That Learns Your Habits

Zoxide is a blazing-fast, Rust-powered cd replacement that learns your most-used directories and jumps to them instantly

Abstract illustration of a terminal cursor navigating a directory tree along an optimized glowing path, representing zoxide's smart navigation.

Every developer has a handful of directories they visit dozens of times a day. Project roots, config folders, deeply nested module paths — the muscle memory of typing cd ~/projects/client-x/packages/api/src gets old fast. I'd tried aliases, shell bookmarks, and even autojump years ago. Then I found zoxide, a smarter cd command written in Rust that tracks where you actually go and lets you jump there with a few keystrokes. It's been in my shell config for over a year now, and I genuinely forget it's there — which is the highest compliment a CLI tool can receive.

What Zoxide Actually Does

Zoxide maintains a local database of directories you've visited, ranked by frequency and recency (a combined metric the project calls "frecency"). When you type z foo, it doesn't do a naive substring search of your filesystem. Instead, it queries its database for the highest-ranked directory matching "foo" and jumps you there instantly. The lookup is O(1)-fast because the database is a simple in-memory list — no background indexing, no daemon, no network calls.

It's a spiritual successor to tools like z (the shell script), autojump, and fasd, but rewritten from scratch in Rust. That matters not because "Rust fast" is a meme, but because the previous tools were shell scripts with real performance costs on large databases and slow filesystems. Zoxide's lookup consistently takes under 5 milliseconds on my machine with ~1,200 entries.

Getting Started in Two Minutes

Installation is straightforward on every platform. On macOS with Homebrew:

brew install zoxide

On Linux, the install script handles it:

curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh

After installing the binary, you need to hook it into your shell. For Bash, add this to your .bashrc:

eval "$(zoxide init bash)"

For Zsh, Fish, Nushell, PowerShell, and others, swap bash for your shell name. That's the entire setup. From this point on, every cd you run gets silently logged (zoxide hooks into the cd command). After a day of normal work, your database has enough data to be useful.

The Core Commands

  • z <query> — Jump to the best-matching directory. Multiple query terms narrow results: z proj api matches ~/projects/client-x/packages/api.
  • zi <query> — Interactive mode. Pipes results into fzf (if installed) so you can fuzzy-select when there's ambiguity.
  • zoxide query --list — Dump the full database with scores, useful for debugging or auditing.
  • zoxide add <path> — Manually seed a directory without visiting it first.
  • zoxide remove <path> — Prune stale entries (deleted project directories, for instance).

Why Frecency Beats Frequency Alone

The frecency algorithm is what makes this feel intelligent rather than mechanical. A directory you visited 200 times six months ago but haven't touched since will gradually lose rank. A directory you visited three times today shoots to the top. This means z almost always does what you mean right now, not what you meant last quarter.

In practice, I find that after about a week of usage, I almost never get a wrong match. When I do, zi with fzf is the escape hatch — it takes an extra second but always gets me where I need.

Fitting Zoxide Into a Real Workflow

Here's where it clicked for me. I work across 8-10 project directories on any given day, and several share similar folder structures (src, config, tests). I used to maintain a rats' nest of shell aliases. Now my workflow is:

# Jump to the API project z api # Jump specifically to the e2e test folder inside the dashboard project z dash e2e # Not sure which "config" I want? Interactive mode. zi config

It composes well with other CLI tools. I'll often pipe zoxide query output into scripts that need to operate across multiple project roots. It also respects $_ZO_EXCLUDE_DIRS if you want to keep certain paths (like node_modules or .git internals) out of the database entirely.

Rough Edges and Limitations

Zoxide is mature and stable, but it's not magic:

  • Cold start problem. The database starts empty. Your first day with zoxide is underwhelming because it hasn't learned anything yet. You can speed this up with zoxide import if you're migrating from autojump or z.sh — it reads their databases directly.
  • Stale entries persist. If you delete a project directory, zoxide doesn't automatically purge it. You'll get a "no such directory" error once, and then zoxide removes it — but it's reactive, not proactive. A periodic zoxide query --list | while read ... cleanup script is worth having.
  • Ambiguity in large databases. With 1,000+ entries and vague single-word queries, you'll occasionally land in the wrong place. The fix is always to add a second query term, but it's a minor friction point.
  • No cross-machine sync. The database is local. If you work across multiple machines, each one builds its own database independently. I've seen community scripts that sync via Git or Dropbox, but nothing official.

How It Compares

If you're coming from autojump (Python), expect identical behavior with noticeably faster lookups — autojump's Python startup overhead is measurable in large shells. If you're coming from the original z.sh (shell script), zoxide is a drop-in replacement with better edge-case handling around special characters in paths and a proper database format. If you've never used any directory jumper, you're about to wonder how you lived without one. It's one of those tools — like a solid grep replacement — that quietly saves you hundreds of small context switches a week.

The Bottom Line

Zoxide is a smarter cd command that earns its place by being invisible. No configuration to maintain, no aliases to remember, no daemon to babysit. Install it, forget about it, and after a week your fingers will type z instead of cd without you even noticing. For a CLI tool, that's the ultimate success criteria.

WHY I'D USE IT (valid HTML, 2 short paragraphs — my personal use case):

I maintain several Drupal and Node.js projects simultaneously, each with deeply nested directory structures. Zoxide eliminated the mental overhead of remembering exact paths — I just type z drupal theme or z node api and I'm there. It's especially valuable during rapid context switching when I'm debugging across multiple codebases in the same terminal session.

I also use it as a lightweight audit of where I actually spend my time. Running zoxide query --list --score once a month shows me which projects are getting the most attention and which ones I've neglected. It's an accidental productivity insight from what's essentially a two-letter command.