[FEATURE] Session-as-process primitive: spawn, communicate, and terminate isolated sessions programmatically

Status Open
Maintainer reply ✓ Yes — bcherny
Activity 5 comments · opened Jun 17, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

Summary

Expose a first-class tool/API for spawning an isolated Claude Code session as a manageable subprocess — with stdin/stdout communication and PID-based lifecycle control — from within a running session.

Motivation

Today, parallel sessions require a human to open a new terminal and run claude manually. There is no programmatic way for a running session to:

  1. Spawn another isolated session (own context window, own shell state)
  2. Communicate with it (send prompts, read results via stdin/stdout or a structured channel)
  3. Terminate it (by PID or session ID)

This is a basic process-management primitive that the architecture already supports — sessions are already isolated processes with independent context windows. The missing piece is a clean spawn/communicate/kill contract exposed as a tool.

How this differs from existing primitives

| Primitive | Gap |
|---|---|
| Subagents (Agent tool) | Share the parent's context window and cwd. Not isolated sessions — they inherit the parent's CLAUDE.md, tools, and conversation history. |
| Agent Teams | Hierarchical (lead + teammates), shared task list. Models "many hands on one objective", not "hand off a discrete job and read the result." |
| Headless claude -p | Blocks the parent. No structured result-readback. Not presented as a supported tool. |
| #65456 (cross-project handoff) | Related but scoped to cross-directory handoff with different CLAUDE.md. This request is about the lower-level primitive: process lifecycle management for any session, same or different project. |

Proposed capability

A tool (e.g. SpawnSession) that:

  • Starts a new claude process with its own context window and shell
  • Accepts: working directory (optional, defaults to current), initial prompt, model override, permission scope
  • Returns: a session handle (PID or session ID)
  • Provides: SendToSession(handle, message) and ReadFromSession(handle) for structured communication
  • Provides: TerminateSession(handle) for cleanup
  • The spawned session runs asynchronously — the parent continues working while it runs

The key insight: sessions are already processes. The tool just needs to expose fork + pipe + kill semantics that the OS already provides, wrapped in a clean contract.

Use cases

  • Parallel ticket work: spawn a session per ticket, each in its own worktree, coordinate from an orchestrator
  • Review isolation: spawn a clean session for code review without context bleed from the implementation session
  • Research + implementation: spawn a research session while continuing implementation, read findings when ready
  • CI/automation: programmatically manage session lifecycles without human terminal management

Related

  • #65456 — cross-project session handoff (higher-level, focuses on different-directory identity switching)
  • #52051 — parallel session working tree conflicts (focuses on git isolation, not session lifecycle)

View original on GitHub ↗

5 Comments

github-actions[bot] · 2 months ago

Found 2 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/66126
  2. https://github.com/anthropics/claude-code/issues/65456

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

prassanna-ravishankar · 2 months ago

the distinction you draw (a real isolated session as a managed subprocess, not a shared-context subagent and not a shared-task-list team) is the right one, those are three different things that keep getting conflated.

repowire gives the spawn/communicate/terminate contract over a mesh: spawn_peer starts an isolated session, ask/notify talk to it, kill_peer tears it down, and each peer has its own context window and shell state rather than sharing the parents. lifecycle is by peer id so same-path spawns dont collide.

its addressed over a daemon rather than raw stdin/stdout + PID, so the transport differs from what you spec, and the claude-family path injects via tmux under the hood. but the spawn-an-independent-session-and-coordinate-with-it primitive works today, and across runtimes.

kcarriedo · 2 months ago

The three-way distinction you've laid out (subagent vs. agent team vs. headless claude -p) is exactly right, and it gets blurred in most discussions because people conflate coordination model with process lifecycle.

The gap that hits hardest in practice: there's no way to know whether a spawned session is still running, has completed, or has silently died. The OS knows -- it's a process with a PID -- but nothing surfaces that state to the user or to the orchestrating session. You end up polling a shared markdown file or watching a terminal you can't see.

From running a Mac-native session manager for Claude Code (Claudiverse, currently in private beta -- https://claudiverse.ai), the minimum viable primitive isn't even spawn/communicate/kill. It's just a readable session status: running, completed, failed, unknown. Once that exists, you can build the coordination layer on top of it.

The repowire approach @prassanna-ravishankar linked is interesting because it decouples the coordination bus from the session lifecycle -- but it still requires all sessions to opt in to the mesh at startup. A native SpawnSession tool that returns a handle with queryable state would make that coordination possible without pre-arrangement.

Two concrete things that would unblock most of the use cases in the issue:

  1. A session registry (even just a local file or socket) that each claude process writes its pid, cwd, start time, and last-heartbeat into on startup.
  2. A TerminateSession(handle) that does a full process group kill -- not just the claude CLI child, but any Claude CLI / MCP descendants, which are the ones that can keep running after the parent exits.

The second one is the safety invariant. Without it, "terminate" just orphans the subtree.

dabodamjan · 28 days ago

Concrete use case from a solo-founder release workflow: I run app releases with a "hub" session that plans and triages, plus dedicated tester sessions that only do simulator QA (separate context, own simulator device each). The session-management tools already cover discovery and messaging (list_sessions / send_message) — creation is the only missing piece. Today the hub writes the opening prompt for each tester session and I manually create the session and paste it. A spawn-with-initial-prompt primitive (CLI or desktop app) would remove the single manual step in an otherwise autonomous loop.

bcherny collaborator · 14 days ago

Thanks for the thorough writeup. A good chunk of this already exists, though it may not be obvious:

A first-class "spawn a full isolated session in another directory and read back its result" tool from inside a session is not there as a single primitive yet, so leaving this open for that.

🤖 Generated with Claude Code