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
- Open iTerm2 and navigate to iTerm2 → Install Shell Integration and Utilities
- Select your shell from the dropdown menu (usually Zsh on modern macOS)
- 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:
- Open a new iTerm2 window
- Type a command and press Enter
- You should see a faint line appear below each command prompt (this is the mark)
- Try Cmd+Shift+Up/Down to jump between command marks
- 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.
- SSH into your target host
- 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.
-
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.)
-
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:
- In any profile's Advanced settings, find "Automatic Profile Switching"
- 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:
- Verify shell integration is installed on the remote host (see Step 4)
- Check that the sourcing line is in the remote shell config:
cat ~/.zshrc | grep iterm2 - 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:
- Ensure
APPEND_HISTORYis set (Zsh) orhistappendis enabled (Bash) - Check that your history file has write permissions:
ls -la ~/.zsh_historyor~/.bash_history - Increase
HISTSIZEandSAVEHISTif you're hitting limits
Marks Not Appearing
Problem: You don't see faint lines below each prompt.
Solution:
- Verify the iTerm2 shell integration script is actually sourced:
echo $ITERM2_SHELL_INTEGRATION - Some shells or configurations may suppress the mark characters. Try resetting your shell config to include only the iTerm2 sourcing line and basic settings
- 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.