Keeping history per working directory (cf. per shell session)

Is there a way to make a modern shell’s history feature be scoped to a path?

My working contexts are split up as paths on the file system, and the pattern of shell activity, such as repeatedly issued commands, tends to be distinct to each ‘project’. It would be nice if I could scope the history feature to commands issued from the current path (or sub-path).

Asked By: sohocoke


Not a neat answer but an alternative if you’re using bash as your shell: you could createt some alias in your .bashrc.

For instance:

alias a='cd /tmp/A ; history -w ; history -c ; export HISTFILE=/home/user/.a_history ; history -r $HISTFILE'
alias b='cd /tmp/B ; history -w ; history -c ; export HISTFILE=/home/user/.b_history ; history -r $HISTFILE'

Then, if you type a:

  1. you will be moved in your project directory
  2. the current history will be saved (history -w)
  3. then the history kept in memory will be reset (history -c)
  4. the project history file will be set to /home/user/.a_history and read (history -r)
Answered By: apaul

With zsh, you could do:

mkdir -p ~/.zsh/dirhist

And add to your ~/.zshrc:

chpwd() {
  [[ $PWD = $OLDPWD ]] || fc -Pp ~/.zsh/dirhist/${PWD////@}

chpwd() is called whenever the current directory changes. There, we reset the history file to something like ~/.zsh/dirhist/@foo@bar when you cd to /foo/bar.

Answered By: Stéphane Chazelas

If you are using ZSH, take a look at this small plugin I recently wrote to handle this:

It stores a separate HISTFILE for every directory you’ve executed commands in, and adds a chpwd hook to switch between HISTFILEs when you change directories.

It also provides a zle widget you can bind to a keypress that will toggle the HISTFILE between your original “global” HISTFILE and the HISTFILE for your current working directory.

It was originally based on Jim Hester’s per-directory-history plugin, but has since been rewritten from the ground up to fix many of the issues with that plugin.

Answered By: Eric Freese

I wrote a ZSH plugin which does what you want:

In contrast to other solutions my plugin falls back to the global history automatically. That means that you don’t have to switch between directory history and global history.

However the other solutions are a little more lightweight I guess.

Answered By: tymm