fix(claudbg-9627): scan up to 20 lines for cwd field in session discovery

The project path was missing for sessions whose first JSONL line has no
cwd field. Fix reads up to 20 non-empty lines to find any entry with cwd
(typically a system-type entry that may not be at line 1).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
Elijah Voigt 2 months ago
parent f45a0dfd87
commit 0bca469701

@ -1,10 +1,15 @@
--- ---
# claudbg-9627 # claudbg-9627
title: 'sessions list: some sessions show no project path' title: 'sessions list: some sessions show no project path'
status: todo status: completed
type: bug type: bug
priority: normal
created_at: 2026-03-31T23:44:53Z created_at: 2026-03-31T23:44:53Z
updated_at: 2026-03-31T23:44:53Z updated_at: 2026-04-01T05:59:53Z
--- ---
Some entries in `claudbg sessions list` do not display a project path. Investigate why the project path is missing for certain sessions. Some entries in `claudbg sessions list` do not display a project path. Investigate why the project path is missing for certain sessions.
## Summary of Changes
Fixed `read_cwd_from_first_line()` in `src/parser/discovery.rs`. The old code stopped after the first non-empty line even if it contained no `cwd` field. The fix scans up to 20 non-empty lines looking for any entry with a `cwd` field. Claude Code typically writes `cwd` on a `system`-type entry which may not be the very first line in all session files.

@ -44,26 +44,36 @@ fn claude_projects_dir() -> Option<PathBuf> {
Some(PathBuf::from(home).join(".claude").join("projects")) Some(PathBuf::from(home).join(".claude").join("projects"))
} }
/// Read the first non-empty line of a file and attempt to extract `cwd` from it. /// Scan the first few lines of a session file to find a `cwd` field.
/// ///
/// Returns `None` if the file cannot be read or the first line cannot be parsed. /// Reads up to 20 non-empty lines looking for any entry whose top-level `cwd`
/// field is set. The `cwd` field is written by Claude Code on `system`-type
/// entries; it may not appear on the very first line if the session file starts
/// with a user or assistant message.
///
/// Returns `None` if the file cannot be read or no `cwd` is found within the
/// first 20 lines.
fn read_cwd_from_first_line(path: &Path) -> Option<String> { fn read_cwd_from_first_line(path: &Path) -> Option<String> {
const MAX_LINES: usize = 20;
let file = std::fs::File::open(path).ok()?; let file = std::fs::File::open(path).ok()?;
let reader = BufReader::new(file); let reader = BufReader::new(file);
let mut checked = 0usize;
for line in reader.lines() { for line in reader.lines() {
let line = line.ok()?; let line = line.ok()?;
let trimmed = line.trim(); let trimmed = line.trim();
if trimmed.is_empty() { if trimmed.is_empty() {
continue; continue;
} }
checked += 1;
if let Ok(entry) = serde_json::from_str::<RawEntry>(trimmed) if let Ok(entry) = serde_json::from_str::<RawEntry>(trimmed)
&& entry.cwd.is_some() && entry.cwd.is_some()
{ {
return entry.cwd; return entry.cwd;
} }
// Return after first non-empty line regardless. if checked >= MAX_LINES {
break; break;
} }
}
None None
} }
@ -266,11 +276,7 @@ pub fn discover_all_agents() -> crate::error::Result<Vec<AgentRef>> {
let session_dir_entries = match std::fs::read_dir(&proj_path) { let session_dir_entries = match std::fs::read_dir(&proj_path) {
Ok(e) => e, Ok(e) => e,
Err(err) => { Err(err) => {
eprintln!( eprintln!("claudbg: could not read {}: {}", proj_path.display(), err);
"claudbg: could not read {}: {}",
proj_path.display(),
err
);
continue; continue;
} }
}; };

Loading…
Cancel
Save