How to Set Up iTerm2 Shell Integration for SSH Command History Across Hosts

How to Set Up iTerm2 Shell Integration for SSH Command History Across Hosts

MacOS developers who frequently SSH into multiple servers face a recurring frustration: losing command history when switching between hosts, or having a massive jumbled history that mixes commands from production, staging, and local environments.

iTerm2's shell integration feature solves this by maintaining separate command history per hostname, tracking directories with frecency sorting, and integrating deeply with your shell to understand context. This guide walks you through enabling and configuring this powerful feature.

What Shell Integration Actually Does

Before diving into setup, understand what you're gaining:

  • Per-host command history - Your production SSH session keeps its own history separate from your local shell and staging environment
  • Frecency-based recent directories - iTerm2 tracks which directories you visit most frequently and most recently on each host
  • SCP click-to-download - Download remote files by clicking them in terminal output
  • Automatic marks - iTerm2 marks each prompt location, letting you navigate command-by-command with keyboard shortcuts
  • Drag-and-drop uploads - Drag files into your terminal to auto-generate upload commands

These features require shell integration to be installed on your local machine and, optionally, on remote hosts you SSH into.

Prerequisites

You'll need:

  • iTerm2 version 3.4 or later (check via iTerm2 → About iTerm2)
  • A supported shell: Bash 4.4+, Zsh, or Fish
  • For remote history: SSH access to target hosts (shell integration also works without remote installation, but with limited features)

Step 1: Enable Shell Integration in iTerm2

  1. Open iTerm2 and navigate to iTerm2 → Install Shell Integration and Utilities
  2. Select your shell from the dropdown menu (usually Zsh on modern macOS)
  3. Click Install and grant permission when prompted

iTerm2 will modify your shell configuration file (.zshrc, .bashrc, or .config/fish/config.fish depending on your shell) by adding this snippet:

test -e "${HOME}/.iterm2_shell_integration.zsh" && source "${HOME}/.iterm2_shell_integration.zsh"

Restart your terminal or run source ~/.zshrc to activate integration.

Step 2: Verify Local Shell Integration

After installation, verify integration is working:

  1. Open a new iTerm2 window
  2. Type a command and press Enter
  3. You should see a faint line appear below each command prompt (this is the mark)
  4. Try Cmd+Shift+Up/Down to jump between command marks
  5. Open iTerm2 → Shell Integration → Show Recent Directories — you should see a list of directories you've visited with frequency weights

If marks aren't visible, your shell integration didn't activate. Check that the sourcing line was added to your shell config file and restart the terminal.

Step 3: Configure Per-Host History

Now configure iTerm2 to maintain separate history for different SSH destinations. This is critical for developers managing multiple environments.

Local Machine Setup

Edit your shell configuration file to ensure history isolation:

For Zsh (~/.zshrc):

# Enable iTerm2 shell integration (if not already present)
test -e "${HOME}/.iterm2_shell_integration.zsh" && source "${HOME}/.iterm2_shell_integration.zsh"

# Increase history size for SSH connections
export HISTSIZE=100000
export SAVEHIST=100000

# Keep separate history per session when using shell integration
setopt APPEND_HISTORY
setopt INC_APPEND_HISTORY

For Bash (~/.bashrc):

# iTerm2 shell integration
test -e "${HOME}/.iterm2_shell_integration.bash" && source "${HOME}/.iterm2_shell_integration.bash"

# Increase history size
export HISTSIZE=100000
export HISTFILESIZE=100000

# Append history immediately after each command
shopt -s histappend

Reload your shell: exec zsh or exec bash

Step 4: Install Shell Integration on Remote Hosts (Optional but Recommended)

For full per-host history tracking, install shell integration on servers you frequently SSH into.

  1. SSH into your target host
  2. On that remote machine, download and install shell integration:
curl -L https://iterm2.com/shell_integration/install_shell_integration.sh | bash

Or, if you prefer to review the script before running it:

curl -L https://iterm2.com/shell_integration/install_shell_integration.sh -o /tmp/install.sh
cat /tmp/install.sh  # Review the contents
bash /tmp/install.sh

The installer will:

  • Download the shell integration script for your remote shell
  • Add the sourcing line to your remote shell configuration
  • Create .iterm2_shell_integration.[shell] in your home directory

Once installed on a remote host, disconnect and reconnect via SSH. You'll now see marks on the remote host, and iTerm2 will track your command history separately for that host.

Step 5: Configure Automatic Profile Switching by Hostname

