Documents
Home>Documents>AI>Agent>Geny

Building Claude Control: A Multi-Session Claude Management System

5 min readFeb 3, 2026Feb 22, 2026

Claude Control Development Kickoff — A Multi-Session Claude Management System

Once I started using Claude Code seriously for day-to-day work, it became clear pretty quickly that a single session wasn't going to cut it. I constantly found myself needing to handle frontend changes, backend refactoring, and test writing all at the same time. That's what led me to build Claude Control — a multi-session Claude management system.

Structure of the First Commit

The initial project structure was straightforward: a single FastAPI server and a session manager class, nothing more.

from fastapi import FastAPI
from typing import Dict
import subprocess
import asyncio

app = FastAPI(title="Claude Control")

class SessionManager:
    def __init__(self):
        self.sessions: Dict[str, subprocess.Popen] = {}

    async def create_session(self, session_id: str, workdir: str) -> dict:
        process = subprocess.Popen(
            ["claude", "--json"],
            cwd=workdir,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        self.sessions[session_id] = process
        return {"session_id": session_id, "status": "created"}

    async def send_prompt(self, session_id: str, prompt: str) -> str:
        process = self.sessions.get(session_id)
        if not process:
            raise ValueError(f"Session {session_id} not found")
        process.stdin.write(f"{prompt}\n".encode())
        process.stdin.flush()
        output = process.stdout.readline().decode()
        return output

manager = SessionManager()

Design Decisions I Wrestled With Early On

The biggest question was how to manage processes. Spawning the Claude CLI as a subprocess is simple, but if the process dies, recovery is painful and tracking state gets messy. I went with this approach to start, but eventually migrated to Redis-based state management.

The other concern was session isolation. Each session needed to operate independently in its own working directory — changes made to files in one session couldn't bleed into another.

@app.post("/sessions")
async def create_session(request: CreateSessionRequest):
    session = await manager.create_session(
        session_id=request.session_id,
        workdir=request.workdir,
    )
    return {"data": session, "message": "Session created"}

@app.post("/sessions/{session_id}/prompt")
async def send_prompt(session_id: str, request: PromptRequest):
    result = await manager.send_prompt(session_id, request.prompt)
    return {"data": result}

Reflections

When I pushed that first commit, I genuinely wasn't sure this would turn into anything useful. But having lived with Claude Code firsthand, the need for multi-session support was undeniable — and over the course of 88 more commits, the system grew into something quite solid. The autonomous execution mode and the manager-worker pattern in particular were features I hadn't planned for at all when I started.

Tags
ClaudeAgentmulti-sessionPythonFastAPI