07.10.2026 9 min read

iTerm2 for Agentic Development: A Workspace That Survives a Restart

Many of us now write code with agents. There are editors like Cursor and plenty of orchestration tools, but for me the most useful harness is still the terminal: Claude Code in one tab, Codex in another, a shell beside each.

Orchestration platforms have their place. Once an agent is designed and tested and its loop is verified, running it on a platform is no problem. But in the research and discovery phase, while you are still validating hypotheses, I suppose you use the raw CLI too.

That works until the machine reboots. After a Mac or PC restart every tab is gone, and bringing them back is hell: open each tab, find the folder, start Claude or Codex again, resume the right conversation, rename everything.

I went looking for a way out and found iTerm2. It has what is needed, but not out of the box, and it took some configuration and a few wrong turns to get there. This is that journey and the setup I ended with: one profile per agent and a saved window arrangement. Each start now brings back the same tabs, names, groups and split panes, and every agent resumes its last conversation.

What you get

  • One tab per agent, named after its project and grouped by product.
  • A status on every tab: working, waiting for you, or idle.
  • A plain terminal pane next to each agent, opened in the same folder.
  • The whole layout back after every restart, with each agent resuming where it stopped.

Screenshot of an iTerm2 window: two tab groups, agent tabs showing working, idle and waiting status, and a Codex agent pane beside a shell pane

My workspace in iTerm2: two tab groups, a status under each tab, and an agent pane beside a plain shell. Project names, paths, the host name and a login URL are replaced with placeholders.

What you need

  • iTerm2 3.7 or later, which requires macOS 13 or later. Version 3.7 added the Claude Code integration, session status and tab groups.
  • Claude Code, Codex CLI, or both, installed and signed in.
  • One folder per agent. claude --continue resumes the most recent conversation in the current folder, so two agents in one folder would resume the same conversation. Git worktrees work well for parallel agents on one repository.

Step 1: See every agent's status

Choose iTerm2 > Install Claude Code Integration. It lists what it will change before you confirm. The main change is a set of hooks in ~/.claude/settings.json that report each Claude session's state to iTerm2.

Then turn on the views you want:

  • Session Status tool. View > Toggle Toolbelt, then View > Toolbelt > Session Status. It lists every session in the window, and sessions waiting for you sort to the top.
  • Cockpit. Window > Cockpit (⌥⇧⌘C) is a floating panel with the same list across all windows.
  • Notify on Status Change. Window > Notify on Status Change (⇧⌘X) alerts you the next time a session in the window changes state. It is a one-shot alarm: it fires once, switches itself off, and is not saved with the profile or the arrangement.

Example status views: the Cockpit panel grouped by status, the Session Status tool, and a status-change alert with a Reveal button

Illustration of the three status views. The real panels differ in detail.

The built-in integration covers Claude Code only. Session status is open to other tools: any program can report a status through a control sequence or the it2 command. A community plugin, iterm2-status, does this for Codex and is in public beta.

Codex status with the iterm2-status plugin

The plugin adds Codex sessions to the same Session Status list, with working, waiting and idle states. It needs iTerm2 3.7 or later, Codex CLI 0.153.4 or later, Python 3.9 or later, and the Python API switched on under iTerm2 > Settings > General > Magic.

mkdir -p ~/plugins
git clone https://github.com/treyreynolds/iterm2-status.git ~/plugins/iterm2-status
cd ~/plugins/iterm2-status
python3 install.py --dry-run
python3 install.py
python3 install.py doctor --live
  1. Run the dry run first. It previews what the installer will change: a personal Codex plugin entry, the status hooks, and a launcher profile for iTerm2.
  2. After installing, start a new Codex session, type /hooks, and review and trust the plugin's hooks. Sessions that were already running do not report status.
  3. Run a short task. The Codex row should move from idle to working and back.

According to its README, the hooks only report status: they never approve or block agent actions, and nothing is sent off the machine. python3 install.py uninstall removes it. It is an independent project in its first public beta, so read the hooks before you trust them.

Step 2: One profile per agent

A profile holds the three things a tab needs: its name, its folder, and the command that resumes the agent. Dynamic profiles keep all of them in one JSON file, which iTerm2 reloads whenever it changes.

Create ~/Library/Application Support/iTerm2/DynamicProfiles/agents.json. This example has a Claude Code agent, a Codex agent and a plain shell:

