Localize shell history for projects

I frequently work on multiple projects in parallel, the terminal application always open and in use.
Shell history is very helpful for recalling commands, but I prefer to have just those available in the history which relate to the project for the current folder.
It would be nice to keep the command-line history separate depending on the folder open. Linux/macOS terminal shells are able to do that. I am configuring zsh to keep history apart based on the (current) working directory.
Configuration Example zsh
- Create a
zshhistory configuration script. - Invoke the script in through the
~/.zshrcconfiguration file.
Steps
Install ~/.zshrc-history.sh
cat << EOF > ~/.zshrc-history.sh
export HISTFILE="$HOME/.zsh_history"
export HISTSIZE=100000
export SAVEHIST=100000
setopt APPEND_HISTORY
setopt HIST_IGNORE_DUPS
setopt INC_APPEND_HISTORY
function _set_dir_history() {
local dir="$PWD"
local target_file="$HOME/.zsh_history"
while [[ "$dir" != "/" ]]; do
if [[ -f "$dir/.zsh_history.local" ]]; then
target_file="$dir/.zsh_history.local"
break
fi
dir="${dir:h}"
done
# Only flush and reload history if the file actually changed
if [[ "$HISTFILE" != "$target_file" ]]; then
fc -P
export HISTFILE="$target_file"
fc -R
fi
}
function chpwd() {
_set_dir_history
}
# run once when shell starts
_set_dir_history
EOFAdd
echo "source ~/.zshrc-history.sh" >> ~/.zshrcActivate the new zsh history configuration.
source ~/.zshrcHow it works
The script optimizes performance by only flushing and reloading history when actually switching between history files. Without this check, every cd would incur file I/O overhead even when the target history file hasn’t changed. The condition if [[ "$HISTFILE" != "$target_file" ]] ensures fc -P and fc -R only run during actual file transitions.
You are now ready to configure individual project directories to have their own zsh history.
Enable local zsh history for a directory
cd ~/projects/my_project
touch .zsh_history.local
# Optional
echo ".zsh_history.local" >> .gitignoreAll command-line history is added to ~/projects/my_project/.zsh_history.local while executing commands inside that directory or one of its subdirectories. Commands issued whilst visting other directories continue to be added to ~/.zsh_history unless those also have local history enabled.
~/.zsh_history (or whatever history file you have defined) remains the history target if .zsh_history.local is not defined in your current folder or any of the parent folders.
Other Shells
The approach to have localised works in principle for other shells, such as bash. But those will/may need shell specific adjustments.
Summary
Not much work for a noticable gain, reduction of annoyance and smoother use of commandline.