Accept story 39: Persistent Claude Code Sessions in Web UI

Use --resume <session_id> with claude -p so the web UI claude-code-pty
provider maintains full conversation context across messages, identical
to a long-running terminal Claude Code session.

Changes:
- Capture session_id from claude -p stream-json system event
- Pass --resume on subsequent messages in same chat session
- Thread session_id through ProviderConfig, ChatResult, WsResponse
- Frontend stores sessionId per chat, clears on New Session
- Unset CLAUDECODE env to allow nested spawning from server
- Wait for clean process exit to ensure transcript flush to disk

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dave
2026-02-20 11:51:19 +00:00
parent cff7f5fe7f
commit cde75bd7fb
11 changed files with 9524 additions and 61 deletions

View File

@@ -1,29 +0,0 @@
---
name: Persistent Claude Code Sessions in Web UI
test_plan: pending
---
# Story 39: Persistent Claude Code Sessions in Web UI
## User Story
As a developer using the web UI with the claude-code-pty provider, I want my conversation context to persist across messages, so that Claude remembers what we've discussed and can build on prior work — just like a normal terminal Claude Code session.
## Background
Currently the `claude-code-pty` provider spawns a fresh `claude -p` process for every message, sending only the last user message. This means Claude has zero memory of prior conversation turns. The fix is to capture the session ID from the first `claude -p` call and pass `--resume <session-id>` on subsequent messages. Claude Code persists conversation transcripts locally as JSONL files, so resumed sessions have full context — identical to a long-running terminal session from the API's perspective.
## Acceptance Criteria
- [ ] First message in a web UI chat spawns `claude -p "<message>" --output-format stream-json --verbose` and captures the session ID from the `system` or `result` JSON event
- [ ] Subsequent messages in the same chat spawn `claude -p "<message>" --resume <session-id> --output-format stream-json --verbose`
- [ ] Conversation context carries across messages (Claude remembers what was said earlier)
- [ ] Starting a new chat in the web UI starts a fresh session (no resume)
- [ ] Session ID is held per web UI chat session (not global)
- [ ] Cancellation still works mid-message
## Out of Scope
- Multi-turn conversation history display in the frontend (already works via existing message state)
- Session persistence across server restarts
- Managing/cleaning up old Claude Code session files on disk