CLI tool
agkozak/zsh-z avatar
agkozak/zsh-z

zsh-z: frecency-based directory jumping, rewritten in pure Zsh

Jump quickly to directories that you have visited "frecently." A native Zsh port of z.sh with added features.

2,457 stars80 forksShellMIT

At a glance

What is it?
A native Zsh port of rupa/z that drops every external command from the hot path, locks its datafile properly, and shipped a large v2.0 in August 2026.
Who is it for?
zsh-z is the right pick if you already live in Zsh and want directory jumping that costs nothing per prompt, and the wrong pick if you need one script that works in Bash too, because that portability was exactly what the rewrite gave up. Two things decide it for most people: whether you are on Cygwin, MSYS2 or WSL where the fork savings are large, and whether you can live with a datafile that only Zsh reads.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Shell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 7, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What frecency actually scores

The core idea is older than this port. zsh-z watches when you enter a directory and how long you stay there, then ranks directories by a blend of frequency and recency, the property the README calls frecency. Type a partial string and it jumps to whichever path scores highest among the matches.

The README's own example is the clearest illustration: `z src` might land you in `~/src/zsh`, `z zsh` might get you there too, and `z c/z` might be more specific still. Which one wins depends on your habits and how long the datafile has been accumulating. That is a real trade in ergonomics. You give up predictability, because the answer depends on history, and you get speed, because the string you type gets shorter the more you use it.

The database is a single file, `~/.z` by default, or whatever you point `ZSHZ_DATA` at. Because it is a plain text datafile rather than a compiled database, you can inspect it, move it between machines, and start from scratch by deleting it.

Why the rewrite dropped awk, sort and date

The original `rupa/z` is a bash and Zsh tool that leans on embedded `awk` scripts for the heavy lifting. agkozak used it heavily, then translated it, awk parts included, into pure Zsh. The stated goal was to eliminate calls to external tools and the forking that comes with subshells.

The list of tools that disappeared is worth reading closely: `awk`, `sort`, `date`, `sed`, `mv`, `rm` and `chown`. On a normal Linux box that is a modest win. On Windows-adjacent environments the author calls out by name, Cygwin, MSYS2 and WSL, forking is slow enough that the savings become the reason to switch. A `cd`-adjacent command that runs on every single prompt is exactly the kind of thing you notice when it forks eight processes.

The port also kept compatibility in a way that surprises people. By default zsh-z reads and writes the same `~/.z` database as `rupa/z`, and the README calls it a drop-in replacement, so you can keep using the original when you launch Bash and get the new one in Zsh.

The v2.0 write path, which is where the real work landed

The v2.0.0 release was published on 2026-08-14 and is described in the README as the most significant release in the project's history. The headline is that database writes never block your prompt on any platform.

The mechanism is small and worth understanding. The per-prompt `--add` that records where you just were used to run in the background on most systems but ran in the foreground on Cygwin and MSYS2, because backgrounding there cost a wrapper subshell plus a job. It now runs as a single disowned job on every platform. The release notes put numbers on it: a foreground write whose cost grows with the datafile, roughly 30 ms at 300 entries and roughly 300 ms at 1,000 entries, becomes a flat 10 to 12 ms fork. Elsewhere it halves the forks per prompt.

Concurrency got the same treatment. Writes use a dedicated lockfile through `zsh/system` file locking with a bounded wait, and the new `ZSHZ_LOCK_TIMEOUT` setting defaults to 1 second. Locks are released even if a write is interrupted, and on Cygwin and MSYS2 a rename Windows refuses is retried briefly, because a virus scanner or the search indexer opening the file in the instant before it moves used to drop one directory silently. The v2.0 release also moved the datafile to `600` permissions, readable only by you, which closes a small leak on shared machines.

Tab completion that ranks by score instead of alphabetically

One of the smaller changes has an outsized effect on daily use. Tab completions are sorted by frecency by default rather than alphabetically, and the README notes that the old behaviour can be restored through its settings section.

That sounds cosmetic until you consider what alphabetical sorting does to a completion list built from your own directory history. It returns every match in dictionary order, which is roughly the opposite of useful. Ranking by the same score that powers the jump makes the completion menu put the directory you almost certainly want at the top.

