Article summary
Previously, I wrote a blog post called How (and Why) to Log Your Entire Bash History. A few years ago, I switched from bash to zsh, and in doing so realized that my bash technique was no longer applicable.
I needed to find a new way to log every command to files corresponding to the date they were executed.
Zsh History Configuration
zsh itself has a number of configuration options for fine tuning control of its built-in history functionality.
As pointed out in a comment on my original post, this Stack Overflow answer indicates that it’s possible to configure zsh to save every command before it’s executed, and to read the history file every time history is accessed:
setopt inc_append_history
setopt share_history
This allows for the sharing of the built-in zsh history across terminals/sessions with zsh. And that’s great – but it doesn’t help with my desire for daily logs of commands that have been executed.
Zsh Hooks
My bash solution was to append the previous command to a file as part of the PROMPT_COMMAND
variable. Another commenter on my original post suggested that it’s possible to do the same in zsh by using the preexec
hook.
The Mastering ZSH book has the following description of the preexec
hook:
preexec is executed between when you press enter on a command prompt but before the command is executed.
By adding the following to my .zshrc
file, I was able to reproduce the same functionality I had in bash.
preexec () {
local fmt_date="$(date +'%Y-%m-%d.%H:%M:%S')" >& /dev/null
echo "${fmt_date} \"${PWD}\" $1" >> ~/.logs/zsh-history-$(date "+%Y-%m-%d").log
}
Conclusion
I’ve now been storing every single command to daily log files for over 12 years. There have been countless times when I’ve gone spelunking in those logs to try to piece together something I had done in the past. I know there are more sophisticated ways to do this – but the simplicity of this approach has worked well for me.