zhist
Zsh history store with directory and exit-status context
TLDR
SYNOPSIS
zhist initzhist add -dir dir -exit n [-ts unix]zhist list [-dir dir]zhist get -id idzhist delete -id id [-all]zhist import file
DESCRIPTION
zhist is a zsh-only shell history tool written in Go. It replaces the zsh history file as the persistent store and records each command together with its working directory and exit status. Native zsh history keeps only the command and a timestamp; zhist keeps that extra context so the picker can highlight failures and switch between global history and the current directory.The interactive UI is fzf, not a custom TUI. `eval "$(zhist init)"` emits zsh hooks and keybindings that call the zhist binary: a preexec/precmd pair appends each command via zhist add, and ctrl-r (plus bare up/down on an empty line) opens zhist list in fzf. Failed commands render in red. ctrl-g toggles global versus directory-scoped history.Entries are appended as JSON lines to ~/.local/share/zhist/history.jsonl (mode 0600), or to the path in ZHIST_FILE. Imported zsh EXTENDED_HISTORY lines have no directory or exit status; they show a blank directory and never render red.
PARAMETERS
init
Print the zsh integration script (hooks, fzf picker, and keybindings). Intended for `eval "$(zhist init)"`.add -dir dir -exit n [-ts unix]
Append one entry. Command text is read from stdin. -ts defaults to the current Unix time.list [-dir dir]
Print entries for fzf: newest first, one unique command per line, tab-separated id / relative time / command. -dir keeps only entries recorded in that directory.get -id id
Print the full command for an entry (including embedded newlines).delete -id id [-all]
Delete the entry with that id. -all also deletes every other entry with the same command text.import file
Import a zsh EXTENDED_HISTORY file (`: timestamp:elapsed;command` lines). Prints `imported N entries`.
CONFIGURATION
Add to ~/.zshrc after any plugin that binds ctrl-r or the arrow keys (the last bind wins):
Override the JSONL store path (default ~/.local/share/zhist/history.jsonl).Because zhist owns persistence, keep native zsh history in memory only:
HISTSIZE=100000
SAVEHIST=0
KEY BINDINGS
These bindings are installed by zhist init:ctrl-r
Open the history picker.up / down
Open the picker when the line is empty; otherwise step native line history.ctrl-g
Toggle global versus current-directory history.ctrl-d
Delete the selected entry.ctrl-x
Delete all entries with the same command.tab
Accept and leave the command on the line.ctrl-/
Toggle the command preview pane. Visibility is remembered in ${XDG_STATE_HOME:-$HOME/.local/state}/zhist/preview-hidden.
CAVEATS
zsh only; there is no bash or fish integration. The picker requires fzf 0.45 or newer. `eval "$(zhist init)"` must run after atuin, zsh-history-substring-search, or other widgets that bind the same keys. Building from source via go install needs the Go version declared in the module. Imported history has no directory or exit status. The record hook prepends itself to precmd_functions and passes $? through so later prompt hooks still see the real exit status.
HISTORY
zhist was created by overflowy in August 2026. It is written in Go and released under the MIT license. The store is JSON Lines; the search UI is delegated to fzf.
