I used to navigate my filesystem one directory at a time. `cd ~/Projects`, then `ls`, then `cd websites`, then `ls`, then `cd jeffbaileyblog`, then `ls`, then `cd hugo`. Every trip to a familiar directory cost me four or five commands. Tab-completion helped a little, but I still had to remember the path. Then I installed zoxide, and `cd` started reading my mind. ## What zoxide actually is Zoxide is a smarter replacement for `cd`. It watches where you go in your terminal, ranks those directories by how often and how recently you visit them, and lets you jump to any of them by typing a fragment of the path. Instead of `cd ~/Projects/websites/jeffbaileyblog/hugo`, I type `z hugo`. Zoxide remembers that I live in that directory most days, and it takes me there. [Ajeet D'Souza][ajeet] wrote it in Rust. It's a single binary with no runtime dependencies. It works in bash, zsh, fish, PowerShell, nushell, and a handful of others. You install it once, add a line to your shell config, and `z` replaces `cd` for most of your navigation. [ajeet]: https://github.com/ajeetdsouza The word that matters here is "frecency," a blend of frequency and recency. Zoxide doesn't just track your most-visited directories. It weights recent visits more heavily than old ones, so the ranking adapts as your work shifts. The directory you lived in last quarter fades. The one you've been in all week rises to the top. ## Why zoxide exists Traditional `cd` treats every navigation as a fresh problem. You tell it exactly where to go, and it goes. It has no memory. It doesn't care that you've visited `~/Projects/websites/jeffbaileyblog/hugo` six times today. The seventh time, you still have to type it all out (or tab-complete through it). That's fine for directories you visit once. It's wasteful for the ten or so directories you actually live in. Zoxide started as a Rust rewrite of earlier tools. [z][z] came first, written in shell by Rupa Vedula. Then [autojump][autojump] in Python, and [fasd][fasd] as another shell-based variant. Each one had the same idea: the shell should learn where you go, and jumping should take one short command. Zoxide took that idea and made it fast and portable. Rust gave it near-instant startup (a cold `z` resolves in microseconds on my machine). The single-binary distribution removed the dependency headaches that plagued the Python and shell versions. And the interface got simpler: one command (`z`) and one interactive variant (`zi`). [z]: https://github.com/rupa/z [autojump]: https://github.com/wting/autojump [fasd]: https://github.com/clvv/fasd ## The mental model: frecency as your shell's intuition Zoxide's core idea is frecency. Every time you `cd` into a directory, zoxide bumps that directory's score. Over time, directories you visit a lot and recently float to the top of the ranking. Directories you visited months ago sink. ```mermaid graph TB A[You cd into a directory] --> B[Zoxide records the visit] B --> C[Score = frequency × recency weight] C --> D[z query matches fragment] D --> E[Highest-scoring match wins] style A fill:#e1f5fe style B fill:#f3e5f5 style C fill:#e8f5e8 style D fill:#fff3e0 style E fill:#ffe0e0 ``` The ranking is the whole trick. When I type `z hugo`, zoxide scans its database for every directory whose path contains "hugo," then returns the one with the highest frecency score. That's almost always the one I want, because I go there daily. Zoxide's algorithm decays old visits using a simple formula. A visit today counts more than a visit yesterday, which counts more than a visit last month. The decay is gradual, so a directory you used heavily last quarter still shows up, but a directory you've been hitting all week outranks it. This matches how humans actually use filesystems. I don't visit 500 directories evenly. I cycle through ten or fifteen active projects, with the mix shifting every few weeks. Frecency captures that pattern directly. ## How the commands work Zoxide exposes two main commands: `z` for non-interactive jumps, and `zi` for interactive selection. ### z: jump to the best match `z fragment` searches your frecency database and jumps to the top-scoring directory that matches. You can pass multiple fragments to narrow further: ```bash z hugo # jump to the best "hugo" directory z blog what-x # jump to a directory matching both "blog" and "what-x" z proj web # disambiguate between multiple projects ``` Fragments don't have to be contiguous in the path. `z proj web` matches `~/Projects/websites` because both words appear in order. That matters when you have similar directory names across several roots. If you type `z` with no argument, zoxide takes you home. If you type `z -` (a single dash), it takes you to the previous directory, just like `cd -`. ### zi: interactive mode `zi` opens an [fzf][fzf]-backed picker showing your top-ranked directories. You type to filter the list, arrow-key through the matches, and hit enter to jump. I use `zi` when my query is ambiguous. If I type `z config` and zoxide sends me to the wrong config directory, I run `zi config` next, see the full list, and pick the right one. After that, zoxide learns my preference (the selected directory's frecency bumps up) and `z config` goes to the correct place next time. [fzf]: https://jeffbailey.us/blog/2026/04/25/what-is-fzf/ ## Zoxide and fzf: two filters that compose Zoxide and [fzf][fzf] solve adjacent problems. Fzf filters any list interactively. Zoxide maintains a ranked list of directories. Put them together and you get the best of both: a small, relevant list of your most-used directories, filtered interactively. This is what `zi` does under the hood. It asks zoxide for the ranked list, then pipes that list into fzf for picking. The mental model composes cleanly: * Zoxide knows *where you go*. * Fzf lets you *pick from a list*. * Together they let you *pick from where you go*. That's why zoxide lists fzf as an optional dependency. Without fzf, `zi` falls back to a simpler picker. With fzf, `zi` feels like the fuzzy finder you'd build for shell navigation if you were designing one from scratch. ## Setup in practice Zoxide ships as a single binary, but it needs a shell hook to intercept `cd` and keep its database current. The install step is two lines in your shell config. For zsh: ```bash eval "$(zoxide init zsh)" ``` For bash: ```bash eval "$(zoxide init bash)" ``` For fish, in `~/.config/fish/config.fish`: ```fish zoxide init fish | source ``` Many people also alias `cd` to `z`, so every navigation feeds the frecency database: ```bash eval "$(zoxide init zsh --cmd cd)" ``` After that line, `cd` *is* `z`. The original `cd` still works for directories zoxide doesn't know yet (it falls back when the query doesn't match any ranked directory), and every directory you visit gets recorded. I run with `--cmd cd` because I don't want two navigation commands in my muscle memory. One command that gets smarter over time beats two commands that I have to remember to switch between. ## What zoxide is not Zoxide is not a file finder. It only tracks directories. If you want to find a file inside a directory, that's [fzf's][fzf] job, or `find`, or `fd`. Zoxide is not a shell history tool. It doesn't record commands, only navigation. Ctrl+R (or fzf's history widget) handles command recall. Zoxide is not a tool for exploring directories you've never visited. It can only rank directories you've been to at least once. The first visit still costs you a full `cd` with a real path, and tab-completion still matters for that first trip. Understanding those boundaries helps. Zoxide is small on purpose. It does one thing (rank directories by frecency) and composes with other tools for everything else. ## Common misconceptions **"Zoxide will mess up my muscle memory."** It won't if you let it replace `cd` entirely. The problem comes from running `z` and `cd` side by side and switching based on whether you "think" zoxide knows the directory. Pick one, use it always, and your hands adapt within a week. **"Zoxide needs to index my whole filesystem."** No. Zoxide only records directories you actually visit. The database grows as you work, not up front. On a fresh install, zoxide knows nothing and stays out of your way until you've visited a few places. **"Zoxide is just another `cd` alias."** The frecency ranking is the whole point. Without the ranking, it would be a worse tab-completer. With the ranking, it predicts where you want to go from a fragment that would be ambiguous to any other tool. **"Zoxide replaces fzf."** It doesn't. They solve different problems and compose naturally. Fzf filters lists. Zoxide produces a ranked list of directories. Use both. ## Trade-offs and limitations Zoxide is small and focused, but it has costs worth understanding. * **It needs training time.** A fresh install is useless. Zoxide gets better as you use it, with the real payoff arriving after a week or two of normal work. * **Wrong matches happen.** Early on, `z config` might send you to `~/old-project/config` instead of `~/current-project/config` because the old one has more history. The fix is to use `zi` once to pick the right directory, which bumps its score, or to use `--remove` to delete stale entries. * **It's shell-coupled.** Zoxide works through shell hooks. If you use a terminal multiplexer or a non-interactive shell, some of the recording might miss. In practice this rarely matters, but worth knowing. * **The database can grow.** Over years, your frecency database accumulates directories you no longer care about. Zoxide provides `zoxide query -l` to list ranked directories and `zoxide remove` to clean them out. I prune mine maybe once a year. * **It doesn't work on fresh machines.** Moving to a new laptop means starting from zero unless you copy over the database file. For most people that's fine (rebuilding frecency is fast once you start working), but it's a real cost. ## The core idea Zoxide solves a problem you probably don't notice until someone points it out: you spend a surprising amount of terminal time typing paths you've already typed hundreds of times. The mental model is a single sentence. Zoxide tracks where you go and lets you jump back with a fragment. The frecency ranking makes "the best match" almost always the one you wanted. The composition with fzf (through `zi`) handles the cases where it isn't. Once the database warms up, `z` replaces `cd` for most of my navigation. I still reach for `cd` when I'm exploring somewhere new, but for the ten directories I live in, one short command and a fragment gets me there. ## Next steps * Install zoxide from [the official repository][zoxide-repo] and add the init line to your shell config. * Try aliasing `cd` to `z` with `--cmd cd` so every navigation trains the frecency database. * Pair zoxide with [fzf][fzf] if you haven't already. `zi` becomes a fuzzy directory picker that knows where you actually work. * Read about [what fzf is][fzf] to see how the two tools compose. * Explore [shell configuration][configure-shell] for more terminal productivity patterns. [zoxide-repo]: https://github.com/ajeetdsouza/zoxide [configure-shell]: https://jeffbailey.us/how-do-i-configure-my-shell/ ## References * [zoxide official repository][zoxide-repo], the source, install instructions, and configuration docs by Ajeet D'Souza. * [z][z], the original shell-based frecency tool by Rupa Vedula that inspired zoxide. * [autojump][autojump], a Python-based predecessor with similar frecency semantics. * [fasd][fasd], another shell-based tool that tracks files and directories by frecency. * [What is fzf?][fzf], the fuzzy finder that zoxide uses for its interactive `zi` picker.