{
  "Profiles": [
    {
      "Name": "Shop API",
      "Guid": "agent-shop-api",
      "Tags": ["Shop"],
      "Custom Directory": "Yes",
      "Working Directory": "/Users/you/work/shop-api",
      "Initial Text": "claude --continue",
      "Allow Title Setting": false,
      "Title Components": 1,
      "Use Custom Tab Title": true,
      "Custom Tab Title": "Shop API",
      "Badge Text": "Shop API"
    },
    {
      "Name": "Docs Site",
      "Guid": "agent-docs-site",
      "Tags": ["Docs"],
      "Custom Directory": "Yes",
      "Working Directory": "/Users/you/work/docs-site",
      "Initial Text": "codex resume --last",
      "Allow Title Setting": false,
      "Title Components": 1,
      "Use Custom Tab Title": true,
      "Custom Tab Title": "Docs Site",
      "Badge Text": "Docs Site"
    },
    {
      "Name": "Shop API shell",
      "Guid": "shell-shop-api",
      "Tags": ["Shop"],
      "Custom Directory": "Yes",
      "Working Directory": "/Users/you/work/shop-api",
      "Allow Title Setting": false,
      "Title Components": 1,
      "Badge Text": "Shop API shell"
    }
  ]
}
KeyWhat it does
GuidAny unique text. iTerm2 uses it to track the profile.
Custom Directory and Working DirectoryOpen the tab in that folder.
Initial TextTyped into the tab, followed by Enter, when the session starts.
Allow Title SettingSet to false, it stops programs from renaming the tab.
Title Components1 shows the session name only.
Use Custom Tab Title and Custom Tab TitleSet the tab's title when the profile opens in a new tab.

The shell profile has no command. It is for the plain terminal pane beside an agent.

I also give every profile a badge (Badge Text) and keep the session name equal to the profile name. With many tabs and constant context switching, those hints matter. The badge is drawn in large type in the corner of the pane and stays visible when the pane is not focused, so I am far less likely to type a task into the wrong Claude session, which is an annoying mistake to make.

Illustration of two panes, each with its profile name as a large red badge in the top-right corner

Illustration of badges in iTerm2's default style: bold red type in the top-right corner of each pane. Not a screenshot.

The session name comes from the profile's Name. On Claude tabs iTerm2 renames it to "Chat" unless you clear the Name of the main session in the Claude Code workgroup, under Settings > Arrangements > Workgroups.

Every file in that folder must be valid, or iTerm2 loads none of them. Write the file with a code editor, because a rich-text editor can replace straight quotes with curly ones.

Step 3: Build the layout

  1. Open each agent from the Profiles menu. Each tab opens in its folder, takes its name and resumes the agent.
  2. Right-click a tab and choose Add Tab to Group. Name the group, then drag the related tabs into it.
  3. For a terminal next to an agent, choose Shell > Split Vertically… (the item with the dots) and pick the matching shell profile.

The plain split shortcut (⌘D) copies the tab's profile, command included, so it would start a second agent in the new pane.

Step 4: Save it and open it at startup

  1. Choose Window > Save Window Arrangement and give it a name.
  2. In Settings > Arrangements, select it and click Set Default.
  3. In Settings > General > Startup, choose Open Default Window Arrangement.

The arrangement stores windows, tabs, tab titles, tab groups and split panes. On restore, each tab reads its profile again, so later edits to agents.json apply without saving the arrangement again. A change to the layout itself, such as a new tab, split or tab name, needs a new save under the same name.

What happens when iTerm2 starts: the default arrangement opens, each tab loads its profile, opens its folder, types its command, and the agent resumes

A reboot still ends every running process, and no terminal can prevent that. What comes back is the layout, and each profile's command restarts its agent in its last conversation.

Optional: a first prompt, Remote Control and notifications

A first prompt. Both CLIs take a prompt on the command line, so Initial Text can hand the agent its first instruction, for example codex resume --last 'Summarize where we stopped and wait.' Claude Code documents the same form after --resume; check that --continue accepts it on your version. A prompt that asks for a summary and waits is safer than "continue", which starts every agent working the moment iTerm2 opens.

Remote Control. In Claude Code, run /config and set Enable Remote Control for all sessions, or put "remoteControlAtStartup": true in ~/.claude/settings.json. Each session can then be continued from claude.ai/code or the Claude mobile app. A conversation resumed with --continue reconnects to the Remote Control session it had before.

Permanent notifications. Notify on Status Change cannot be switched on from a profile, but desktop notifications can. Claude Code sends one when it finishes a task or pauses for a permission prompt while you appear to be away. iTerm2 forwards it to macOS when the agent's profile has these two keys:

"BM Growl": true,
"Send Terminal Generated Alerts": true

BM Growl is the internal name of the Notification Center Alerts checkbox in Settings > Profiles > Terminal. The second key is Send escape sequence-generated alerts under Filter Alerts. iTerm2 also needs notification permission in macOS System Settings.

Gotchas

These cost me the most time. Each one has a short fix.