The release also fixed completion under `setopt COMPLETE_ALIASES`. Earlier versions needed a manual `compdef` line in your configuration; v2.0 registers the alias automatically on the first Tab press, so a fresh install no longer requires you to know that line exists. If you are migrating from an older zsh-z and have that `compdef` in your `.zshrc`, it is now redundant rather than harmful.

Configuration surface and migrating away from other jumpers

The repository is small: a `zsh-z.plugin.zsh` file for plugin managers, the `_zshz` script itself, a `tests/` directory, an `img/` directory for the badges and demo, and a `.github/` directory holding the workflow. Installing is a matter of sourcing the script from your configuration, or letting a plugin manager pick up the plugin file.

bash
source _zshz
+

Beyond the datafile location, the settings the README calls out include `ZSHZ_UNCOMMON`, which controls whether directories outside your home directory or outside a set list are eligible at all, and `ZSHZ_OWNER` for shared systems where the datafile needs an explicit owner. There is a case sensitivity section as well, since path matching behaves differently on case-insensitive filesystems.

The README also has a section on making `--add` work for you, which is about the per-prompt hook rather than about jumping, and a migrating section aimed at people coming from other directory jumpers. The repository topics list `autojump`, which is the competitor most readers will compare against, and the honest difference is that autojump weights by frequency and match quality while zsh-z weights by time spent and recency as well.

Bugs fixed in v2.0 that would have bitten you anyway

Several of the v2.0 fixes are worth reading as a list of things that could break a shell on a slow Tuesday.

On some Zsh builds every database write failed with `can't clobber parameter tmpfd containing file descriptor 0`, which left an error message at every new prompt. The temporary database file descriptor is now held in an unset scalar rather than one seeded with `0`. Separately, when `ZSHZ_DATA` points at a directory, or names a file without a directory component, older versions called `exit` and could close your shell outright; now the tool reports the problem and returns, and the per-prompt hook stays quiet about it so you hear about it once, when you actually run `z`.

There is also `z -x`, which can now remove an entry whose directory no longer exists, and no longer crashes Zsh 4.3.11 on a path with a missing top-level component. The minimum supported version is Zsh 4.3.11, which the README badges state explicitly, and the release notes claim the new read and write paths beat `rupa/z` on both modern Zsh and that oldest supported version.

Maintenance is current. The repository is not archived, the last push was on 2026-09-23, and v2.0.0 shipped with a 264-test suite and CI across five platforms, which is a level of testing discipline unusual for a shell plugin of this size.

Editorial conclusion

zsh-z is the right pick if you already live in Zsh and want directory jumping that costs nothing per prompt, and the wrong pick if you need one script that works in Bash too, because that portability was exactly what the rewrite gave up. Two things decide it for most people: whether you are on Cygwin, MSYS2 or WSL where the fork savings are large, and whether you can live with a datafile that only Zsh reads. Start by sourcing `_zshz` from your `.zshrc`, let the per-prompt `--add` run for a week, and only then look at `ZSHZ_UNCOMMON`, the lock timeout setting, and the completion sort order.

Frequently asked questions

What is zsh z?

Zsh-z is a directory jumping tool for Zsh that ranks the directories you visit by frecency, a blend of how often you go there and how recently. You type a partial path such as `z src` and it moves you to whichever matching directory has the highest score, keeping its data in a plain text file at `~/.z` by default.

How is zsh-z different from autojump?

Both jump to directories by partial match, but they score differently. zsh-z tracks both how often you visit a directory and how much time you spend there, so recency matters, while autojump leans on frequency and match quality. zsh-z also stays pure Zsh with no external commands in the hot path, and reads the same `~/.z` datafile as rupa/z.

Does zsh-z slow down my shell prompt?

Since v2.0, the per-prompt `--add` runs as a single disowned background job on every platform, including Cygwin and MSYS2 where earlier versions wrote in the foreground. The release notes put the old foreground cost at roughly 300 ms with 1,000 entries and the new one at a flat 10 to 12 ms fork, with a lockfile and a `ZSHZ_LOCK_TIMEOUT` of 1 second guarding the write.

Official sources

  1. agkozak/zsh-z on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/agkozak-zsh-z.svg)](https://hysenlabs.com/projects/agkozak-zsh-z)