Combine shell integration with iTerm2's profile switching to get visual context cues based on which host you're connected to.

  1. Create separate profiles for different environments:

    • iTerm2 → Preferences → Profiles
    • Click + to create profiles named "Production", "Staging", "Development"
    • In each profile, customize the background color (red for production, yellow for staging, etc.)
  2. Set up automatic switching:

    • Go to Preferences → Profiles → Default → Advanced
    • Find Semantic History section
    • Enable Triggers by clicking Edit
    • Add a trigger with pattern: (?<=Last login).* (or any hostname pattern)
    • Set action to Run Command with script:
echo "\033]50;SetProfile=Production\007" > /tmp/iterm2.profile

Alternatively, use iTerm2's built-in hostname-based profile switching:

  1. In any profile's Advanced settings, find "Automatic Profile Switching"
  2. Set rules like: hostname="prod.example.com" → use "Production" profile

Step 6: Leverage Recent Directories and Command History

Now that shell integration is fully configured:

Access Recent Directories

  • iTerm2 → Shell Integration → Show Recent Directories (or configure a keyboard shortcut)
  • Directories are ranked by frecency (frequency + recency)
  • This works independently per host, so your production server's frequent directories don't pollute your local suggestions

Jump Between Commands

  • Cmd+Shift+Up — Jump to previous command prompt
  • Cmd+Shift+Down — Jump to next command prompt
  • Works across all your sessions, even remote ones

Use Instant Replay

  • Cmd+Shift+E opens Instant Replay, letting you scrub backward through terminal history
  • Useful for catching errors that scrolled past or verifying command output

Common Configuration Issues

Shell Integration Not Loading on SSH

Problem: You SSH into a host, but marks and recent directories aren't appearing.

Solution:

  1. Verify shell integration is installed on the remote host (see Step 4)
  2. Check that the sourcing line is in the remote shell config: cat ~/.zshrc | grep iterm2
  3. Some servers restrict shell modifications. If you can't modify the remote shell config, iTerm2 will still track history locally, but with reduced functionality

Command History Not Persisting Across Sessions

Problem: You close a tab and lose command history.

Solution:

  1. Ensure APPEND_HISTORY is set (Zsh) or histappend is enabled (Bash)
  2. Check that your history file has write permissions: ls -la ~/.zsh_history or ~/.bash_history
  3. Increase HISTSIZE and SAVEHIST if you're hitting limits

Marks Not Appearing

Problem: You don't see faint lines below each prompt.

Solution:

  1. Verify the iTerm2 shell integration script is actually sourced: echo $ITERM2_SHELL_INTEGRATION
  2. Some shells or configurations may suppress the mark characters. Try resetting your shell config to include only the iTerm2 sourcing line and basic settings
  3. Ensure you're running iTerm2 version 3.4+ (older versions don't support marks)

Comparison: iTerm2 Shell Integration vs. tmux for Multi-Host Management

| Feature | iTerm2 Shell Integration | tmux | |---------|--------------------------|------| | Per-host command history | ✓ Automatic | Requires separate configs | | Frecency-based directories | ✓ Native | Not built-in | | Visual context switching | ✓ Auto profile switching | Manual | | SSH ease of setup | ✓ One-click install | Requires SSH config | | Cross-machine session sync | ✗ Local only | ✓ Via network attach | | Learning curve | Gentle | Moderate | | Works offline | ✓ | ✓ |

iTerm2 shell integration is superior for developers who SSH into multiple hosts occasionally. tmux wins if you need persistent sessions that survive disconnects or collaboration features.

Advanced: Python API for Custom History Tracking

For power users, iTerm2's Python API lets you build custom history tracking:

import iterm2
import os

async def main(connection):
    app = await iterm2.async_get_app(connection)
    session = app.current_terminal_window.current_tab.current_session
    
    # Log command to custom history file
    with open(os.path.expanduser('~/.iterm2_custom_history'), 'a') as f:
        f.write(f"{session.hostname}: {session.name}\n")

iterm2.run_until_complete(main)

Save this as a script and trigger it via iTerm2's trigger system to build custom analytics on your command patterns across hosts.

Conclusion

With shell integration properly configured, iTerm2 becomes a smarter terminal that understands your workflow across local and remote systems. Per-host command history and frecency-based directory navigation eliminate friction when managing multiple environments, while automatic profile switching provides instant visual context that prevents costly mistakes on production systems.

The setup takes 10 minutes but pays dividends every day you SSH into servers.