Zsh command history holds past terminal commands in memory and, when enabled, on disk. You can inspect both lists, remove an unwanted command, and verify it stays removed in a fresh shell.

The active history list belongs to the current shell, while the saved history file can contain commands from other sessions. Its location and retention limits come from the existing shell configuration, so editing history does not require replacing that configuration or choosing a new history path.

An open terminal can write an old command back after it has been deleted from disk. Saved-file editing therefore requires other shells using that file to exit first, followed by disconnecting the remaining shell from the file before editing. A harmless test entry makes the removal visible without exposing a sensitive command.

Steps to view and edit Zsh command history:

  1. Inspect the current shell's history file and retention limits.
    $ printf 'HISTFILE=%s\nHISTSIZE=%s\nSAVEHIST=%s\n' "$HISTFILE" "$HISTSIZE" "$SAVEHIST"

    HISTFILE identifies the actual saved file; ~/.zsh_history is only a common location. HISTSIZE limits events retained in memory, and SAVEHIST limits events saved to disk. A blank HISTFILE or zero SAVEHIST explains why history is not saved between sessions; zero HISTSIZE prevents retaining the active list. Saved-file editing requires a configured history file and positive limits.

  2. Display all events retained in the active history list.
    $ fc -l 1

    history is equivalent to fc -l and normally lists only the most recent 16 events. Starting at 1 requests the full retained list, including its oldest available event; commands already discarded by retention limits cannot be recovered this way.

  3. Run a harmless command to keep as a comparison entry.
    $ echo zsh-history-keep-me
    zsh-history-keep-me
  4. Run the harmless command that will be removed from history.
    $ echo zsh-history-remove-me
    zsh-history-remove-me
  5. Exit every other Zsh session that uses the same history file.
    $ exit

    An old in-memory list can restore deleted entries when its shell saves history. This includes shells in other tabs, windows, terminal multiplexers, or remote sessions using the same file. The remaining terminal stays open for the edit; exiting the others normally lets them save their pending commands first.

  6. Append the remaining shell's unsaved events to its configured history file.
    $ fc -AI

    -A appends, and -I limits writing to events not already saved. This preserves saved entries from other sessions instead of replacing the file with the current list through fc -W. Existing retention and duplicate-filtering options still apply. APPEND_HISTORY normally saves on exit; INC_APPEND_HISTORY appends as commands are entered; INC_APPEND_HISTORY_TIME writes after completion where possible. Cross-terminal imports belong to shared history.

  7. Store the active history path for the file edit.
    $ history_file=$HISTFILE
  8. Disable automatic history-file writes in the remaining shell.
    $ unset HISTFILE

    This affects only the current shell and leaves startup files unchanged. Its old in-memory entries remain available until it exits, but they will not be saved through HISTFILE. Custom history-saving plugins or exit hooks that write their own files need to be stopped before editing those files.

  9. Back up the saved history file before changing its contents.
    $ cp -ip -- "$history_file" "$history_file.before-edit"

    Deleting a record removes its saved command text. The backup preserves the original file, including any sensitive entries, and -i asks before overwriting an existing backup. The backup is a recovery copy, not an erased copy of a secret.

  10. Open the path stored in history_file in your text editor.

    The path is the HISTFILE value displayed earlier, even though HISTFILE is now unset. The file shows saved commands without the event numbers printed by fc -l.

  11. Delete only the saved record containing the exact command echo zsh-history-remove-me.
    echo zsh-history-remove-me

    With EXTENDED_HISTORY or shared history, the record begins with : timestamp:duration; before the command; that prefix belongs to the same record. Other command text and timestamp prefixes stay unchanged. A multiline command can occupy several physical lines, so removing a real multiline entry requires its complete record. history -d is not Zsh's deletion command; its -d flag displays timestamps. Editing through fc without -l can execute the edited command, so it is unsuitable for deleting a saved entry.

  12. Save the history file in the editor.

    The edited file retains the comparison entry and unrelated saved commands. The original contents remain in the backup if the wrong record was removed.

  13. Exit the shell whose history file is unset.
    $ exit
  14. Open a fresh Zsh terminal with your normal startup configuration.

    A fresh shell loads the edited history file without the old in-memory copy. Its history path and limits still come from the existing configuration.

  15. Check the test entries in the fresh shell's retained history.
    $ fc -l -m '*zsh-history-*' 1
       28  echo zsh-history-keep-me

    The quoted pattern selects both test names across the retained list. Only the comparison command should appear; a remaining echo zsh-history-remove-me entry means removal has not succeeded. Event numbers vary. The earlier full-list command also shows unrelated retained history.

Share this guide