Based on claude-code-tools TmuxCLIController, this refactor: - Added DockerTmuxController class for robust tmux session management - Implements send_keys() with configurable delay_enter - Implements capture_pane() for output retrieval - Implements wait_for_prompt() for pattern-based completion detection - Implements wait_for_idle() for content-hash-based idle detection - Implements wait_for_shell_prompt() for shell prompt detection Also includes workflow improvements: - Pre-task git snapshot before agent execution - Post-task commit protocol in agent guidelines Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
6.2 KiB
Luzia Cockpit - Human-in-the-Loop Claude Sessions
Overview
Cockpit provides pausable Claude agent sessions using Docker containers with tmux.
The key innovation is that docker stop/start freezes/resumes the entire session state,
and Claude sessions persist via --session-id and --resume flags.
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ luzia cockpit │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Docker Container │ │
│ │ ┌──────────────────────────────────────────────────┐ │ │
│ │ │ tmux session │ │ │
│ │ │ ┌──────────────────────────────────────────┐ │ │ │
│ │ │ │ Claude CLI │ │ │ │
│ │ │ │ --session-id / --resume │ │ │ │
│ │ │ └──────────────────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Mounts: │ │
│ │ - /workspace → project home │ │
│ │ - ~/.claude → credentials + sessions │ │
│ │ - /var/cockpit → state files │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ docker stop → FREEZE (all state preserved) │
│ docker start → RESUME (continue conversation) │
│ │
└─────────────────────────────────────────────────────────────────┘
Commands
Start a Cockpit
luzia cockpit start <project>
Starts (or resumes) a cockpit container for a project.
Stop (Freeze) a Cockpit
luzia cockpit stop <project>
Stops the container, freezing all state. Can be resumed later.
Remove a Cockpit
luzia cockpit remove <project>
Permanently removes the container and state.
Send a Message
luzia cockpit send <project> <message>
Sends a message to Claude. First message creates the session, subsequent messages continue it.
Respond to a Question
luzia cockpit respond <project> <answer>
Alias for send - used when Claude is waiting for input.
Get Output
luzia cockpit output <project>
Shows recent output from the tmux session.
Check Status
luzia cockpit status [project]
Shows all cockpits or a specific one, including session ID and whether Claude is waiting for a response.
Attach Interactively
luzia cockpit attach <project>
Shows the command to attach to the tmux session for interactive work.
Session Persistence
Claude sessions are stored in the mounted ~/.claude/ directory:
~/.claude/projects/{workspace-path}/{session-id}.jsonl
The cockpit tracks:
session_id- UUID for the Claude conversationsession_started- Whether first message has been sentawaiting_response- If Claude asked a question (detected by "?" at end)last_question- The question Claude asked
Example Workflow
# Start a cockpit for musica project
luzia cockpit start musica
# → Started cockpit, Session: abc-123-def
# Send a task
luzia cockpit send musica "Fix the track component loading bug"
# → Claude analyzes and responds
# Claude asks a question - FREEZE the session
luzia cockpit stop musica
# → Container paused, queue can continue with other projects
# Later, human comes back with answer - RESUME
luzia cockpit start musica
luzia cockpit respond musica "Use lazy loading, target is 200ms"
# → Claude continues with the answer
Integration with Queue
When Claude is waiting for human input:
- Set project queue to
awaiting_humanstatus - Other projects continue processing
- On human response, resume project queue
Docker Image
Built from /opt/server-agents/orchestrator/docker/cockpit/Dockerfile:
- Base:
debian:bookworm-slim - Node.js 20 LTS
- Claude CLI (
@anthropic-ai/claude-code) - tmux with 50000 line history
- Mouse support for human attach
State Files
/var/lib/luz-orchestrator/cockpits/
├── admin.json
├── musica.json
└── overbits.json
Each JSON file contains:
{
"project": "musica",
"session_id": "abc-123-def",
"status": "running",
"session_started": true,
"awaiting_response": false,
"last_question": null
}
Benefits
- True Pause/Resume -
docker stop/startfreezes everything - Conversation Memory - Claude remembers via session persistence
- Non-blocking Queue - Projects don't block each other
- Human Attachment - Can attach tmux for direct interaction
- Credential Isolation - Each project uses shared credentials safely