Smarter cd command that learns your habits using a frecency algorithm for fast directory navigation across shells.
| Command | Description |
|---|
brew install zoxide | Install on macOS with Homebrew |
cargo install zoxide --locked | Install from crates.io |
apt install zoxide | Install on Debian/Ubuntu |
pacman -S zoxide | Install on Arch Linux |
dnf install zoxide | Install on Fedora |
scoop install zoxide | Install on Windows with Scoop |
winget install ajeetdsouza.zoxide | Install on Windows with winget |
nix-env -i zoxide | Install on NixOS |
conda install -c conda-forge zoxide | Install with Conda |
curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh | Install via shell script |
| Command | Description |
|---|
eval "$(zoxide init bash)" | Initialize for Bash (add to .bashrc) |
eval "$(zoxide init zsh)" | Initialize for Zsh (add to .zshrc) |
zoxide init fish | source | Initialize for Fish (add to config.fish) |
Invoke-Expression (& { (zoxide init powershell) }) | Initialize for PowerShell |
zoxide init nushell | save -f ~/.zoxide.nu | Initialize for Nushell |
eval "$(zoxide init elvish)" | Initialize for Elvish |
eval (zoxide init xonsh) | Initialize for Xonsh |
# Bash — add to ~/.bashrc
eval "$(zoxide init bash)"
# Zsh — add to ~/.zshrc
eval "$(zoxide init zsh)"
# Fish — add to ~/.config/fish/config.fish
zoxide init fish | source
# PowerShell — add to $PROFILE
Invoke-Expression (& { (zoxide init powershell | Out-String) })
# Nushell — add to env.nu
zoxide init nushell | save -f ~/.zoxide.nu
source ~/.zoxide.nu
| Command | Description |
|---|
z foo | Jump to highest-ranked directory matching “foo” |
z foo bar | Jump to directory matching both “foo” and “bar” |
z ~/projects | Jump to exact path (like cd) |
z .. | Go to parent directory |
z - | Go to previous directory |
z | Go to home directory (no arguments) |
zi | Interactive selection with fzf |
zi foo | Interactive selection pre-filtered by “foo” |
z foo/ | Jump to subdirectory (trailing slash) |
# After visiting directories, zoxide learns them
cd ~/projects/myapp # Teach zoxide about this path
cd ~/documents/reports # Teach zoxide about this path
cd /var/log/nginx # Teach zoxide about this path
# Later, jump with partial matches
z myapp # Jumps to ~/projects/myapp
z reports # Jumps to ~/documents/reports
z nginx # Jumps to /var/log/nginx
# Multiple keywords narrow the match
z proj myapp # Matches ~/projects/myapp specifically
z doc rep # Matches ~/documents/reports
| Command | Description |
|---|
z proj | Match any directory containing “proj” |
z proj rust | Match directory containing both “proj” and “rust” |
z /home/user/docs | Use absolute path directly |
z docs/ | Match and prefer subdirectory named “docs” |
| Keywords match path components | ”proj” matches /home/user/projects |
| Last keyword can match prefix | z pr matches projects |
| Multiple keywords are AND-matched | All must appear in path |
| Matching is case-insensitive | z PROJ matches projects |
| Concept | Description |
|---|
| Frecency = Frequency + Recency | Score based on how often and how recently visited |
| Recent visits score higher | Directories visited today score more than last week |
| Frequently visited directories rank higher | Regular use increases score over time |
| Scores decay over time | Unused directories gradually lose ranking |
| Database auto-prunes low scores | Old, unused entries are removed automatically |
Maximum entries controlled by _ZO_MAXAGE | Default: 10,000 entries |
| Command | Description |
|---|
zi | Open fzf with all tracked directories |
zi query | Open fzf pre-filtered by query |
↑ / ↓ in fzf | Navigate results |
Enter in fzf | Select and jump to directory |
Escape in fzf | Cancel selection |
| Type in fzf to filter | Further narrow results |
Requires fzf to be installed | Install fzf for interactive mode |
Tab in fzf | Toggle selection (multi-select mode) |
# Open interactive fuzzy finder with all tracked directories
zi
# Pre-filter to directories containing "project"
zi project
# Output format in fzf shows scores:
# 3.50 /home/user/projects/myapp
# 2.10 /home/user/projects/api
# 1.20 /var/www/project-site
| Command | Description |
|---|
eval "$(zoxide init bash --cmd cd)" | Replace cd with zoxide in Bash |
eval "$(zoxide init zsh --cmd cd)" | Replace cd with zoxide in Zsh |
--cmd cd replaces cd command | Makes cd use zoxide (cd, cdi) |
--cmd j creates j and ji | Use custom command names |
Default creates z and zi | Standard zoxide commands |
| Command | Description |
|---|
--hook pwd | Update database on directory change (default) |
--hook prompt | Update database on every prompt |
--hook none | Disable automatic tracking |
# Replace cd in Bash with zoxide
eval "$(zoxide init bash --cmd cd)"
# Now 'cd' uses zoxide, 'cdi' opens interactive
# Use custom command name
eval "$(zoxide init zsh --cmd j)"
# Now 'j foo' jumps, 'ji' opens interactive
# Combine with fzf for enhanced experience
export _ZO_FZF_OPTS="--height 40% --reverse --border"
| Command | Description |
|---|
zoxide query foo | Show best match without jumping |
zoxide query foo --list | List all matches with scores |
zoxide query foo --score | Show matches with frecency scores |
zoxide query --all | List entire database |
zoxide query --all --score | List database with scores |
zoxide query --exclude /path | Exclude specific path from results |
zoxide query --list | head -20 | Top 20 directories |
| Command | Description |
|---|
zoxide add /path/to/dir | Manually add directory to database |
zoxide remove /path/to/dir | Remove directory from database |
zoxide edit | Open database in $EDITOR (interactive) |
Database stored at $_ZO_DATA_DIR/db.zo | Default database location |
# Check what zoxide would match
zoxide query project --list --score
# Output:
# 12.00 /home/user/projects/webapp
# 8.50 /home/user/projects/api
# 3.20 /home/user/old-project
# Manually seed the database for new machines
zoxide add ~/projects/webapp
zoxide add ~/projects/api
zoxide add ~/.config/nvim
# Remove stale entries (deleted directories)
zoxide query --all | while read -r dir; do
[ -d "$dir" ] || zoxide remove "$dir"
done
# Export database for backup
zoxide query --all --score > zoxide-backup.txt
| Command | Description |
|---|
zoxide import --from z path/to/.z | Import from z.sh database |
zoxide import --from autojump path/to/autojump.txt | Import from autojump database |
zoxide import --merge --from z path/to/.z | Merge import (keep existing entries) |
zoxide import --from z --merge ~/.z | Common z.sh import |
# Migrate from z.sh (most common)
zoxide import --from z ~/.z
# Migrate from autojump
zoxide import --from autojump ~/.local/share/autojump/autojump.txt
# Merge with existing database (don't overwrite)
zoxide import --merge --from z ~/.z
# After importing, verify
zoxide query --all --score | head -20
| Command | Description |
|---|
export _ZO_DATA_DIR="$HOME/.local/share/zoxide" | Set database directory |
export _ZO_ECHO=1 | Print matched directory before jumping |
export _ZO_EXCLUDE_DIRS="/tmp/*:/private/*" | Exclude directories from tracking |
export _ZO_FZF_OPTS="--height 40%" | Custom fzf options for zi |
export _ZO_MAXAGE=10000 | Set maximum database entries |
export _ZO_RESOLVE_SYMLINKS=1 | Resolve symlinks before storing |
# ~/.bashrc or ~/.zshrc — full zoxide configuration
# Set custom data directory
export _ZO_DATA_DIR="$HOME/.local/share/zoxide"
# Print the matched directory before jumping
export _ZO_ECHO=1
# Exclude temporary and system directories
export _ZO_EXCLUDE_DIRS="$HOME:$HOME/Downloads:/tmp/*:/private/*"
# Customize fzf appearance for interactive mode
export _ZO_FZF_OPTS="
--height 40%
--layout reverse
--border rounded
--preview 'ls -la {2..}'
--preview-window right:40%
"
# Maximum entries before pruning (default: 10000)
export _ZO_MAXAGE=10000
# Resolve symlinks to canonical paths
export _ZO_RESOLVE_SYMLINKS=1
# Initialize zoxide (must be AFTER exports)
eval "$(zoxide init zsh)"
| Command | Description |
|---|
z <Tab> | Autocomplete from tracked directories |
z foo<Tab> | Complete matching directories |
Bash completion via zoxide init | Automatic with shell init |
Zsh completion via zoxide init | Automatic with shell init |
Fish completion via zoxide init | Automatic with shell init |
-
Let zoxide learn naturally — Use your shell normally and zoxide will build its database from your habits. Don’t try to manually seed every directory.
-
Use two keywords for precision — When multiple directories match, add a second keyword: z proj api is more precise than z api alone.
-
Use trailing slash for subdirectories — z foo/ prefers subdirectories of the current directory named “foo”, while z foo searches the entire database.
-
Replace cd for maximum learning — Use --cmd cd in your shell init so every directory change feeds zoxide, not just when you remember to use z.
-
Configure exclusions early — Set _ZO_EXCLUDE_DIRS to skip temporary directories, build folders, and node_modules paths that pollute results.
-
Use zi for ambiguous jumps — When you’re not sure which directory will match, use zi (interactive) to preview and select from candidates.
-
Migrate existing data — If switching from z.sh, autojump, or fasd, import your database with zoxide import to start with a warm cache.
-
Clean stale entries — Periodically remove entries for deleted directories using zoxide edit or a cleanup script to keep results relevant.
-
Back up your database — Export with zoxide query --all --score before OS reinstalls or machine migrations.
-
Customize fzf appearance — Set _ZO_FZF_OPTS with --preview 'ls {2..}' to show directory contents in the interactive picker.