Interactive `claude` sessions are classified as background jobs post-2.1.139, causing bg-only guards to fire on user-foreground work

Resolved 💬 7 comments Opened May 16, 2026 by smabe Closed May 27, 2026

Summary

After the agent-view release (v2.1.139, May 11), every Claude Code session — including ones launched interactively by typing claude in a terminal — is set up with $CLAUDE_JOB_DIR, a daemon-managed state file, and a template: "bg" flag. As a result, instructions and guards that were intended for spawned/unattended background jobs now fire on user-foreground sessions too.

The most visible symptom is the worktree-isolation guard: every Edit/Write on a tracked file refuses with a "background session hasn't isolated its changes yet" error and forces the agent to do an EnterWorktree → commit → push → ExitWorktree → pull dance, even for a one-line edit in a session the user is actively typing in.

This is not a misconfiguration on the user's machine — it's the daemon's classification behavior. I reproduce it on a stock install on 2.1.143.

Repro

  1. macOS, fresh terminal. No --bg, no agent-view, no shell wrappers.
  2. cd ~/some/git/repo && claude — open a normal foreground session.
  3. From inside that session, ask the agent to make any single-file edit on a tracked file.
  4. Observe the Edit tool fail with:

> This background session hasn't isolated its changes yet. Call EnterWorktree first so edits land in a worktree instead of the shared checkout, then retry this edit using the worktree path. (To disable this guard for this repo, set "worktree": {"bgIsolation": "none"} in .claude/settings.json.)

  1. The agent's system prompt also includes the line "This session runs as a background job. The user may be chatting with you live or may have stepped away to check results later — respond naturally either way, and don't refer to yourself as 'a background agent.'" — which itself acknowledges the awkwardness.

Evidence the daemon is the cause

Process tree

A single claude invocation spawns a daemon + spare-agent pool:

44013  claude                                                            # foreground (terminal s000)
44581  claude daemon run --origin transient --spawned-by {...,"pid":44013}
44603  --bg-pty-host  .../fb780c90.pty.sock 200 50 --  --bg-spare ...
44605  --bg-spare     /tmp/cc-daemon-501/.../fb780c90.claim.sock
44608  --bg-pty-host  .../90e4af4c.sock    162 36 --  --session-id 90e4af4c-... --agent claude
44611  --bg-pty-host  .../30bad891.pty.sock 200 50 --  --bg-spare ...
44615  --session-id   90e4af4c-2ad8-4c0e-906e-7edbc3a3ad1e --agent claude
44616  --bg-spare     /tmp/cc-daemon-501/.../30bad891.claim.sock

So:

  • The foreground claude (44013) auto-spawns a daemon (44581).
  • The daemon keeps a warm spare agent (44615) and bg-pty hosts ready, presumably so (agent view) feels instant.
  • Everything — including the user's interactive session — gets registered as an "agent" with a job dir.

Job-dir contents for the foreground session

$ env | grep CLAUDE_JOB_DIR
CLAUDE_JOB_DIR=/Users/smabe/.claude/jobs/ec39b0b1

$ cat $CLAUDE_JOB_DIR/state.json | head -20
{
  "state": "blocked",
  "tempo": "active",
  ...
  "template": "bg",
  "respawnFlags": ["--effort", "high", "--permission-mode", "auto"],
  "name": "push-code-changes",
  "nameSource": "auto",
  ...
  "cliVersion": "2.1.143",
  "cwd": "/Users/smabe/projects/HealthData",
  ...
}

template: "bg" is set on the user-foreground session. The daemon also auto-named the session ("push-code-changes") from the agent's last bash output, the way agent-view names spawned background jobs.

Why this is a bug, not a feature

Several harness-level behaviors were written for the old model where $CLAUDE_JOB_DIR implied "unattended bg work that may collide with the user's working copy and other parallel jobs":

  1. Worktree-isolation guard — refuses Edit/Write on tracked files until EnterWorktree. Sensible for an unattended job; pure friction for a user typing into the same session.
  2. System-prompt "Background Session" block — tells the agent the user "may have stepped away." Wrong for the user-foreground case (and the prompt now has to apologize for itself with "respond naturally either way").
  3. Auto-naming — naming the session from agent output ("push-code-changes") is great for unattended jobs the user finds later in agent-view. Less useful, mildly confusing, for an interactive terminal session.

Discrimination signal exists but isn't being used. The daemon already has:

  • --origin transient vs other origins
  • --spawned-by {label, cwd, pid} for spawned jobs
  • --bg / --bg-spare for actual bg pool entries vs the user's TTY-attached session
  • A TTY-attached child process visible to the daemon

Any of those could classify "the user is talking to this session live" vs "this session was spawned to run unattended."

Suggested fix

Distinguish the two cases at the daemon layer and propagate to:

  1. Set template: "foreground" (or omit template) on user-typed sessions; reserve template: "bg" for sessions spawned via claude --bg, agent-view "new background session," Agent tool subagents, Task API spawns, etc.
  2. The worktree-isolation guard should fire only on template: "bg", not on the presence of $CLAUDE_JOB_DIR.
  3. The "Background Session" block in the system prompt should only be inserted for template: "bg".
  4. Auto-naming from agent output should only happen for template: "bg".

The bgIsolation: "none" setting documented in the guard message is a workaround that disables protection wholesale, which is the wrong knob — users running real parallel bg work in the same repo want the protection on; they just don't want it firing on their interactive session.

Environment

  • claude --version2.1.143 (Claude Code)
  • macOS 25.5.0 (darwin), zsh, Ghostty terminal
  • Plain claude invocation in a project directory, no flags, no shell wrappers

Related

  • #59702 — EnterWorktree/ExitWorktree cwd-pinning bug (filed today by another user). Compounds with this one: the forced worktree dance is the trigger surface for #59702, so fixing this issue would reduce exposure to that one too.
  • #59846 — Naming feedback: "agent view" conflates with the existing "agent" concept. Separate concern, same underlying conflation: "agent" and "session" are no longer cleanly distinguished post-2.1.139, and harness behaviors keyed off "is this a session?" assumptions break in surprising places.

View original on GitHub ↗

This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