Skip to content

feat: dual-mode sessions (TUI + stream-json) with prompt API #52

@paolino

Description

@paolino

Context

Agent-daemon currently runs claude CLI in TUI mode inside tmux sessions, exposed via WebSocket for terminal clients (kanbanned TUI and browser). To support non-terminal clients (Telegram), we need a second mode where the claude process runs with --output-format stream-json --input-format stream-json, exposing a prompt-level API.

Terminology

  • Session = the tmux session, tied to a worktree. Lives until explicitly killed (issue work is done). DELETE /sessions/<id> kills the session.
  • Mode = how the claude process runs inside that tmux session: terminal (TUI) or structured (stream-json). Switching mode restarts the claude process, not the tmux session.
  • Resume = --resume {session_id} carries conversation history across claude process restarts within the same tmux session. Same cwd, same worktree, same session files — just different process flags.

Requirements

Dual-mode claude process

  • The claude process inside a tmux session can run in either terminal mode (TUI, existing) or structured mode (stream-json)
  • Mode is part of session state, visible in GET /sessions response
  • Switching mode: kill the current claude process, respawn with --resume {session_id} and the appropriate flags, inside the same tmux session
  • The tmux session and worktree are unaffected by mode switches
  • Mutual exclusion: only one claude process per session at a time

Prompt API (structured mode only)

  • POST /sessions/<id>/prompt — send a text prompt, stream back JSON response
  • Response streaming via SSE or WebSocket (TBD)
  • Permission callbacks forwarded to the caller (for Telegram approval buttons)

Mode switching

  • POST /sessions/<id>/mode — switch between terminal and structured
  • Uses --resume to carry conversation history across mode switches
  • Same tmux session, same cwd — resume should work naturally since session files stay in place

CLI flags for structured mode

Based on how claude-agent-sdk works internally:

claude --output-format stream-json \
       --input-format stream-json \
       --permission-prompt-tool stdio \
       --resume {session_id}

The daemon reads/writes JSON on the process stdin/stdout instead of piping terminal I/O.

Session lifecycle (unchanged)

  • POST /sessions — creates tmux session + worktree + launches claude (TUI by default)
  • POST /sessions/<id>/mode — restarts claude process with different flags (NEW)
  • DELETE /sessions/<id> — kills tmux session entirely, optionally cleans up worktree (existing, unchanged)

Non-goals

  • Replacing terminal mode — terminal clients (kanbanned TUI, browser) continue using the existing WebSocket terminal API
  • Python SDK dependency — the daemon speaks the JSON protocol directly

Metadata

Metadata

Assignees

No one assigned

    Labels

    featNew feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions