You can approximate per-directory history in zsh using plugins or custom hooks. The shell itself doesn’t support this natively (though patches have been proposed). (zsh.org)
Here are viable methods:
Method 1: Use the “per-directory-history” plugin (Oh My Zsh or standalone)
- Oh My Zsh includes a plugin called
per-directory-history. (GitHub) - To enable it, add
per-directory-historyto yourplugins=( … )in~/.zshrc. (Unix & Linux Stack Exchange) - The plugin arranges that commands are saved to both a global history file and to per-directory-history files (mirroring the directory tree under a base history directory). (Jim Hester)
- There is a toggle (default key binding
Ctrl-G) to switch between viewing global history and directory-specific history. (GitHub) - You can configure base dir for per-directory history via a variable like
HISTORY_BASE. (GitHub)
Method 2: Use another plugin or custom “cwd-history” approach
- The plugin zsh-cwd-history stores separate
HISTFILEper directory and uses thechpwdhook to change history file when youcd. (Unix & Linux Stack Exchange) - Another project: ericfreese/zsh-cwd-history (mentioned in StackOverflow answers) (Unix & Linux Stack Exchange)
- You can bind a key to toggle between directory history vs global history in such plugins. (Unix & Linux Stack Exchange)
Method 3: DIY using hooks (zshaddhistory / chpwd)
If you want to roll your own:
-
In your
~/.zshrc, set a base directory to store local histories, e.g.:export DIRHIST_BASE="$HOME/.dirhist" -
Use
chpwdhook (runs on eachcd) to switchHISTFILE:function chpwd_set_histfile() { local dir_rel="${PWD/#$HOME\//}" # directory relative to home local histf="${DIRHIST_BASE}/${dir_rel}/.zsh_history" mkdir -p "$(dirname "$histf")" HISTFILE="$histf" } autoload -U add-zsh-hook add-zsh-hook chpwd chpwd_set_histfile -
Optionally, when starting the shell (at prompt or init), you may want to load the relevant directory history:
if [[ -n $PWD ]]; then chpwd_set_histfile fc -R # read history from the new HISTFILE fi -
You may also want to duplicate commands into a global history file (so you don’t lose cross-dir commands). You can use the
zshaddhistoryfunction to append each new command to a global log as well. Example:function zshaddhistory() { local cmd=${1%%$'\n'} # strip newline print -sr -- "$cmd" # to current HISTFILE print -s -- "$cmd" >> "$HOME/.zsh_global_history" return 1 # prevent double logging by default handler }
Caveats:
- You must manage
HISTSIZE,SAVEHIST, trimming, etc. - If you have concurrent shells in the same directory, they write to the same file.
- Performance may degrade if you have many directories with deep trees.
- Some plugins limit history size per directory.
If you like, I can generate a ready-to-use .zshrc snippet (or plugin setup) for your environment (Linux/macOS). Do you prefer plugin-based or DIY?
Would you recommend using a per-directory history setup, or is it more trouble than it’s worth?
It depends on how you work and how much benefit you'd get vs overhead. Here’s a breakdown to help you decide.
Pros
Easier recall in project contexts When you're working in a particular directory (project), your relevant commands are grouped. You don’t sift through unrelated commands.
Cleaner history per context Less “noise” when using reverse-search (
Ctrl-R) or browsing history while in a directory.Better separation If you work on many unrelated things, per-directory history isolates each context.
Toggle flexibility Some plugins allow toggling between global and per-directory history. (e.g. the
per-directory-historyplugin in Oh My Zsh) (Unix & Linux Stack Exchange)Cons / Costs
Implementation complexity / maintenance burden You’ll need to manage hooks (
chpwd,zshaddhistory), directory tree creation, collisions, trimming histories, etc.Cross-shell or concurrent sessions issues Two shells in the same directory may write to the same history file -> race conditions or interleaving.
Disk & file overhead Many small history files over deep directory trees will clutter your
~/.dirhist(or whatever base).Fragmentation of history Sometimes you do want to search across all your commands globally. If you forget some context, per-dir history might hide useful commands you used elsewhere.
Plugin shortcomings / bugs Some users report that existing plugins don’t handle all edge cases (editing history, switching modes reliably). (Unix & Linux Stack Exchange)
Recommendation
per-directory-history) and use it for a few weeks. If you like the improvement and don’t hit issues, keep it.If you like, I can simulate (or produce) a benchmark or user feedback comparing both setups for your workflow to see whether it's worth it for you. Do you want me to do that?