I use Claude Code from the terminal inside VS Code.

That works well until I open a second project.

When I finish with that project, muscle memory takes over and I close VS Code with Cmd+Q. The problem is that this also closes the first window and interrupts any Claude Code session still running there.

After doing this enough times, I started looking for a way to keep Claude alive independently of VS Code.

My first attempt: screen

My first thought was GNU Screen.

I discovered it years ago on Linux, and it has helped me through plenty of long-running jobs on remote servers. It seemed like a natural fit for this problem.

I started a named session:

screen -S claude

Then I launched Claude Code inside it, closed VS Code with Cmd+Q, reopened the project, and reattached to the session.

Claude was still there.

That was the good news. The basic idea worked: the agent did not need to live and die with the editor terminal.

The terminal colors were less successful.

macOS ships an older version of Screen, so I installed a newer one with Homebrew. That improved things partially, but I still could not get the full color output from my terminal setup. Claude Code was usable, but the interface looked mostly gray.

I had solved the persistence problem, but the experience still did not feel right.

Moving to tmux

Then I remembered tmux.

I had already been using it in desktop terminal workflows for years, so I tried the same setup there. This time everything worked as I wanted: the Claude Code session survived closing VS Code, and the terminal interface kept its colors.

The workflow is simple:

  1. Start Claude Code inside a named tmux session.
  2. Close VS Code whenever needed.
  3. Open a terminal later and attach to the same session.

The Claude process belongs to tmux rather than the VS Code terminal, so closing the editor no longer ends the session.

The shell shortcuts

Once the setup proved reliable, I added a few shell functions:

claude-new() {
  if [ -z "$1" ]; then
    echo "Usage: claude-new <tmux-name>"
    return 1
  fi

  tmux new-session -d -s "$1" "claude"
  tmux attach -t "$1"
}

claude-resume() {
  tmux new-session "claude -r"
}

# Attach to an existing Claude tmux session
claude-attach() {
  if [ -z "$1" ]; then
    echo "Usage: claude-attach <session-name>"
    return 1
  fi

  tmux attach-session -t "$1"
}

# Kill a Claude tmux session
claude-kill() {
  if [ -z "$1" ]; then
    echo "Usage: claude-kill <session-name>"
    return 1
  fi

  tmux kill-session -t "$1"
}

claude-new creates a detached tmux session, starts Claude Code inside it, and immediately attaches to it:

claude-new blog

claude-resume opens Claude’s session picker inside a new tmux session:

claude-resume

This resumes a Claude session. It does not reconnect to an existing tmux session.

If the tmux session itself is already running, I reconnect to it with claude-attach:

claude-attach blog

When I no longer need it:

claude-kill blog

And whenever I want to see what is still active:

tmux ls

A small fix for an annoying habit

This is not a complicated setup.

There is no daemon to configure, no custom Claude integration, and no need to change how I use VS Code. tmux simply gives the process a longer lifetime than the terminal window where it started.

Now I can open multiple projects, close VS Code with Cmd+Q, and return later without wondering whether I just killed an active Claude Code session.