Why I split the editor and the agent across two apps, how tmux keeps Claude Code sessions alive when the window closes, and the small configuration quirks that make it all feel native.

When I started using Claude Code seriously, I expected to live inside VS Code with its Claude Code extension. I tried that setup for a few weeks and it worked — but it always felt like two tools wrestling for the same real estate. The editor wanted to show me code. The agent wanted my full attention. Both wanted the bottom half of the window.
The configuration I've landed on splits the roles across two apps: a terminal for the agent, an editor for reviewing what it did. That separation turned out to be the thing that made the whole workflow click. This post is a walkthrough of that setup — Ghostty and tmux for the agent side, Zed for the review side — plus the small configuration knots you actually need to untie to make it feel native.
A plugin-based setup (VS Code + Claude Code extension) puts both the agent and the editor into a single window. It's convenient, but two things bothered me:
Separating the two apps fixes both. The agent runs full-screen in Ghostty (often split across tmux panes when I want two agents working in parallel). The editor opens separately, showing me only code. The agent keeps running when the editor is closed, and the editor reloads itself when the agent changes a file.
The mental model is simple: Claude Code is a process, not a panel. Once you start treating it that way, hosting it in a terminal multiplexer is the natural choice.
┌────────────────────────────────┐ ┌────────────────────────────────┐
│ Ghostty (fullscreen) │ │ Zed │
│ │ │ │
│ ┌─ tmux session: misoto22 ──┐ │ │ Project diff / Git panel │
│ │ ┌ claude ┐ ┌ pnpm dev ┐ │ │ │ Inline diff gutters │
│ │ │ │ │ │ │ │ │ (reads what Claude wrote) │
│ │ │ │ │ │ │ │ │ │
│ │ └────────┘ └──────────┘ │ │ │ │
│ └────────────────────────────┘ │ │ │
└────────────────────────────────┘ └────────────────────────────────┘
persisted by opens when I want
tmux + resurrect to review changes
Ghostty hosts tmux. tmux hosts the Claude Code session alongside a dev server or a REPL. Zed opens on the side to review what Claude changes. Closing Ghostty doesn't kill the Claude session — tmux detaches it, and tmux-resurrect brings it back later.
The rest of this post walks through each piece.
I used VS Code for years. Zed replaced it as my read-mostly editor for Claude Code work for two reasons: it's fast enough that I don't notice opening it, and its git-diff integration is good enough that reviewing agent-generated changes is the primary thing I do in it.
Git integration is what I actually use. Zed gives you three views of a change:
cmd-y / alt-yThe Git panel and Project Diff both refresh instantly when Claude writes to disk, so I can watch changes appear as the agent makes them. There's one caveat worth knowing: buffers you've already opened don't auto-reload. If Claude rewrites a file that's open in a Zed tab, Zed notices the file changed on disk but leaves the buffer showing the old content until you run editor::ReloadFile. The community has asked for automatic reload of unmodified buffers but it's not shipped yet.
My habit: use the Git panel and Project Diff to find what Claude changed, then open the file fresh (not from an existing tab) to actually read it. That sidesteps the stale-buffer issue entirely.
Split views — useful when I want a diff on one side and the current file on the other, or two related files side by side. Zed's splitting is lightweight enough that I use it reflexively instead of tab-hopping.
What I don't use Zed for: writing code directly. Claude writes almost all of the code now. Zed is where I read it, approve it, and occasionally fix a one-liner that's faster than explaining.
Ghostty is a GPU-accelerated terminal emulator with a zero-configuration philosophy. It does what iTerm2 and Alacritty do, but the defaults are good enough that I haven't had to touch its config beyond a font size.
What makes it worth choosing for Claude Code specifically:
Shift+Enter works natively for multi-line input in Claude Code. Most terminals need a keybinding tweak; Ghostty, iTerm2, WezTerm, and Kitty are the four the docs list as working out of the box.The thing to understand about Ghostty: it's intentionally boring. No built-in tab UI beyond the basics, no plugin system, no scripting layer. If you want sessions and splits, you reach for tmux. That's the point.
tmux is a terminal multiplexer. If you haven't used one, the three concepts to understand are:
The magic verb is detach. When you detach from a session, everything in it keeps running — the Claude Code conversation, the dev server, the REPL, a long-running build. You can come back later (tmux attach -t <name>) and find it exactly where you left it. Close Ghostty entirely and reopen it — still running. SSH disconnects in the middle of a deploy — still running.
For Claude Code specifically, this solves the single most annoying thing about terminal-hosted agents: losing the conversation because you closed a window.
My default layout for a project session is two panes: Claude Code on the left, a dev server or test watcher on the right. When I'm running two agents in parallel on different branches, it becomes two horizontal panes stacked in one window, one session per project.
Detach-and-reattach handles closed windows and SSH drops. It doesn't handle reboots — tmux sessions live in memory, so a restart clears them. For that you need two plugins, and for Claude Code specifically, a third.
tmux-resurrect saves the environment: session list, window layout, pane arrangement, working directories, and in many cases the running programs themselves. Trigger with prefix + Ctrl-s to save, prefix + Ctrl-r to restore.
tmux-continuum sits on top. It auto-saves every 15 minutes in the background, and with one setting it auto-restores the last save whenever tmux starts. The line that makes it work:
set -g @continuum-restore 'on'After that, tmux on a fresh boot comes up already attached to where you left off the last time.
The gap: plain resurrect captures that Claude Code was running in a pane, but not which conversation it was attached to. A restored pane opens a fresh Claude session, not your old one. That's fine for a shell or a dev server, but useless if you wanted to pick up a long conversation.
tmux-assistant-resurrect closes that gap. It's a companion plugin that hooks into CC's SessionStart event to record each live session's UUID, then hooks tmux-resurrect's save/restore lifecycle to re-run claude --resume <id> in the right pane when tmux comes back. The command it reconstructs keeps your CLI flags, your environment variables, and your session history intact. Install via TPM alongside the other two:
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'
set -g @plugin 'timvw/tmux-assistant-resurrect'The practical result: I reboot, Ghostty opens, tmux attaches, and three Claude Code windows come back in exactly the state they were in — same conversations, same working directories, same dev servers alongside them.
Most of ~/.tmux.conf is personal preference. A few lines, though, are load-bearing for Claude Code specifically.
Shift+Enter for newlines. tmux strips extended keys by default, which means Shift+Enter submits your message instead of inserting a newline inside Claude Code. Two lines fix this:
set -s extended-keys on
set -as terminal-features 'xterm*:extkeys'The first tells tmux to honour extended key reporting when Claude Code requests it. The second tells tmux that the outer terminal (Ghostty) can pass those sequences through.
Desktop notification passthrough. Claude Code's notification hook emits an escape sequence the outer terminal converts into a native notification. tmux intercepts that sequence by default, so notifications never reach Ghostty. One line opens the channel:
set -g allow-passthrough onThe same setting also lets Claude Code's terminal progress bar reach the outer terminal.
Sensible defaults. I use the standard tmux-sensible plugin so I don't have to re-learn every obscure default. The only things I change on top are a higher history limit (for when Claude spews a long trace), and set -g mouse on so I can click between panes instead of reaching for the prefix.
Everything else — status bar, colours, key remaps — is taste, and nothing about it is Claude-specific.
The flow I fall into without thinking:
tmux attach (or just tmux if continuum already restored) → I'm immediately back where I left off.cmd-tab to Zed. Project Diff shows everything that changed. Read, approve, or send corrections back to Claude.cmd-tab to Zed for that too.Two apps, clear roles, no context switching penalty. It stops feeling like setup and starts feeling like a single environment.
If you're moving from VS Code + Claude Code extension to a terminal-hosted setup, in order:
Shift+Enter works natively. iTerm2, WezTerm, and Kitty are the other three that work out of the box.tmux-resurrect, tmux-continuum, and tmux-assistant-resurrect. All three via TPM in fifteen minutes. This is the piece that makes the setup actually resilient.extended-keys, terminal-features, allow-passthrough).cmd-tab. Two full windows will feel wrong at first. Give it a week.Most of the friction in an AI-driven workflow comes from fighting your tools for attention. Splitting the agent and the editor into two apps ends that fight. Everything else — session persistence, keybindings, diff views — is polish on top of that one decision.
Every link below is a page I consulted while writing this post. The notes are what you'll actually get from each.
Shift+Enter configuration, tmux extended-keys requirements, and notification passthrough. Read this before touching ~/.tmux.conf.SessionStart to track session IDs and re-runs claude --resume on restore.