Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import ApplicationServices

// MARK: - Model

/// Claude Code names a project dir after its cwd with every non-alphanumeric
/// character replaced by "-", so /Users/me/src/github.com/a_b becomes
/// -Users-me-src-github-com-a-b. Replacing only "/" silently fails to match
/// any path containing a dot or underscore.
func encodedProjectDir(_ path: String) -> String {
// ASCII-only on purpose: a non-ASCII letter is not [a-zA-Z0-9] either.
String(path.map { $0.isASCII && ($0.isLetter || $0.isNumber) ? $0 : "-" })
}

enum AgentKind: String { case claude = "Claude Code", codex = "Codex" }

struct AgentSession {
Expand Down Expand Up @@ -143,7 +152,7 @@ final class ProcessDiscovery {
// a claude process can hold several project transcripts open; prefer
// the one whose encoded project dir matches the process cwd
if all.count > 1, let cwd {
let encoded = cwd.replacingOccurrences(of: "/", with: "-")
let encoded = encodedProjectDir(cwd)
if let preferred = all.first(where: { $0.contains(encoded) }) { return preferred }
}
return all.first
Expand Down Expand Up @@ -1094,7 +1103,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
if let path = snap.transcriptPath {
seen.insert(path)
} else if snap.kind == .claude, let cwd = snap.cwd {
let encoded = cwd.replacingOccurrences(of: "/", with: "-")
let encoded = encodedProjectDir(cwd)
let i = cwdIndex[encoded, default: 0]
cwdIndex[encoded] = i + 1
seen.insert("cwd#\(encoded)#\(i)")
Expand Down Expand Up @@ -1167,7 +1176,7 @@ if CommandLine.arguments.contains("--scan") {
var cwdCounts: [String: Int] = [:]
for s in snaps {
if let p = s.transcriptPath { live.insert(p) }
else if s.kind == .claude, let c = s.cwd { cwdCounts[c.replacingOccurrences(of: "/", with: "-"), default: 0] += 1 }
else if s.kind == .claude, let c = s.cwd { cwdCounts[encodedProjectDir(c), default: 0] += 1 }
}
print("== sessions ==")
for s in SessionScanner().scan(live: live, claudeCwdCounts: cwdCounts) {
Expand Down