From 166e44161dae7a21f33a0f5861537be1db641a07 Mon Sep 17 00:00:00 2001 From: Pierre Martin Date: Mon, 23 Mar 2026 13:25:27 +0100 Subject: [PATCH] feat(01-01): implement FindClaudeProcesses and EncodePath - Scan /proc for PIDs with "claude" in cmdline - Read cwd via os.Readlink, skip errors silently - EncodePath replaces / and . with - for ~/.claude/projects/ folder names Co-Authored-By: Claude Opus 4.6 (1M context) --- proc.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 proc.go diff --git a/proc.go b/proc.go new file mode 100644 index 0000000..adde78e --- /dev/null +++ b/proc.go @@ -0,0 +1,62 @@ +package main + +import ( + "os" + "path/filepath" + "strconv" + "strings" +) + +// FindClaudeProcesses scans procDir (typically "/proc") for active Claude Code processes. +// It returns a Process for each PID whose cmdline starts with "claude". +// Read errors (permission denied, vanished process) are silently skipped. +func FindClaudeProcesses(procDir string) ([]Process, error) { + entries, err := os.ReadDir(procDir) + if err != nil { + return nil, err + } + + var procs []Process + + for _, entry := range entries { + pid, err := strconv.Atoi(entry.Name()) + if err != nil { + continue // not a PID directory + } + + cmdlineData, err := os.ReadFile(filepath.Join(procDir, entry.Name(), "cmdline")) + if err != nil { + continue // permission denied or process vanished + } + + parts := strings.Split(strings.TrimRight(string(cmdlineData), "\x00"), "\x00") + if len(parts) == 0 { + continue + } + + // Match if the binary name ends with "claude" or is exactly "claude" + bin := filepath.Base(parts[0]) + if bin != "claude" { + continue + } + + cwd, err := os.Readlink(filepath.Join(procDir, entry.Name(), "cwd")) + if err != nil { + continue // cannot read cwd + } + + procs = append(procs, Process{ + PID: pid, + Cmd: parts, + Cwd: cwd, + }) + } + + return procs, nil +} + +// EncodePath converts an absolute path to the folder name format used by +// ~/.claude/projects/. Slashes and dots are replaced with dashes. +func EncodePath(path string) string { + return strings.NewReplacer("/", "-", ".", "-").Replace(path) +}