Name a directory whatever you actually call it, and let zoxide find it.
cd ~/work/infra/terraform-prod-eu-west-1
zalias deploy
z deploy # from anywhere, forever afterNo wrapper around z, no fork of zoxide, no database of its own. About 150
lines of shell.
Most of us end up running two systems for getting around the filesystem, and neither one covers the other's ground.
Shell aliases — alias deploy='cd ~/work/infra/terraform-prod-eu-west-1' —
are precise and instant. You choose the word, so the word is the one in your
head. But the list is hand-maintained, it doesn't fuzzy-match, it doesn't know
which directories you actually use, and every new one is another line in a
dotfile you'll be reading in three years wondering if the path still exists.
zoxide fixes all of that. It learns where you go, ranks by frecency, and
matches on fragments, so z terra is enough. But it can only match words that
are in the path. A repo named Candela that adjusts screen brightness is
unreachable by z backlight, no matter how many times you visit it. The word
you'd search for exists only in your head, and there is nowhere to put it.
That's the gap. Aliases let you name things but can't search; zoxide can search but only over names it was given.
zalias puts your word into the path, where zoxide can already find it:
~/.local/share/zalias/deploy -> ~/work/infra/terraform-prod-eu-west-1
That symlink is a second, equally real path to the same directory. zoxide add
records it like any other. Now z deploy works — and so do zi deploy, the
fzf picker, frecency ranking, and every other zoxide feature, because as far as
zoxide is concerned nothing unusual has happened.
| shell alias | zoxide | zalias | |
|---|---|---|---|
| You choose the word | ✅ | ❌ | ✅ |
| Fuzzy / partial matching | ❌ | ✅ | ✅ |
| Ranked by how often you go there | ❌ | ✅ | ✅ |
| Works for a word not in the path | ✅ | ❌ | ✅ |
| Survives you forgetting the exact name | ❌ | ✅ | ✅ |
| One place to look at what exists | ❌ scattered in rc files | ✅ | ✅ zalias |
Requires zoxide. Bash 4+ or zsh.
git clone https://github.com/danielrosehill/zalias
cd zalias
./install.sh
exec $SHELLinstall.sh appends a source line to ~/.bashrc and/or ~/.zshrc (backing
each up first), and re-running it after moving the checkout repoints the
existing line rather than adding a second. Pass --bash or --zsh to pick
one. Or skip it entirely and source zalias.sh yourself — anywhere after
zoxide init.
To uninstall: delete the two-line block the installer added, and rm -rf the
alias directory.
zalias # list every alias
zalias NAME # alias the current directory
zalias NAME PATH # alias a specific directory
zalias rm NAME # remove one
zalias sync # re-add every alias to the zoxide database
zalias dir # where the symlinks liveHyphenate names and multi-word queries work, because zoxide requires each keyword to match the path in order with the last one matching the final component:
zalias personal-site # answers z personal, z site, and z personal sitezalias sync exists for when the zoxide database is disposable and gets
disposed of — you wiped it, or you restored your dotfiles onto a new machine
and the symlinks arrived before any of them had been visited. It re-adds every
live alias and skips dangling ones.
| Variable | Default | Meaning |
|---|---|---|
ZALIAS_DIR |
${XDG_DATA_HOME:-~/.local/share}/zalias |
Where the symlinks live |
ZALIAS_RESOLVE |
0 |
Land on the real path instead of the alias path |
By default you end up standing on the alias path, which has two consequences worth knowing before they surprise you:
z deploy
pwd # ~/.local/share/zalias/deploy — not the real path
cd .. # ~/.local/share/zalias — not the real parentNothing is broken — git, builds and relative paths all work, because the
symlink is transparent to anything that opens a file. It is the shell's own
bookkeeping (pwd -L, and ..) that shows the seam. Set ZALIAS_RESOLVE=1
and a chpwd/PROMPT_COMMAND hook drops you on the real path instead, at
which point the mechanism is invisible:
export ZALIAS_RESOLVE=1
z deploy
pwd # ~/work/infra/terraform-prod-eu-west-1
cd .. # ~/work/infraIt is off by default only because silently moving you somewhere other than where you asked to go is a rude thing for a tool to do without being asked.
The symlinks are the only state zalias has, and git stores a symlink natively
(mode 120000, with the target path as the blob), so a dotfile repo backs them
up exactly — a restore relinks rather than copying the directories behind them.
If your dotfile manager only commits files it already tracks (yadm's
yadm add -u, and most hand-rolled sync scripts, work this way), a newly
created alias will be backed up by nothing, silently. Define __zalias_hook
after sourcing to close that:
__zalias_hook() { yadm add -- "$1"; } # $1 = symlink path, $2 = add|removeThree facts, and nothing else:
- zoxide matches directories on the text of their path, ranked by frecency.
- A symlink is a second path to the same directory.
- zoxide does not resolve symlinks when adding, so it stores and matches the path you gave it, verbatim.
Point 3 is load-bearing. _ZO_RESOLVE_SYMLINKS defaults to 0; if you set
it to 1, every alias collapses onto its real path and silently stops
working. That is the one setting incompatible with this tool.
More detail, including the failure modes and why the resolve hook re-adds the alias before resolving: docs/how-it-works.md.
- Aliases are hand-written. This solves "I know my word and the path lacks it". It does not solve "I don't remember what I called it" — that needs searching repo descriptions, which is a different and much larger tool.
ZALIAS_DIRshows up inpwdunlessZALIAS_RESOLVE=1. See above.- Reserved names.
list,ls,rm,remove,sync,dir,helpare subcommands, so an alias by one of those names can't be managed through this front end. - Tested on Linux with bash. The zsh path uses
add-zsh-hookand avoids bash-only constructs (nomapfile, no-printf, noreadlink -f), and should work on macOS and BSD, but I haven't run it there. Reports welcome.
zoxide has no alias feature and, per its maintainer's design, isn't likely to grow one — it is deliberately a frecency-ranked matcher over paths you've visited. The symlink trick is a consequence of that design rather than a discovery; this repo is the packaging, the lifecycle management, and the written-down reasoning, not a new idea.
MIT.