Part 1 of this series covered the foundation: Homebrew, a clean shell environment, and the package management habits that keep a developer Mac from becoming a liability. If you haven't read it, the short version is that Homebrew is already installed and your system is ready for what comes next. This part builds directly on that.
The terminal is where you spend more time than almost any other tool. Most developers accept the default experience, tweak a color scheme, and move on. That's a mistake. The terminal isn't just a window to type commands into. It's a workspace, and like any workspace, the way it's organized determines how fast you can think. iTerm2, configured properly, turns that workspace into something that actually keeps up with how a working developer moves through a day.
By the end of this article you'll have a fully operational command center. Not a prettier terminal. A structured environment with profiles, sensible key bindings, a font that renders correctly, and a scrollback buffer that doesn't eat your build logs.
Why iTerm2 Beats the Default macOS Terminal
The built-in Terminal.app is fine for running a one-off command. It's not fine for anything more demanding. There's no proper profile system, window splitting is clunky, and the integration story with tools like tmux is shallow. You can make it work, but you're constantly working around it instead of with it.
Better Profiles and Window Management
Profiles are the foundation of everything in this guide. A profile in iTerm2 is a named bundle of appearance settings, behavior rules, key bindings, and environment configuration. You can have one profile for local development, another for SSH sessions, another for running AI agents, and each one opens exactly the way you need it without touching the others. Terminal.app has nothing comparable.
Window splitting in iTerm2 is first-class. Horizontal and vertical splits, pane navigation with keyboard shortcuts, and the ability to broadcast input to multiple panes simultaneously. When you're running a dev server in one pane, watching logs in another, and running tests in a third, that's not a luxury. That's just how multi-context work actually goes.
Deeper tmux Integration
iTerm2 doesn't just run tmux inside a terminal window. It integrates with tmux natively via tmux -CC, which means tmux sessions are represented as actual iTerm2 tabs and windows rather than a multiplexed view inside a single pane. You get the persistence of tmux sessions with the full iTerm2 rendering engine on top. That distinction matters when you're reconnecting to a session after closing your laptop.
Hotkey Workflow That Stays Out of Your Way
The hotkey window is the single biggest productivity unlock iTerm2 offers. A dedicated terminal instance that appears over any application on a configurable keystroke and disappears just as fast. No Command+Tab, no Dock, no switching contexts. You press a key, you're in the terminal, you press it again, you're back where you were. It sounds small. After a week of using it, you won't understand how you worked without it.
Set your expectations clearly: by the end of this article, you'll have a terminal environment with real structure behind it. The visual polish is a side effect, not the goal.
Install iTerm2 with Homebrew
Part 1 established Homebrew as the package manager for this entire series. If you're jumping in here without that foundation, install Homebrew first by following the instructions at brew.sh, then come back. Everything from here assumes brew is available on your path.
Installing iTerm2 is a single command:
brew install --cask iterm2Why Homebrew over the DMG?
The DMG download from iterm2.com works, but it puts you outside the Homebrew ecosystem. With the cask install, brew upgrade --cask iterm2 handles updates, brew uninstall --cask iterm2 handles removal, and your install is reproducible from a Brewfile alongside every other tool on your system. That consistency compounds over time.
On first launch, iTerm2 will ask whether you want it to check for updates automatically. You can decline since Homebrew handles that. Click through the accessibility permission prompts if they appear. The current stable release is 3.5.x. You can verify your installed version at any time by running brew info --cask iterm2 or checking iTerm2 → About iTerm2 from the menu bar.
Understanding iTerm2 Profiles
A profile in iTerm2 is not a theme. It's not just colors and a font. It's a complete named configuration bundle that controls appearance, terminal behavior, working directory, environment variables, key bindings, and more. Every window and tab you open is backed by exactly one profile. That's the mental model to hold onto.
Profiles vs Windows vs Tabs: Clearing Up the Confusion
The three-level hierarchy works like this. A profile is the configuration template. A window is a physical iTerm2 window on screen, which can contain one or more tabs. A tab is an individual terminal session inside a window, each running against a profile. You can open the same profile in multiple tabs, or open different profiles in different tabs inside the same window. They're independent layers, not nested settings.
The Default Profile and Why You Should Leave It Alone
iTerm2 ships with a Default profile. The temptation is to edit it directly. Don't. The Default profile is the fallback for anything that doesn't have an explicit profile assigned. If you modify it and something breaks, you've broken the fallback for your entire setup. Instead, duplicate it immediately: Preferences → Profiles → select Default → click the gear icon → Duplicate Profile. Rename the duplicate to something like "Base" or your own name and do all your customization there. Keep Default intact.
Project-Specific Profiles
The primary daily-driver pattern is one profile per project or context. A profile for your main application's backend, another for its frontend, another for infrastructure work. Each one can open in a specific directory, set environment variables, use a distinct color scheme so you know at a glance which context you're in, and run a startup command if needed. This isn't over-engineering. It's the difference between a terminal that remembers your context and one that makes you re-establish it every session.
Dynamic Profiles
"Dynamic profiles are the version-controlled, shareable, dotfile-friendly alternative to clicking through the GUI."
Dynamic profiles are profiles defined as JSON files stored at ~/Library/Application Support/iTerm2/DynamicProfiles/. iTerm2 reads that directory at launch and any time files change. The practical upside is significant: you can commit your profiles to a dotfiles repository, share them across machines, and diff changes over time. A dynamic profile file is just a JSON array of profile objects, each with the same keys you'd set in the GUI. They appear in the Profiles list alongside manually created ones, and they behave identically once loaded.
Launcher Profiles
A launcher profile is a profile configured specifically to open a terminal pre-wired for one task. Not a general-purpose terminal you navigate from. A terminal that lands exactly where you need it. Practical examples include a profile that opens in your main project directory with the virtual environment activated, a profile that initiates an SSH connection to a specific host immediately on open, a profile configured for running an AI agent with a wider column width and a distinct background color, and environment-specific profiles that set AWS_PROFILE or KUBECONFIG before your shell prompt even appears. The pattern scales as your project count grows.
Enable Natural Text Editing
Out of the box, iTerm2 doesn't behave the way the rest of macOS does when you use modifier keys in the terminal. Option+Arrow moves by word in every other macOS text field. In the default iTerm2 configuration, it sends escape sequences that most shells don't interpret the way you'd expect. Command+Arrow is similarly broken. This is one of the first things to fix because it affects every command you type from this point forward.
The fix is a single preset. Navigate to: iTerm2 → Settings → Profiles → Keys → Presets → Natural Text Editing.
Applying this preset configures the following key bindings:
- Option+Left: Move the cursor one word to the left.
- Option+Right: Move the cursor one word to the right.
- Command+Left: Move the cursor to the beginning of the line.
- Command+Right: Move the cursor to the end of the line.
- Option+Delete: Delete the word immediately to the left of the cursor.
This preset overwrites existing key mappings
When you apply Natural Text Editing, it replaces whatever key bindings were previously set in that profile's Keys section. If you've already configured custom bindings in this profile, review the Keys tab before and after applying the preset so you know what changed. The preset is correct for most workflows, but it's worth confirming nothing critical was overwritten.
Apply this to every profile you create. If you're using dynamic profiles, the relevant JSON key is "Key Mappings" and you can copy the mapping block from an exported profile. The muscle memory you've built across every other macOS application transfers directly once this is in place, and you'll stop reaching for the mouse to reposition your cursor mid-command.
Enable Unlimited Scrollback
iTerm2's default scrollback buffer holds 1,000 lines. That number sounds reasonable until you're watching a Gradle build, a Docker image pull, or a long AI agent session scroll past it. The output you need is gone, replaced by whatever the terminal decided to keep. This is not a theoretical problem. It happens regularly in real development work.
The fix is straightforward: iTerm2 → Settings → Profiles → Terminal → check Unlimited scrollback.
The honest tradeoff is memory. An unlimited scrollback buffer will grow as long as your session runs. In practice, for most development sessions, the memory footprint stays well under a few hundred megabytes even after hours of output. If you're running on a machine with constrained RAM or you're keeping dozens of sessions open simultaneously, a large fixed limit like 100,000 lines is a reasonable middle ground instead of truly unlimited.
Unlimited scrollback pairs well with iTerm2's built-in search, accessible with Cmd+F, which lets you search the entire buffer including everything above the visible window. For long outputs, that search is often faster than piping to grep after the fact.
One important note for tmux users: tmux maintains its own scrollback buffer separately from iTerm2's. The iTerm2 setting controls what the iTerm2 renderer holds. Inside a tmux session, scrollback is governed by the history-limit setting in your .tmux.conf. Both need to be configured to avoid gaps.
Install and Configure MesloLGS Nerd Font
Why Nerd Fonts Matter for the Terminal
A standard monospace font renders characters. A Nerd Font renders characters plus several thousand additional glyphs: Git branch symbols, file type icons, status indicators, arrow separators, and the full range of symbols that modern prompt frameworks use to communicate information visually. Without a Nerd Font installed and set as your terminal font, those glyphs render as empty boxes or question marks. The prompt looks broken because it is broken, at least from a rendering standpoint.
Installing via Homebrew
MesloLGS NF is the recommended choice for this series. It was designed specifically for Powerline and Starship prompt compatibility, which matters because Starship is coming in a later part. Install it with:
brew install --cask font-meslo-lg-nerd-fontSetting the Font in iTerm2
Navigate to: iTerm2 → Settings → Profiles → Text → Font, then select MesloLGS NF from the font picker. Set the size to whatever your eyes prefer. 13pt or 14pt is a reasonable starting point for most displays.
The common mistake is setting the font in the wrong place. iTerm2 has a global appearance section, but profile-level font settings override it. If you configure MesloLGS NF globally but your profiles still specify a different font, the profiles win. Set the font explicitly in every profile you use. If you're using dynamic profiles, the JSON key is "Normal Font" with a value like "MesloLGSNFM-Regular 13".
Verifying Glyph Rendering
Once the font is set, run this test command in your terminal:
echo " ✓"Correct output shows a folder icon, a home icon, a Git branch symbol, and a checkmark, all rendering as distinct recognizable glyphs with proper spacing. Broken output shows empty rectangles, question marks, or missing characters where those glyphs should be. If you see broken output, the most likely cause is that the active profile is still using a different font. Confirm the font setting in the profile backing your current tab and reopen a new tab to pick up the change.
This font is also a hard requirement for Starship prompt, which handles the visual layer of your shell environment. That's covered in Part 3.
Part 3 covers Starship prompt: what it is, why it replaces both Oh My Zsh and plain PS1 configurations for most developers, and how to configure it to surface the information you actually need without slowing your shell startup down.
Configure the iTerm2 Status Bar
The status bar is a persistent information strip that renders either above or below the terminal buffer, depending on your preference. It doesn't scroll with your output. It stays anchored while you work, giving you a live read on context that would otherwise require separate commands or window-switching.
Enabling the Status Bar
Navigate to iTerm2 → Settings → Profiles → Session → Status Bar. Check the Enable Status Bar checkbox, then click Configure Status Bar to open the component editor. You'll see a drag-and-drop canvas at the top and a library of available components below it.
Recommended Components and What Each One Shows
Drag any component from the library onto the canvas to activate it. These six are worth adding first:
- Current Directory: Shows your working directory so you always know where you are, even after a long scroll.
- Git Branch: Displays the active branch name when you're inside a repository.
- CPU Usage: A live graph or percentage readout that catches runaway processes without leaving the terminal.
- Memory Usage: Shows current RAM pressure at a glance, useful when running local containers or build pipelines.
- Hostname: Critical on the Remote Host profile so you never forget which machine you're looking at.
- Battery: Practical on a laptop, pointless on a desktop. Skip it if you're always plugged in.
Once components are on the canvas, drag them left or right to reorder. Tighter arrangements read better at smaller font sizes.
The status bar is configured per profile, which matters. For the hotkey window profile, keep it empty or limit it to current directory only. A minimal hotkey window loads faster and feels lighter. For the main workspace profile, use the full six-component layout. The color and font size of status bar text are adjustable under the Advanced button in the same panel, though the defaults are readable enough to leave alone until everything else is working.
Create a Hotkey Window
What a Hotkey Window Is and Why You Want One
A hotkey window is a terminal that appears and disappears on a single keypress from any application. No dock click. No Command+Tab cycling. No app switching at all. You press the shortcut, the terminal slides down from the top of the screen or up from the bottom, you run a command, you press the shortcut again, and you're back in whatever you were doing. The application you were in never lost focus in the permanent sense. The hotkey window is an overlay, not a context switch.
The practical benefit compounds fast. Checking a git status, tailing a log file, running a quick curl, looking up a port number: all of these take four seconds with a hotkey window and thirty seconds without one. Over a full workday, that adds up.
Recommended Shortcuts and What to Avoid
Navigate to iTerm2 → Settings → Keys → Create a Dedicated Hotkey Window. You'll be prompted to record a keyboard shortcut.
Control+Backtick is the best primary choice. It sits in a comfortable position, it's fast to hit one-handed, and macOS doesn't claim it by default. Control+Option+Space works well as an alternative for people who prefer a three-key chord that feels more deliberate.
Several shortcuts look tempting and will cause immediate problems:
- Command+Space: Spotlight. macOS owns this. You'll fight it every time.
- Command+Backtick: Window cycling within the current app. Reassigning it breaks expected behavior everywhere.
- Control+Space: macOS input source switching. It may appear unbound on your machine, but it reactivates when you add a second keyboard input method. Don't rely on it.
Check Before You Assign
Before committing to any hotkey, open System Settings → Keyboard → Keyboard Shortcuts and search for the key combination. macOS has more reserved shortcuts than most people realize, and a conflict won't always produce an obvious error. It'll just silently win.
Configuring the Hotkey Window Profile
When you create the hotkey window, iTerm2 lets you assign a dedicated profile to it. Create a profile named something like HK Scratchpad and assign it here. Keep this profile minimal: no status bar, a transparent or near-transparent background at around 85% opacity, and a font size two points smaller than your main workspace profile. The hotkey window should feel lightweight and temporary because that's exactly what it is.
Recommended Profile Layout for a Developer Machine
The Six-Profile System
A deliberate profile structure makes iTerm2 predictable. When every session type has a named home, you stop making ad-hoc decisions about where to open things. Here are six profiles worth creating:
- 00 Main Workspace: Your primary daily driver. Full status bar, your main color scheme, default working directory set to your home folder or project root.
- 01 Local Development: Tuned for running local servers and build tools. Consider a slightly warmer background color to distinguish it visually from the main workspace.
- 02 Remote Host: No local working directory set. Hostname component prominently placed in the status bar. A distinct color scheme so you never confuse a remote session for a local one.
- 03 Logs: Wide terminal, smaller font size, high scrollback. Designed for reading log output, not interactive work.
- 04 Agent Runner: For running AI agents, background jobs, or long-running scripts. Muted color scheme so it doesn't demand attention when it's just churning.
- 05 Scratch Terminal: No persistence expectations. Use it, close it, forget it. This is where you run one-off commands you don't care about keeping.
Naming Conventions and Why They Matter
iTerm2 sorts profiles alphabetically in the UI. Without a numeric prefix, a profile named "Remote Host" sorts after "Main Workspace" but before "Scratch Terminal," and the order shifts whenever you add something new. Two-digit numeric prefixes lock the sort order permanently. 00 through 05 always appear in that sequence regardless of what you add later.
To create each profile without rebuilding settings from scratch, select your Default profile in the profile list, click the gear icon at the bottom, and choose Duplicate Profile. Rename the duplicate, then adjust only the settings that differ. Working directory, color scheme, and status bar components are the three things that actually change between most profiles. Everything else inherits cleanly from the clone.
This layout is a starting point. If you don't run agents locally, skip 04. If you live in remote sessions, add a second remote profile for a second host. The numbering system accommodates expansion without breaking the sort order.
Common Mistakes and How to Avoid Them
Five Things That Catch People Off Guard
Editing the Default profile directly. The Default profile is iTerm2's fallback. Any profile that doesn't explicitly override a setting inherits from it. If you change the font in Default, every profile that hasn't set its own font changes with it. If you change the color scheme, same result. Edit Default only when you want a global baseline change. For everything else, clone it first.
Setting the Nerd Font at the application level but not in the profile. iTerm2 has both an application-level font setting and a per-profile font setting. The profile-level setting wins. If you installed your Nerd Font and selected it in the general preferences but your glyphs still show as boxes, open the profile's Text tab and set the font there explicitly. That's the setting that actually controls what renders.
Conflict Check Is Not Optional
If your hotkey stops working after a macOS update, the first place to look is System Settings → Keyboard → Keyboard Shortcuts. Apple occasionally claims new shortcuts in OS updates. Check this any time a hotkey silently stops responding.
Assigning a hotkey that macOS already owns. Covered in the hotkey section, but worth repeating here because it's the most common source of "iTerm2 is broken" reports that aren't actually iTerm2 problems at all.
Confusing iTerm2 profiles with shell configuration. Profiles control the terminal emulator: colors, fonts, working directory, window behavior. They don't touch the shell. Your zsh configuration lives in .zshrc and runs the same way regardless of which profile launched the session. If your aliases aren't working, the profile isn't the problem.
Skipping the Natural Text Editing preset. Option+Arrow for word-jumping and Option+Delete for word-deletion are muscle memory for most developers. Without the Natural Text Editing key preset enabled under Settings → Profiles → Keys → Load Preset, those shortcuts produce escape sequences instead of movement. Enable it once and stop wondering why your keyboard feels wrong.
Part 2 Completion Checklist
Every item in Part 3 assumes this checklist is complete. Starship's configuration references fonts, profiles, and terminal behavior that were set up here. If something in Part 3 doesn't render correctly, the answer is almost always an unchecked item below.
What Comes Next: The Shell Prompt
This part covered a lot of ground. iTerm2 is installed, your profiles are structured and named, the Nerd Font is in place, the hotkey window is wired to a shortcut that actually works, and the status bar is showing useful information without cluttering the workspace. The terminal emulator is configured.
Here's what's still missing. Open a new iTerm2 window right now and look at the prompt. It's the plain default zsh prompt: a percent sign, maybe a hostname, nothing else. The terminal looks good. The prompt inside it doesn't match.
Part 3 fixes that. It walks through installing and configuring Starship, a cross-shell prompt that displays Git branch status, language runtime versions, the exit code of the last command, and execution time for anything that ran longer than a few seconds. All of it rendered with the Nerd Font icons you installed in this part.
Every part of this series builds on the one before it. The font you installed here is the reason the prompt in Part 3 looks the way it does.