Resume Claude Code Sessions Interactively
A Go-based TUI (Terminal User Interface) application that allows users to browse and resume recent Claude Code sessions. It provides a sophisticated split-screen interface where users can browse projects, view sessions, and preview conversation messages in real-time before resuming.
Architecture Overview
The application follows the Go standard project layout with clean separation of concerns:
**cmd/claude-resume/** - Application entry point and CLI commands**internal/sessions/** - DuckDB queries and data operations for fetching projects and sessions**internal/tui/** - Bubble Tea-based terminal UI implementation**internal/db/** - Database initialization and connection management**pkg/models/** - Shared data models (Project, Session)Data Flow
1. DuckDB queries read from `~/.claude/projects/**/*.jsonl` files containing session history
2. Projects are fetched first with aggregated statistics (session count, last activity)
3. Sessions are lazily loaded only when a project is selected
4. Messages are lazily loaded when navigating sessions (first 10 + last 10 messages)
5. When a session is selected, the app changes to the project directory and executes `claude --resume <session-id>`
Implementation Instructions
Step 1: Set Up Project Structure
Create the following directory structure:
```
claude-resume/
├── cmd/claude-resume/
│ └── main.go
├── internal/
│ ├── db/
│ │ └── duckdb.go
│ ├── sessions/
│ │ └── sessions.go
│ └── tui/
│ └── tui.go
├── pkg/models/
│ └── models.go
├── go.mod
├── go.sum
├── Makefile
└── CLAUDE.md
```
Step 2: Initialize Go Module
Initialize the project with required dependencies:
```bash
go mod init github.com/username/claude-resume
go get github.com/marcboeker/go-duckdb
go get github.com/charmbracelet/bubbletea
go get github.com/charmbracelet/lipgloss
go get github.com/spf13/cobra
```
Step 3: Implement Database Connection (internal/db/duckdb.go)
Create a singleton DuckDB connection that:
Opens a temporary in-memory databaseInstalls and loads the JSON extension (`INSTALL json; LOAD json;`)Returns a reusable connection to prevent overheadStep 4: Define Data Models (pkg/models/models.go)
Define the following structs:
```go
type Project struct {
Path string
SessionCount int
LastSessionAt time.Time
}
type Session struct {
SessionID string
ProjectPath string
MessageCount int
FirstMessage string
LastActivity time.Time
Messages []Message
}
type Message struct {
Role string
Content string
}
```
Step 5: Implement Session Queries (internal/sessions/sessions.go)
Create three main query functions:
#### FetchProjects()
Use SQL to group all events by `cwd` (project path)Aggregate session counts and last activity timestampReturn top 100 projects ordered by last activity#### FetchSessions(projectPath string)
Filter events by project pathGroup by sessionId (cast to VARCHAR to handle binary data)Return up to 100 sessions per project#### FetchMessages(projectPath, sessionID string)
Use SQL window functions (`ROW_NUMBER() OVER`) to select first 10 and last 10 messagesHandle both string and array message formats in JSONParse tool calls with nested structure (type, name, input)Filter out system reminders and interruption messagesStep 6: Build TUI Interface (internal/tui/tui.go)
Implement a Bubble Tea model with the following features:
#### State Management
Track current view (project list vs. session view)Track selected project and session indexesManage left/right viewports for split-screen mode#### Project View
Display list of projects with session counts and last activitySupport keyboard navigation (↑/↓ arrows, j/k vim keys)Enter key to select a project and load its sessions#### Session View (Split-Screen)
**Left viewport**: List of sessions with message counts and last activity**Right viewport**: Preview of messages for currently selected sessionSupport navigation with ←/→ arrows or h/l vim keysEnter key to resume selected session#### Message Display Features
Truncate all messages to 50 characters for readabilityColor-code by role: User (blue), Assistant (pink), Tool messages (gray)Show tool calls with 🔧 icon and truncated parametersShow tool results with ↩ iconDisplay "... (N messages omitted) ..." when middle messages are skipped#### Terminal Handling
Use `tea.WithAltScreen()` for clean terminal restorationHandle `WindowSizeMsg` to dynamically resize viewportsCall `updateViewport()` on first window size message to fix initial renderUse `lipgloss.JoinHorizontal()` for proper split-screen layoutStep 7: Create CLI Commands (cmd/claude-resume/main.go)
Use Cobra to implement two commands:
#### `claude-resume show`
Default command that launches the TUIInitializes Bubble Tea program with alt screenHandles clean exit and error reporting#### `claude-resume debug-session <session-id>`
Prints raw session data for debuggingUseful for inspecting message structure and metadataStep 8: Add Build Configuration (Makefile)
Create targets for:
`build`: Compile the binary to `./bin/claude-resume``run`: Build and execute immediately`install`: Install to `$GOPATH/bin` for global usage`test`: Run all tests`clean`: Remove build artifactsStep 9: Handle Session Resumption
When user presses Enter on a selected session:
1. Extract project path from session
2. Use `os.Chdir()` to change to the project directory
3. Execute `claude --resume <session-id>` using `exec.Command()`
4. Exit the TUI cleanly to hand control to Claude Code
Important Implementation Details
SQL Query Patterns
Always cast `sessionId` to `VARCHAR` to avoid binary data issuesUse `COALESCE(cwd, 'Unknown')` to handle null project pathsWindow functions are critical for efficient message selection without loading entire conversationLimit queries to prevent UI overwhelm (100 projects, 100 sessions)Performance Optimizations
Sessions loaded on-demand when a project is selectedMessages loaded lazily when navigating sessionsSingleton database connection prevents repeated initializationEfficient SQL with aggregations instead of application-side filteringError Handling
Gracefully handle missing or corrupted JSONL filesProvide informative error messages when DuckDB connection failsHandle cases where no projects or sessions are foundValidate session ID before attempting resumeTesting Strategy
Test the following scenarios:
Projects with many sessions (verify scrolling)Sessions with many messages (verify first/last selection)Projects with no sessions (edge case)Sessions with various message types (user, assistant, tool calls, tool results)Window resize events (verify viewport recalculation)Navigation in both project and session viewsGit Commit Policy
**NEVER execute git commit commands unless explicitly requested by the user.**
Git commits should only be created when the user explicitly asks using phrases like:
"commit these changes""create a commit""git commit""please commit"This ensures users maintain full control over their git history and can review all changes before committing.
Development Commands
```bash
Build the application
make build
Build and run immediately
make run
Install to Go's bin directory
make install
Run tests
make test
Clean build artifacts
make clean
Update dependencies
go mod tidy
```
Usage Examples
After installation:
```bash
Launch interactive TUI to browse and resume sessions
claude-resume show
Debug a specific session (get raw data)
claude-resume debug-session <session-id>
```
Constraints
Requires DuckDB with JSON extension supportAssumes Claude Code session data exists at `~/.claude/projects/**/*.jsonl`Terminal must support ANSI colors and alt screen for proper renderingGo 1.21+ recommended for best compatibility