Skip to content

cognito

 3 min A tiny shell private mode that stops history, makes up-arrow forget, and hides its own switches.
Published

Mar 28, 2018

For one sensitive command, usually an exported password or another temporary value, a leading space was enough to omit it from history. If the work needed two or three related commands, or the commands after the export also needed to stay private, repeating that convention became awkward.

My shell has a private mode. incognito turns history off, cognito turns it back on, and neither command appears in the record afterward. It keeps a useful history while I work, then lets me discard that entire session. The helpers began in Bash; the zsh translation uses its fc stack machinery:

incognito () { cognito off; }
cognito () {
  case ${1:-on} in
    (on)  [[ -z $HISTFILE ]] && fc -WIP && HISTFILE="$HISTFILE__" && unset HISTFILE__;;
    (off) [[ -z $HISTFILE__ ]] && HISTFILE__="$HISTFILE" && fc -WIp && unset HISTFILE;;
  esac
}

The obvious half: incognito stashes HISTFILE into HISTFILE__ and unsets it, so nothing new reaches that history file; cognito restores it. The bash twin in the same dotfiles does exactly that and nothing more.

The half that needs zsh is fc -WIp. Unsetting HISTFILE stops writes, but the session history still lives in memory—up-arrow would replay the private commands for as long as the shell ran. fc -W writes the history file, -I limits the write to events since the last one, and -p pushes the current history list onto a stack and starts a fresh, empty one. So incognito flushes the real history and swaps in a throwaway list; every private command accumulates there. cognito runs the mirror image, fc -WIP: -P pops the stack, and up-arrow behaves as if the private session never happened.

The guards make both directions idempotent. [[ -z $HISTFILE__ ]] means a second incognito cannot clobber the stash with an empty value, and [[ -z $HISTFILE ]] means cognito is a no-op unless private mode is on.

The detail I keep: the switches hide themselves. The history configuration pre-seeds both shells’ ignore lists with the toggle names, with and without a trailing space:

HISTIGNORE='[bf]g:[bf]g :exit:exit :cognito:cognito :incognito:incognito '
HISTORY_IGNORE='([bf]g|[bf]g |exit|exit |cognito|cognito |incognito|incognito )'

So the record shows no mode switch at all—no incognito line bracketing a conspicuous gap.

Gotchas: bash gets the degraded version, where private commands stay recallable in-session until the shell exits. And private mode only governs the shell’s own history; a program that keeps its own log keeps its own log. The same dotfiles add one more layer for the shells themselves: ~/.zsh_history and ~/.bash_history are tracked symlinks to /dev/null, so anything that ignores HISTFILE and writes the default path writes to the bit bucket.