@teddysc/claude-run 0.13.0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,7 @@
8
8
  <link rel="icon" href="/icon-192.png" sizes="192x192" />
9
9
  <link rel="icon" href="/icon-512.png" sizes="512x512" />
10
10
  <link rel="apple-touch-icon" href="/icon-192.png" />
11
- <script type="module" crossorigin src="/assets/index-Bz7pnCx9.js"></script>
11
+ <script type="module" crossorigin src="/assets/index-CfXKVwHJ.js"></script>
12
12
  <link rel="stylesheet" crossorigin href="/assets/index-CSMaeBYb.css">
13
13
  </head>
14
14
  <body class="bg-zinc-900 text-zinc-100">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teddysc/claude-run",
3
- "version": "0.13.0",
3
+ "version": "0.14.1",
4
4
  "description": "A beautiful web UI for browsing Claude Code conversation history",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,7 +8,8 @@
8
8
  },
9
9
  "main": "./dist/index.js",
10
10
  "files": [
11
- "dist"
11
+ "dist",
12
+ "spec.md"
12
13
  ],
13
14
  "scripts": {
14
15
  "dev": "concurrently \"bun run dev:web\" \"bun run dev:server\"",
package/spec.md ADDED
@@ -0,0 +1,274 @@
1
+ # claude-run Specification
2
+
3
+
4
+ A beautiful web UI for browsing Claude Code conversation history.
5
+
6
+ Always run `bun run build` when you're done modifying code!!!
7
+
8
+ ## Overview
9
+
10
+ claude-run is a web application that provides a searchable, browsable interface for Claude Code conversation history stored in `~/.claude/`. It consists of:
11
+
12
+ - **API Server**: Hono-based HTTP server with Server-Sent Events (SSE)
13
+ - **Web Frontend**: React + TypeScript + Tailwind CSS
14
+ - **File Watcher**: Real-time updates when conversations change
15
+ - **Full-Text Search**: ripgrep-powered search across conversation content
16
+
17
+ ## Architecture
18
+
19
+ ### Directory Structure
20
+
21
+ ```
22
+ /Users/tsca/testdir/claude-run/
23
+ ├── api/ # Backend API
24
+ │ ├── index.ts # CLI entry point
25
+ │ ├── server.ts # Hono HTTP server
26
+ │ ├── storage.ts # File system operations
27
+ │ ├── watcher.ts # File system watcher
28
+ │ ├── fulltext-search.ts # ripgrep search integration
29
+ │ └── types.ts # Shared TypeScript types
30
+ ├── web/ # Frontend
31
+ │ ├── app.tsx # Main App component
32
+ │ ├── utils.ts # Client-side utilities
33
+ │ ├── utils/
34
+ │ │ └── url-state.ts # URL state serialization
35
+ │ ├── hooks/
36
+ │ │ └── use-event-source.ts # SSE hook
37
+ │ └── components/
38
+ │ ├── session-list.tsx # Sidebar session list
39
+ │ ├── session-view.tsx # Conversation viewer
40
+ │ └── export-dialog.tsx # Export functionality
41
+ └── package.json
42
+ ```
43
+
44
+ ### Data Model
45
+
46
+ #### Session
47
+
48
+ ```typescript
49
+ interface Session {
50
+ id: string; // UUID from filename
51
+ display: string; // First user message (truncated)
52
+ timestamp: number; // Session start time
53
+ project: string; // Full project path
54
+ projectName: string; // Directory name only
55
+ messageCount: number; // User + assistant message count
56
+ startTime: number | null; // First message timestamp (ms)
57
+ endTime: number | null; // Last message timestamp (ms)
58
+ fileSizeBytes: number | null; // JSONL file size on disk
59
+ }
60
+ ```
61
+
62
+ #### Conversation Message
63
+
64
+ ```typescript
65
+ interface ConversationMessage {
66
+ type: "user" | "assistant" | "summary" | "file-history-snapshot";
67
+ uuid?: string;
68
+ timestamp?: number;
69
+ message?: {
70
+ model?: string;
71
+ content?: Array<{ type: string; text?: string; ... }>;
72
+ ...
73
+ };
74
+ ...
75
+ }
76
+ ```
77
+
78
+ #### Session Metadata
79
+
80
+ ```typescript
81
+ interface SessionMetadata {
82
+ id: string;
83
+ model: string | null; // null = unknown model
84
+ }
85
+ ```
86
+
87
+ ### File Storage
88
+
89
+ Claude Code stores data in `~/.claude/`:
90
+
91
+ - `history.jsonl` - Session metadata and display names
92
+ - `projects/<encoded-path>/<uuid>.jsonl` - Conversation files
93
+ - `file-history/` - File snapshots
94
+
95
+ ## API Endpoints
96
+
97
+ ### GET /api/projects
98
+ Returns list of all projects with sessions.
99
+
100
+ ### GET /api/sessions/stream
101
+ Server-Sent Events stream for real-time session updates.
102
+ - Event: `sessions` - Full session list (on connect)
103
+ - Event: `sessionsUpdate` - Incremental updates
104
+ - Event: `heartbeat` - Keep-alive (30s interval)
105
+
106
+ ### POST /api/sessions/metadata
107
+ Get model metadata for session IDs.
108
+ ```json
109
+ { "ids": ["uuid1", "uuid2"] }
110
+ ```
111
+
112
+ ### POST /api/sessions/delete
113
+ Delete sessions by ID (removes files and history entries).
114
+ ```json
115
+ { "ids": ["uuid1", "uuid2"] }
116
+ ```
117
+
118
+ ### POST /api/sessions/rename
119
+ Rename a session by updating its display title in history.jsonl.
120
+ ```json
121
+ { "id": "uuid1", "display": "New title", "project": "/path/to/project", "timestamp": 1700000000000 }
122
+ ```
123
+
124
+ ### GET /api/conversation/:id
125
+ Get full conversation for a session.
126
+
127
+ ### GET /api/conversation/:id/stream
128
+ Server-Sent Events for real-time conversation updates.
129
+
130
+ ### POST /api/search
131
+ Full-text search using ripgrep.
132
+ ```json
133
+ {
134
+ "query": "search term",
135
+ "options": {
136
+ "mode": "literal" | "regex",
137
+ "caseSensitive": boolean,
138
+ "wordRegexp": boolean,
139
+ "maxMatchesPerFile": number
140
+ },
141
+ "project": "project path or null"
142
+ }
143
+ ```
144
+
145
+ ## URL State Management
146
+
147
+ All UI state is synchronized with URL query parameters for shareable links:
148
+
149
+ | Param | Description | Default |
150
+ | ----------- | --------------------------- | ---------- |
151
+ | `project` | Selected project path | null (all) |
152
+ | `session` | Selected session ID | null |
153
+ | `q` | Search query | "" |
154
+ | `ft` | Full-text search enabled | false |
155
+ | `ftMode` | Search mode (literal/regex) | "literal" |
156
+ | `cs` | Case sensitive search | false |
157
+ | `ww` | Whole word search | false |
158
+ | `mm` | Max matches per file | 200 |
159
+ | `sidebar` | Sidebar collapsed | false |
160
+ | `batch` | Batch selection mode | false |
161
+ | `noUnknown` | Hide Unknown model sessions | false |
162
+ | `sort` | Sidebar sort mode | "recent" |
163
+
164
+ ### State Persistence
165
+
166
+ - Search: Debounced 600ms, replaceState while typing, pushState on idle
167
+ - Navigation: Immediate pushState
168
+ - Back/forward: All state restored from URL
169
+
170
+ ## Features
171
+
172
+ ### Session List Sidebar
173
+
174
+ - **Search**: Filter by display text or project name
175
+ - **Full-text search**: Toggle to search conversation content via ripgrep
176
+ - **Project filter**: Searchable dropdown with fuzzy match for project name and full path
177
+ - **Batch mode**: Multi-select sessions for bulk export
178
+ - **Unknown model filter**: Hide sessions without detected models
179
+ - Checkbox: "Hide Unknown model"
180
+ - When enabled and unknown sessions exist: "Delete Unknown (N)" button
181
+ - Delete removes session files and history entries
182
+ - **Compact metadata**: Message count, total duration, and JSONL file size
183
+ - **Sorting**: Sort by duration or JSONL size (ascending/descending)
184
+
185
+ ### Conversation View
186
+
187
+ - **Header**: Session title, project path, model, start/end times, message count, total duration, and JSONL file size
188
+ - **Rename title**: Click the session title to edit and save a new name
189
+ - **Message rendering**: User/assistant messages with tool calls
190
+ - **Collapsible tool calls**: Click to expand/collapse
191
+ - **Copy button**: Copy message text to clipboard
192
+ - **Resume command**: Copy command to resume session in terminal
193
+ - **Export**: Download conversation as Markdown
194
+
195
+ ### Export Dialog
196
+
197
+ - Single or batch session export
198
+ - Markdown format with metadata
199
+ - Copy to clipboard or download as file
200
+
201
+ ### Real-time Updates
202
+
203
+ - File watcher monitors `~/.claude/projects/`
204
+ - SSE pushes updates to connected clients
205
+ - Session list and conversation view update automatically
206
+
207
+ ## Session Metadata Extraction
208
+
209
+ For each session, the system extracts:
210
+
211
+ 1. **Model**: First occurrence in user/assistant messages
212
+ 2. **Start time**: First message timestamp
213
+ 3. **End time**: Last message timestamp
214
+ 4. **Message count**: Total user + assistant messages
215
+ 5. **JSONL size**: File size on disk
216
+
217
+ Unknown model sessions are those where no model was found in the conversation.
218
+
219
+ ## Cleanup and Maintenance
220
+
221
+ ### Orphaned Session Cleanup
222
+
223
+ On startup, the system automatically removes orphaned history entries (sessions in `history.jsonl` without corresponding `.jsonl` files).
224
+
225
+ ### Delete Logging
226
+
227
+ Both server and browser log deletion operations:
228
+
229
+ **Server console:**
230
+ ```
231
+ [/api/sessions/delete] Received request to delete N sessions: [...]
232
+ [deleteSession] Attempting to delete: <uuid>
233
+ [deleteSession] Successfully deleted: <path>
234
+ [deleteSession] Removed from history.jsonl: <uuid>
235
+ ```
236
+
237
+ **Browser console:**
238
+ ```
239
+ [handleDeleteUnknownSessions] Requesting deletion of N sessions: [...]
240
+ [handleDeleteUnknownSessions] Server response: {...}
241
+ [handleDeleteUnknownSessions] N deleted, N failed
242
+ ```
243
+
244
+ ## Development
245
+
246
+ ### Build
247
+
248
+ ```bash
249
+ bun install
250
+ bun run build
251
+ ```
252
+
253
+ ### Run
254
+
255
+ ```bash
256
+ bun start # Production
257
+ bun start --dev # Development with CORS
258
+ bun start --no-open # Don't open browser
259
+ bun start -p 3000 # Custom port
260
+ ```
261
+
262
+ ### Tech Stack
263
+
264
+ - **Runtime**: Bun
265
+ - **Server**: Hono
266
+ - **Frontend**: React, TanStack Virtual, Tailwind CSS, Lucide icons
267
+ - **Search**: ripgrep (rg)
268
+ - **Build**: Bun bundler
269
+
270
+ ## Security Considerations
271
+
272
+ - Server binds to 127.0.0.1 by default (localhost only)
273
+ - File paths validated before operations
274
+ - No authentication (intended for local use only)