Skip to content

Commit e586f08

Browse files
yepzdkclaude
andcommitted
Fix summary extraction and add terminal title
- Scan entire JSONL file for summaries (not just last 100 entries) - Set terminal tab title with status summary (e.g., "CSM: 2 needs input, 1 working") - Reset terminal title on exit Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 074d744 commit e586f08

File tree

3 files changed

+82
-9
lines changed

3 files changed

+82
-9
lines changed

internal/session/session.go

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,8 @@ func parseSession(projectName, logFile string, runningDirs map[string]bool) (Ses
246246
return session, nil
247247
}
248248

249-
// Extract summary from entries
250-
session.Summary = extractSummary(entries)
249+
// Extract summary from the log file (scans entire file)
250+
session.Summary = extractSummary(logFile)
251251

252252
// Determine status from log entries
253253
session.Status, session.Task = determineStatus(entries, isRunning)
@@ -263,15 +263,42 @@ func parseSession(projectName, logFile string, runningDirs map[string]bool) (Ses
263263
return session, nil
264264
}
265265

266-
// extractSummary finds the most recent summary entry
267-
func extractSummary(entries []LogEntry) string {
268-
// Look for the most recent summary entry
269-
for i := len(entries) - 1; i >= 0; i-- {
270-
if entries[i].Type == "summary" && entries[i].Summary != "" {
271-
return entries[i].Summary
266+
// extractSummary reads the entire file to find the most recent summary entry
267+
// Summaries are typically at the beginning of the file, so we need to scan it all
268+
func extractSummary(logFile string) string {
269+
file, err := os.Open(logFile)
270+
if err != nil {
271+
return ""
272+
}
273+
defer file.Close()
274+
275+
var lastSummary string
276+
scanner := bufio.NewScanner(file)
277+
buf := make([]byte, 0, 64*1024)
278+
scanner.Buffer(buf, 1024*1024)
279+
280+
for scanner.Scan() {
281+
line := scanner.Text()
282+
if line == "" {
283+
continue
284+
}
285+
286+
// Quick check before full JSON parse
287+
if !strings.Contains(line, `"type":"summary"`) {
288+
continue
289+
}
290+
291+
var entry LogEntry
292+
if err := json.Unmarshal([]byte(line), &entry); err != nil {
293+
continue
294+
}
295+
296+
if entry.Type == "summary" && entry.Summary != "" {
297+
lastSummary = entry.Summary
272298
}
273299
}
274-
return ""
300+
301+
return lastSummary
275302
}
276303

277304
// decodeProjectName converts the directory name to a readable project name

internal/ui/ui.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ func RenderJSON(sessions []session.Session) error {
6969

7070
// RenderLive renders the live dashboard view
7171
func RenderLive(sessions []session.Session) {
72+
// Set terminal title with status summary
73+
SetTerminalTitle(buildTerminalTitle(sessions))
74+
7275
// Clear screen and move cursor to top
7376
fmt.Print("\033[2J\033[H")
7477

@@ -136,6 +139,48 @@ func ShowCursor() {
136139
fmt.Print("\033[?25h")
137140
}
138141

142+
// SetTerminalTitle sets the terminal tab/window title
143+
func SetTerminalTitle(title string) {
144+
fmt.Printf("\033]0;%s\007", title)
145+
}
146+
147+
// ResetTerminalTitle resets the terminal title to default
148+
func ResetTerminalTitle() {
149+
fmt.Print("\033]0;\007")
150+
}
151+
152+
// buildTerminalTitle creates a status summary for the terminal title
153+
func buildTerminalTitle(sessions []session.Session) string {
154+
counts := make(map[session.Status]int)
155+
for _, s := range sessions {
156+
if s.Status != session.StatusInactive {
157+
counts[s.Status]++
158+
}
159+
}
160+
161+
// Priority: Needs Input > Working > Waiting > Idle
162+
var parts []string
163+
164+
if n := counts[session.StatusNeedsInput]; n > 0 {
165+
parts = append(parts, fmt.Sprintf("%d needs input", n))
166+
}
167+
if n := counts[session.StatusWorking]; n > 0 {
168+
parts = append(parts, fmt.Sprintf("%d working", n))
169+
}
170+
if n := counts[session.StatusWaiting]; n > 0 {
171+
parts = append(parts, fmt.Sprintf("%d waiting", n))
172+
}
173+
if n := counts[session.StatusIdle]; n > 0 {
174+
parts = append(parts, fmt.Sprintf("%d idle", n))
175+
}
176+
177+
if len(parts) == 0 {
178+
return "CSM: no active sessions"
179+
}
180+
181+
return "CSM: " + strings.Join(parts, ", ")
182+
}
183+
139184
// getStatusDisplay returns the symbol and color for a status
140185
func getStatusDisplay(status session.Status) (string, string) {
141186
switch status {

main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ func runLiveView(interval time.Duration) {
6868
ui.HideCursor()
6969
defer func() {
7070
ui.ShowCursor()
71+
ui.ResetTerminalTitle()
7172
ui.ClearScreen()
7273
fmt.Println("Goodbye!")
7374
}()

0 commit comments

Comments
 (0)