Zoxide: The Smarter cd Replacement That Learns Your Habits
Zoxide: The Smarter cd Replacement That Learns Your Habits
You know the routine. You need to get to a project directory buried three or four levels deep, so you start typing cd ~/projects/work/acme-corp/backend/services/auth-service and lean on Tab to autocomplete each segment. Or maybe you keep a mental map of your directory structure and still fat-finger the path halfway through. If you work across multiple projects, the friction compounds -- you're burning keystrokes and attention on something your computer should already know.
Zoxide solves this by learning where you go. It's a Rust-based cd replacement that tracks the directories you visit, ranks them by how frequently and recently you use them (a concept called "frecency"), and lets you jump to the right place with a short fuzzy query. Type z auth and you land in that auth-service directory without spelling out the full path. It works on Linux, macOS, and Windows, supports every major shell, and has earned over 6,000 stars on GitHub for good reason.
Why Zoxide Over Plain cd
Plain cd is stateless. Every invocation starts from zero -- it doesn't know or care that you visit ~/projects/acme/backend fifty times a day. You type the same paths over and over. Shell history helps a little (cd then arrow-up), but it's fragile and linear.
Zoxide adds memory. After a few hours of normal work, it has a ranked database of your directories. From that point on, partial matches are usually enough. z acme jumps to ~/projects/acme. z back jumps to ~/projects/acme/backend. If there are multiple matches, zoxide picks the one with the highest frecency score. If that's wrong, you refine: z acme back narrows it down.
The friction reduction is small per invocation but massive over a day. It's one of those tools that changes how you move through your filesystem.
How Frecency Works
Zoxide borrows the frecency algorithm from Firefox's address bar (and before that, Mozilla's Places database). Frecency is a portmanteau of "frequency" and "recency" -- directories you visit often get a high score, but directories you visited recently get a temporary boost.
The practical effect:
- A directory you visited 100 times last month but haven't touched in two weeks will gradually lose ranking.
- A directory you visited for the first time today will temporarily rank higher than older, less-used paths.
- Over time, the scores converge on a stable ranking that reflects your actual workflow.
Zoxide stores this data in a simple SQLite database. The database stays small (a few KB even with thousands of entries) and queries are effectively instant.
Installation
Zoxide is available through most package managers:
# macOS
brew install zoxide
# Fedora
sudo dnf install zoxide
# Ubuntu/Debian (22.04+)
sudo apt install zoxide
# Arch Linux
sudo pacman -S zoxide
# From source via Cargo
cargo install zoxide --locked
# Windows (Scoop)
scoop install zoxide
# Windows (winget)
winget install zoxide
After installing the binary, you need to initialize it in your shell. This is the step most people forget.
Shell Integration
Add the appropriate init line to your shell configuration file. This sets up the z and zi commands.
# Bash (~/.bashrc)
eval "$(zoxide init bash)"
# Zsh (~/.zshrc)
eval "$(zoxide init zsh)"
# Fish (~/.config/fish/config.fish)
zoxide init fish | source
# Nushell (~/.config/nushell/env.nu)
zoxide init nushell | save -f ~/.zoxide.nu
# Then source it in config.nu:
# source ~/.zoxide.nu
# PowerShell ($PROFILE)
Invoke-Expression (& { (zoxide init powershell | Out-String) })
By default, zoxide creates the z command as the smart jump and zi as the interactive picker. If you want to replace cd entirely, pass the --cmd cd flag:
eval "$(zoxide init bash --cmd cd)"
This replaces cd itself, so cd foo becomes a frecency-powered jump. Purists may prefer keeping z separate so cd retains its standard behavior.
Key Commands
Once initialized, you get three main tools:
# Jump to the highest-ranked directory matching "foo"
z foo
# Jump using multiple keywords (all must match path segments)
z proj backend
# Interactive selection (requires fzf)
zi
# Interactive selection with a query pre-filled
zi backend
# Add a directory to the database manually
zoxide add /path/to/directory
# Remove a directory from the database
zoxide remove /path/to/directory
# List all tracked directories with scores
zoxide query --list
# Find the top match without jumping (dry run)
zoxide query foo
# Show the database path
zoxide query --list | head -1 # entries are in _ZO_DATA_DIR
The z command handles the common case: you know roughly where you want to go. The zi command handles the ambiguous case: you want to see the candidates and pick one.
Pairing with fzf
Zoxide's zi command uses fzf (if installed) to present an interactive fuzzy-search interface over your directory database. This is where zoxide becomes truly powerful.
# Install fzf if you haven't
brew install fzf # macOS
sudo apt install fzf # Debian/Ubuntu
sudo dnf install fzf # Fedora
With fzf installed, zi opens a full-screen picker showing all tracked directories ranked by frecency. You type to filter, arrow keys to select, Enter to jump. It's the same interaction model as fzf for file selection, but scoped to directories you've actually used.
You can also pipe zoxide's output into other tools:
# Open a project in your editor by frecency
code "$(zoxide query -l | fzf)"
# cd into a directory and immediately list contents
z proj && ls
Comparison: Zoxide vs the Alternatives
Zoxide isn't the first tool in this space. Here's how it stacks up against the older options:
| Feature | zoxide | autojump | z.lua | z (rupa/z) | fasd |
|---|---|---|---|---|---|
| Language | Rust | Python | Lua | Shell | Shell |
| Speed | Very fast | Slow on large DBs | Fast | Fast | Moderate |
| Algorithm | Frecency | Frecency | Enhanced frecency | Frecency | Frecency |
| Shell Support | bash, zsh, fish, nu, pwsh | bash, zsh, fish | bash, zsh, fish, pwsh | bash, zsh | bash, zsh |
| fzf Integration | Built-in (zi) |
Plugin | Built-in | No | No |
| Windows Support | Yes | Partial | Yes | No | No |
| Active Maintenance | Yes (2024+) | Minimal | Occasional | Archived | Abandoned |
| Database | SQLite | Flat file | Flat file | Flat file | Flat file |
| import from others | Yes | N/A | N/A | N/A | N/A |
The verdict: If you're starting fresh, use zoxide. It's faster, better maintained, supports more shells, and the fzf integration is first-class. If you're migrating from autojump or z, zoxide can import your existing database:
# Import from autojump
zoxide import --from autojump /path/to/autojump/db
# Import from z (rupa/z or zsh-z)
zoxide import --from z /path/to/z/data
Configuration
Zoxide is configured through environment variables. Set these before the eval "$(zoxide init ...)" line in your shell config.
# Change where the database is stored (default: platform-specific data dir)
export _ZO_DATA_DIR="$HOME/.local/share/zoxide"
# Print the matched directory before jumping (useful for debugging)
export _ZO_ECHO=1
# Exclude directories from tracking (colon-separated, supports globs)
export _ZO_EXCLUDE_DIRS="$HOME:$HOME/Downloads:/tmp/*"
# Maximum number of entries in the database (default: 10000)
export _ZO_MAXAGE=10000
# Resolve symlinks before storing paths
export _ZO_RESOLVE_SYMLINKS=1
# Use fzf options for zi (customize the picker appearance)
export _ZO_FZF_OPTS="--height 40% --reverse --border"
The most useful of these is _ZO_EXCLUDE_DIRS. By default, zoxide tracks every directory you visit, including $HOME itself (which isn't useful as a jump target since you can just type cd). Excluding home, downloads, and tmp keeps your database focused on project directories.
Tips and Workflows
Bootstrap your database faster
Zoxide only learns directories you've visited since installation. If you want to seed it with your project directories immediately:
# Add all git repos under ~/projects
fd -t d '.git$' ~/projects -x zoxide add {//}
# Add specific directories manually
zoxide add ~/projects/acme ~/projects/personal/blog ~/dotfiles
Use z for project switching
The highest-leverage use of zoxide is jumping between projects. If you work on three or four repos regularly, z acme, z blog, z infra becomes muscle memory within a day.
Combine with tmux or Zellij
If you use a terminal multiplexer, zoxide's database is shared across all panes and sessions. Jump to a project in any pane and the frecency update applies everywhere.
Debug unexpected matches
If z foo is jumping to the wrong directory, check the scores:
zoxide query --list | grep -i foo
You'll see the score next to each path. If an old directory is outranking the one you want, remove it:
zoxide remove /old/path/to/foo
Alias for common patterns
# Quick project opener: jump and open in editor
zc() { z "$@" && code . }
# Jump and list
zl() { z "$@" && ls -la }
The Bottom Line
Zoxide does one thing and does it exceptionally well: it eliminates the tax of typing full directory paths. The frecency algorithm means it gets smarter the more you use it, and the fzf integration covers the cases where you're not sure exactly what you're looking for. Installation takes two minutes, configuration is optional, and it works on every platform and shell you're likely to use. If you haven't replaced cd with something smarter yet, zoxide is the one to pick.