By default, Touch ID authentication for sudo doesn't work inside tmux sessions.
This is because tmux runs in a different bootstrap namespace and can't access the
Security framework's authentication context.
brew install pam-reattach
sudo tee /etc/pam.d/sudo_local <<'EOF'
# sudo_local: auth account password session
auth optional /opt/homebrew/lib/pam/pam_reattach.so ignore_ssh
auth sufficient pam_tid.so
EOF
No shell wrapper needed. No Python helper needed. Just open a new tmux pane and
sudo will prompt for your fingerprint.
pam_reattach.sore-attaches the per-session bootstrap namespace so Touch ID works in tmuxignore_sshflag detects$SSH_CONNECTION/$SSH_CLIENT/$SSH_TTYand makes the module a no-op over SSH, so it falls through to password authpam_tid.soenables Touch ID for sudo -- markedsufficientso it gracefully falls through to password if Touch ID is unavailable- Using
sudo_localinstead of editingsudodirectly means this survives macOS updates /etc/pam.d/sudoalready includessudo_localby default on modern macOS (Sonoma+)
| Context | What happens |
|---|---|
| Local terminal | Touch ID prompt |
| tmux (local) | Touch ID prompt (via pam_reattach) |
| SSH session | Password prompt (ignore_ssh skips reattach) |
| tmux over SSH | Password prompt (ignore_ssh skips reattach) |
| No Touch ID hardware | Password prompt (pam_tid fails, falls through) |
| pam_reattach not installed | Password prompt (optional, skipped by PAM) |
The Touch ID dialog only shows "Terminal" (or your app name) - it doesn't show which command is being authorized. Add this shell wrapper to see the user, parent process, and command before the Touch ID prompt appears.
# SUDO WRAPPER - Shows what's being run before Touch ID prompt
# Displays macOS notification + terminal output with user, parent process, and command
# Install terminal-notifier for faster notifications: brew install terminal-notifier
sudo() {
local parent_cmd=$(ps -o comm= -p $PPID 2>/dev/null)
local sudo_cmd="$*"
local notif_title="Touch ID: Authorize sudo"
local notif_subtitle="${parent_cmd:-shell} wants to run as root"
local notif_msg="Command: $sudo_cmd"
# macOS notification FIRST (before any output)
if command -v terminal-notifier &>/dev/null; then
terminal-notifier -title "$notif_title" -subtitle "$notif_subtitle" -message "$notif_msg" -timeout 5 &>/dev/null
else
osascript -e "display notification \"$notif_msg\" with title \"$notif_title\" subtitle \"$notif_subtitle\"" 2>/dev/null
sleep 0.5 # Give notification time to render
fi
# Terminal output
echo -e "\033[1;33m[sudo]\033[0m $notif_subtitle"
echo -e "\033[1;33m[sudo]\033[0m $notif_msg"
command sudo "$@"
}Terminal:
[sudo] zsh wants to run as root
[sudo] Command: rm -rf /tmp/junk
macOS Notification:
- Title: "Touch ID: Authorize sudo"
- Subtitle: "zsh wants to run as root" (or "claude", "node", etc.)
- Message: "Command: rm -rf /tmp/junk"
- Security awareness: Know exactly what you're authorizing before touching the sensor
- AI agent visibility: When tools like Claude Code or Cursor run
sudo, you'll seeParent: nodeorParent: claudeso you know it wasn't you - Audit trail: Terminal output shows the command history
For the macOS notification to appear, you need to allow notifications from Script Editor:
- Open System Settings → Notifications
- Scroll down to Script Editor
- Enable Allow Notifications
- Optionally set banner style to "Alerts" if you want them to persist until dismissed
If Script Editor doesn't appear in the list, run sudo once first - it will appear after osascript runs for the first time.
The built-in osascript has slight latency. For instant notifications, install terminal-notifier:
brew install terminal-notifierThe wrapper automatically uses it when available (no code changes needed).
If you don't want the popup, use this simpler version:
sudo() {
local parent_cmd=$(ps -o comm= -p $PPID 2>/dev/null)
echo -e "\033[1;33m[sudo]\033[0m ${parent_cmd:-shell} wants to run as root"
echo -e "\033[1;33m[sudo]\033[0m Command: $*"
command sudo "$@"
}- On Apple Silicon Macs, the library is at
/opt/homebrew/lib/pam/pam_reattach.so - On Intel Macs, it would be
/usr/local/lib/pam/pam_reattach.so pam_reattachis markedoptionalso sudo still works if the library is missing- Works in tmux, iTerm2, Terminal.app, Ghostty, and any other terminal emulator
- pam_reattach - the module that makes Touch ID work in tmux
- Apple sudo_local documentation - macOS Sonoma's persistent Touch ID sudo config