SymptomCauseFix
Sessions do not come back after a restartThe default startup option relies on macOS saving window state, which did not happen reliably for meOpen a default window arrangement at startup instead
A tab shows "Chat (claude)" instead of its nameWhen claude starts, the Claude Code workgroup renames the session to "Chat"Set the tab title: Window > Edit Tab Title, or Custom Tab Title in the profile. It sits on top of the session name
A name set in Edit Session > Session Name is lostSession Name is the field the workgroup overwritesUse the tab title, or clear the main session's Name in the Claude Code workgroup
A split pane starts a second agent⌘D copies the tab's profile, command includedSplit with Shell > Split Vertically… and a shell profile
iTerm2 opens one plain windowStarting iTerm2 by opening a folder or file with it skips the startup arrangementStart it from the Dock or Spotlight
New profiles do not appearOne invalid file in DynamicProfiles stops all of them from loadingCheck the file: plutil -p agents.json prints it only if it parses

Conclusion

A restart used to cost me the whole workspace. Now iTerm2 opens, the tabs come back with their names and groups, and every agent picks up its last conversation. I no longer feel sad when my Mac needs a restart.

For this way of working I keep a few short rules:

  1. One agent, one profile, one folder. Two agents in one folder resume the same conversation.
  2. Label every tab three ways. Tab title, session name and badge: the hints stop you typing a task into the wrong session.
  3. Split with a shell profile. Never with ⌘D, which starts a second agent.
  4. Save the arrangement after every layout change. iTerm2 opens the last saved version, not the last one you saw.
  5. Keep every profile in one file. agents.json is the only place that says what runs where.
  6. Write start prompts you would run unattended. They fire every time iTerm2 opens.
  7. Let the status and notifications call you. Do not walk the tabs to see who is waiting.

Here is the shape of the agents.json I ended with, with every attribute I use. The names and paths are examples: one Claude Code agent, one Codex agent and one shell.

{
  "Profiles": [
    {
      "Name": "Shop API",
      "Guid": "agent-shop-api",
      "Tags": ["Shop"],
      "Custom Directory": "Yes",
      "Working Directory": "/Users/you/work/shop-api",
      "Initial Text": "claude --continue 'Continue where you left off.'",
      "Allow Title Setting": false,
      "Title Components": 1,
      "Use Custom Tab Title": true,
      "Custom Tab Title": "Shop API",
      "Badge Text": "Shop API",
      "BM Growl": true,
      "Send Terminal Generated Alerts": true
    },
    {
      "Name": "Docs Site",
      "Guid": "agent-docs-site",
      "Tags": ["Docs"],
      "Custom Directory": "Yes",
      "Working Directory": "/Users/you/work/docs-site",
      "Initial Text": "codex resume --last 'Continue where you left off.'",
      "Allow Title Setting": false,
      "Title Components": 1,
      "Use Custom Tab Title": true,
      "Custom Tab Title": "Docs Site",
      "Badge Text": "Docs Site",
      "BM Growl": true,
      "Send Terminal Generated Alerts": true
    },
    {
      "Name": "Shop API shell",
      "Guid": "shell-shop-api",
      "Tags": ["Shop"],
      "Custom Directory": "Yes",
      "Working Directory": "/Users/you/work/shop-api",
      "Allow Title Setting": false,
      "Title Components": 1,
      "Badge Text": "Shop API shell"
    }
  ]
}
AttributeWhy I set it
Name, Guid, TagsThe profile's name, a unique id, and a tag for grouping and searching profiles.
Custom Directory, Working DirectoryThe tab opens in the agent's folder.
Initial TextThe resume command and its first prompt, typed when the tab opens.
Allow Title Setting, Title ComponentsPrograms cannot rename the tab, and the title shows the session name only.
Use Custom Tab Title, Custom Tab TitleThe tab gets its name when the profile opens.
Badge TextThe large label in the corner of the pane.
BM Growl, Send Terminal Generated AlertsDesktop notifications when the agent needs me.

Sources

DP
Written by
Denis Panaskin

Featured Articles

iTerm2 for Agentic Development: A Workspace That Survives a Restart

October 07, 2026

How to set up iTerm2 for Claude Code and Codex: one profile per agent, a status on every tab, and a saved window arrangement that brings back every tab, group and split pane after a restart, with each agent resuming its last conversation.

How Festi Built a Mobile App and CMS for a Big Four Regional Office

October 06, 2026

Festi built a cross-platform mobile application and a custom CMS for a regional office of a Big Four accounting firm, deployed inside its existing Microsoft Azure environment. Internal communication efficiency improved by 40%, manual content update workload fell by over 50%, and every intended user adopted the platform after a four-month build.

How Festi Automated Tax Report Filing for a Leading IT Solutions Company

October 05, 2026

Festi built an automated tax filing solution that connects data extraction, validation and submission into a single workflow on top of the client's existing financial systems. Accountant work time fell by 20%, filings go out faster, and error rates dropped across IRS and location-based sales tax reports, with deployment completed in two weeks.

Get in Touch

Building with coding agents, or planning to? Tell us what you are working on and we will share what has worked for our team.