Skip to content

Zsh History Actor Tagging

Automatically tag every command written to ~/.zsh_history with the actor that executed it — franz, claude, or codex.

Tags are written as shell comments (#@actor), so replaying history remains safe.

How It Works

The actor is detected using environment inspection:

CLAUDECODE unset                    →  franz
CLAUDECODE=1, grandparent is codex  →  codex
CLAUDECODE=1, otherwise             →  claude

Claude Code sets CLAUDECODE=1 in subprocesses. Codex CLI does the same — a two-level process tree walk disambiguates them.

Zsh's zshaddhistory hook intercepts commands before they're written, appends #@actor, then writes manually via print -sr and suppresses the default write.

Example history entries:

: 1745628000:0;git status #@franz
: 1745628042:0;ls -la /tmp #@claude
: 1745628103:0;npm run build #@codex

Setup

Add to ~/.zshrc:

~/.zshrc
_detect_command_actor() {
  if [[ -n "$CLAUDECODE" ]]; then
    local grandparent=$(ps -o comm= -p $(ps -o ppid= -p $(ps -o ppid= -p $$)) 2>/dev/null | xargs)
    if [[ "$grandparent" == *codex* ]]; then
      echo "codex"
    else
      echo "claude"
    fi
  else
    echo "franz"
  fi
}

zshaddhistory() {
  local cmd="${1%%$'\n'}"
  local actor=$(_detect_command_actor)
  print -sr -- "${cmd} #@${actor}"
  return 1
}

hh() {
  local n=${1:-100}
  fc -li -${n} | sed -E 's/ #@(claude|codex|franz)/  [\1]/'
}

Ensure these history settings are present:

HISTFILE="$HOME/.zsh_history"
HISTSIZE=100000
SAVEHIST=100000
setopt EXTENDED_HISTORY
setopt INC_APPEND_HISTORY
setopt SHARE_HISTORY
setopt HIST_IGNORE_SPACE

Warning

EXTENDED_HISTORY must be enabled or timestamps will break.

Usage

hh        # last 100 commands
hh 500    # last 500 commands

hh 1000 | grep '\[claude\]'
hh 1000 | grep '\[codex\]'
hh 1000 | grep '\[franz\]'

Sample output:

  891  2026-04-26 02:18  cd ~/projects/api  [franz]
  892  2026-04-26 02:19  git status  [claude]
  893  2026-04-26 02:19  npm install  [claude]
  894  2026-04-26 02:21  git diff HEAD  [franz]
  895  2026-04-26 02:22  codex exec "refactor auth.ts"  [codex]

Note

Existing history is not retroactively tagged.

Limitations

  • If Claude stops setting CLAUDECODE, all commands default to franz
  • If Codex runs through a wrapper, detection may misclassify as claude
  • Deep process trees may require adjusting traversal depth