---
name: "Claude Code session ID not persisted across browser refresh"
---

# Bug 264: Claude Code session ID not persisted across browser refresh

## Description

The Claude Code provider uses a session_id to resume conversations via `--resume <id>`. This session_id is stored in React state (`claudeSessionId`) but is NOT persisted to localStorage. After a browser refresh, the session_id is lost (`null`), so Claude Code cannot resume the prior session.

A fallback exists (`build_claude_code_context_prompt` in `server/src/llm/chat.rs:188`) that injects prior messages as flattened text inside a `<conversation_history>` block, but this loses structure (tool calls, tool results, reasoning) and Claude Code treats it as informational text rather than actual conversation turns. In practice, the LLM does not retain meaningful context after refresh.

This is the root cause behind bug 245 (chat history persistence regression). The localStorage message persistence from story 145 works correctly for the UI, but the LLM context is not properly restored because the session cannot be resumed.

Key files:
- `frontend/src/components/Chat.tsx:174` — `claudeSessionId` is ephemeral React state
- `frontend/src/components/Chat.tsx:553` — session_id only sent when non-null
- `server/src/llm/chat.rs:278` — backend branches on session_id presence
- `server/src/llm/providers/claude_code.rs:44` — `--resume` flag passed to Claude CLI

## How to Reproduce

1. Open the Story Kit web UI and select claude-code-pty as the model
2. Have a multi-turn conversation with the agent
3. Refresh the browser (F5 or Cmd+R)
4. Send a new message referencing the prior conversation
5. The LLM has no knowledge of the prior conversation

## Actual Result

After refresh, claudeSessionId is null. Claude Code spawns a fresh session without --resume. The fallback text injection is too lossy to provide meaningful context. The LLM behaves as if the conversation never happened.

## Expected Result

After refresh, the Claude Code session is resumed via --resume, giving the LLM full context of the prior conversation including tool calls, reasoning, and all turns.

## Acceptance Criteria

- [ ] claudeSessionId is persisted to localStorage (scoped by project path) and restored on component mount
- [ ] After browser refresh, the next chat message includes session_id in the ProviderConfig
- [ ] Claude Code receives --resume with the persisted session_id after refresh
- [ ] Clearing the session (clear button) also clears the persisted session_id
- [ ] After server restart with session files intact on disk, conversation resumes correctly
