11

I would like to both share history across terminals and keep track of elapsed time for history commands. The intuitive way seems to be to use both EXTENDED_HISTORY and SHARE_HISTORY, but this sets all elapsed timestamps to 0 after restarting the shell. Is this the correct way to do it? Is it even possible?

Scenario 1: EXTENDED_HISTORY and SHARE_HISTORY

$ history -Dn | sed 's|\\n|\n      |g'
0:00  cat << EOF > ~/.zshrc
          HISTFILE=~/.zhistory-test
          HISTSIZE=100
          SAVEHIST=100
          setopt EXTENDED_HISTORY
          setopt SHARE_HISTORY # the only change compared to below
      EOF
0:00  exec zsh

0:00sleep 1

0:00  exec zsh

Scenario 2: only EXTENDED_HISTORY

$ history -Dn | sed 's|\\n|\n      |g'
0:00  cat << EOF > ~/.zshrc
          HISTFILE=~/.zhistory-test
          HISTSIZE=100
          SAVEHIST=100
          setopt EXTENDED_HISTORY
      EOF
0:00  exec zsh

0:01sleep 1

0:00  exec zsh

Scenario 3: INC_APPEND_HISTORY and SHARE_HISTORY

Same as scenario 1, but replacing SHARE_HISTORY with INC_APPEND_HISTORY seems to have the same effect.

System info

$ zsh --version

zsh 5.4.2 (x86_64-unknown-linux-musl)

$ ldd /usr/bin/zsh

        /lib/ld-musl-x86_64.so.1 (0x7f0f8b1d8000)
        libcap.so.2 => /lib/libcap.so.2 (0x7f0f8acfa000)
        libncursesw.so.6 => /lib/libncursesw.so.6 (0x7f0f8aa89000)
        libc.so => /lib/ld-musl-x86_64.so.1 (0x7f0f8b1d8000)

$ uname -a

Linux hostname 4.12.13_1 #1 SMP PREEMPT Thu Sep 14 13:15:00 UTC 2017 x86_64 GNU/Linux

$ lsb_release -d

Description:    Void Linux
2
  • I was looking for this too. I like how INC_APPEND_HISTORY_TIME works, but it doesn't appear to work with SHARE_HISTORY. I guess we are looking for a SHARE_HISTORY_TIME. Feb 2, 2020 at 20:57
  • @whatsthatitspat What do you think of my answer? Jan 31, 2021 at 15:46

2 Answers 2

3

I’ve tested several ways of trying to share extended history between multiple terminal sessions and this is the only one that seems to work flawlessly:

autoload -Uz add-zsh-hook

setopt extendedhistory incappendhistorytime

load-shared-history() {
  # Pop the current history off the history stack, so we don't grow
  # the history stack endlessly
  fc -P

  # Load a new history from $HISTFILE and push it onto the history 
  # stack.
  fc -p $HISTFILE
}

# Import the latest history at the start of each new command line.
add-zsh-hook precmd load-shared-history

Now all you need to do to sync your history in any terminal session is to press Enter.

3
  • Out of curiosity, did you try doing fc -RI? That's what the zsh manual recommends as the way to "manually" load history when not using SHARE_HISTORY. Dec 28, 2022 at 23:59
  • 1
    It’s been two years since I answered this, but as far as I recall, nothing else I tried would keep the recorded times of your commands intact, which is what OP asked for. You’re welcome to test this yourself, though. Dec 31, 2022 at 19:58
  • Yeah, I looked at it, the downside is that of course the commands don't become available in your history until they complete. So if you want to quickly launch a few long running commands, it may be a bit more annoying. The ideal IMHO would actually be to have two history files: one that doesn't save durations, one that does. Search for historical commands in the former, search for durations (when you need them) in the latter. I may look into it; I don't think it's that bad. Jan 1, 2023 at 1:01
1

The only option you need is SHARE_HISTORY

Here's a video of shared history working

And here's the documentation linked + quoted

This option both imports new commands from the history file, and also causes your typed commands to be appended to the history file (the latter is like specifying INC_APPEND_HISTORY, which should be turned off if this option is in effect). The history lines are also output with timestamps ala EXTENDED_HISTORY (which makes it easier to find the spot where we left off reading the file after it gets re-written).

By default, history movement commands visit the imported lines as well as the local lines, but you can toggle this on and off with the set-local-history zle binding. It is also possible to create a zle widget that will make some commands ignore imported commands, and some include them.

If you find that you want more control over when commands get imported, you may wish to turn SHARE_HISTORY off, INC_APPEND_HISTORY or INC_APPEND_HISTORY_TIME (see above) on, and then manually import commands whenever you need them using ‘fc -RI’.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .