Better zsh history
misc zsh shell command-line
In a previous article - Unlimited Bash History, we discussed how to have a bigger(or unlimited) history for bash. This post is a follow-up on on that, and we will try to replicate the same for zsh. Let’s try to understand the different environment variables involved and tweak them to have a bigger(or unlimited) history. It’s also worth pointing out that bash and zsh have different default configurations with respect to history, and also the names of the history-related environment variables are also different between them.
Why do we need more history?
As developers, we find ourselves trying to remember a certain command we used in the past (which is pretty lengthy to
type or uses a specific combination of options/arguments).
The reverse history search(
ctrl-r) feature comes in very handy in such situations. This command lets you search through the history of commands stored in the
By default, zsh does not save the history to a file - This is not ideal since we will lose all our history once we exit a shell and there is no way to search/re-use previously used commands. By saving history to a file, and by letting the file grow very large, more commands can be retained and be available for searching.
Understanding related environment variables
Before we get started, let’s try to understand a few environment variables pertaining to history in zsh.
SAVEHIST- Refers to the number of commands that are stored in the zsh history file
HISTSIZE- Refers to the number of commands that are loaded into memory from the history file
HISTFILE- Refers to the path/location of the history file
By default, these variables are not set, and history is not persisted to a file.
However, if you are using plugins like Oh-my-zsh, some of these variables may have
been set already.
If you would like to know more about the different options available, do check out the man page for
man zshoptions from the commandline) or from the Zsh documentation online.
Steps to setup zsh to have unlimited history
1. Set the zsh history file
As we figured out earlier, zsh does not save history to a file by default. We need to set the
variable for that to happen. (If you are using plugins like zsh, search if the variable is already set by typing
echo $HISTFILE on the commandline - If set, you can choose to retain it and skip this step)
# In ~/.zshrc export HISTFILE=~/.zsh_history
2. Increase history size
In bash, Setting the
HISTSIZE variables to an empty string makes the bash history size unlimited.
However, it’s not possible to set the history to an unlimited size in zsh(theoretically, at least). From an zsh
mailing list, it appears the max history size can be
limits.h header file. That has a (really huge) value of 9223372036854775807, which should be enough to
store trillions of commands (a limit we’ll probably never hit). This number can be hard to remember - We can
just set this to a billion, and forget it.
# In ~/.zshrc export HISTFILESIZE=1000000000 export HISTSIZE=1000000000
Now that we have increased the size of our history, let’s try to make it more robust (And that means meddling with more environment variables!).
1. Immediate append
inc_append_history option ensures that commands are added to the history immediately (otherwise, this
would happen only when the shell exits, and you could lose history upon unexpected/unclean termination of the shell).
# In ~/.zshrc setopt INC_APPEND_HISTORY export HISTTIMEFORMAT="[%F %T] "
2. Add Timestamp to history
extended_history records the timestamp of each command in HISTFILE (along with the actual command)
You can later find out the exact time of execution for a command, if needed. Also, using the
to view the last n commands displays the timestamp information, in addition to the actual command:
# On the command line $ history -E -10 474 4.12.2019 00:08 unsetopt | grep extended 475 4.12.2019 00:08 history 5 476 4.12.2019 00:08 history -E 477 4.12.2019 00:09 man zsh 478 4.12.2019 00:09 man zshoptions | less -p EXTENDED_H 479 4.12.2019 00:10 cat ~/.zsh_history 480 4.12.2019 00:11 history -D 481 4.12.2019 00:11 history -E 482 4.12.2019 00:11 man history 483 4.12.2019 00:12 history -10
3. Handling duplicate commands
(While searching with
Ctrl+R) Stepping through the history with UP and DOWN keys becomes a bit annoying if the same
command comes up again and again. A better option is to skip duplicates and show each command only once with the
following setting. (Duplicate commands are still written to the history - However, they come up just once while
# In ~/.zshrc setopt HIST_FIND_NO_DUPS
We can take it up a notch by not writing duplicates to the history file at all, using the
# In ~/.zshrc setopt HIST_IGNORE_ALL_DUPS
This ensures all previous lines matching the current command is removed from history before the current command is saved.
Putting everything together
# In ~/.zshrc export HISTFILESIZE= export HISTSIZE= export HISTFILE=~/.zsh_history setopt HIST_FIND_NO_DUPS # following should be turned off, if sharing history via setopt SHARE_HISTORY setopt INC_APPEND_HISTORY
I use oh-my-zsh. Should I bother with any of this?
oh-my-zsh already already does most of the options discussed above (and lots of other options as well
) - Have a look here, if you’d like to understand
the specifics. I feel the
SAVEHIST value could be bigger than the
10000 oh-my-zsh uses, but everything else is
In this post, we saw how to make our zsh history bigger, so that searching for past commands is seamless. Personally, I didn’t think there was so much to zsh history(Boy, was I wrong!), and learnt a lot of things while setting this up - I hope you found the post useful too. See you in the next post.