Summary
treetop builds and runs on macOS today, but its automatic in-use detection is Linux-only. On macOS, worktrees with a live agent session running inside them are not marked ● unless the .treetop-inuse marker file is present.
Background
In-use detection has two independent signals (see session.go):
.treetop-inuse marker file (marker.go) — cross-platform and deterministic. Already works on macOS.
/proc session scan (session.go scanSessions) — best-effort auto-detection of live agent sessions. It walks /proc/<pid> to record, per agent process:
- its cwd (catches a top-level
claude running in a worktree)
- the regular files it holds open (catches in-process subagents that never
chdir into the worktree but read/write its files)
scanSessions() early-returns supported: false when runtime.GOOS != "linux" (session.go:31), and supportsProcScan() (main.go:158) reports it unsupported. So on macOS only signal (1) fires.
Goal
Implement a darwin equivalent of the /proc scan so live agent sessions are auto-detected on macOS without requiring the marker file — matching the Linux experience (top-level sessions and in-process subagents).
Approach
macOS has no /proc. Equivalent process introspection is available via libproc:
- enumerate pids —
proc_listpids / proc_listallpids
- cwd —
proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, ...) -> vnodePathInfo.vip_path
- open files —
proc_pidinfo(pid, PROC_PIDLISTFDS, ...) then proc_pidfdinfo(..., PROC_PIDFDVNODEPATHINFO, ...) per fd to resolve regular-file paths
Either via cgo against <libproc.h> or by shelling out to lsof as a fallback. cgo/libproc is preferred (no external dependency, faster, no per-pid process spawn).
Suggested structure
- Split the platform-specific scan behind a build tag:
session_linux.go (existing /proc logic) and session_darwin.go (new libproc logic), with the shared sessionScan struct and the agent-matching / decay-tracker logic staying platform-neutral.
isAgentProcess and resolvedLink/openFiles helpers need darwin counterparts.
- Update
supportsProcScan() / the help text in main.go:37 so the "Linux-only" caveat reflects darwin support.
Acceptance criteria
Out of scope
Summary
treetopbuilds and runs on macOS today, but its automatic in-use detection is Linux-only. On macOS, worktrees with a live agent session running inside them are not marked●unless the.treetop-inusemarker file is present.Background
In-use detection has two independent signals (see
session.go):.treetop-inusemarker file (marker.go) — cross-platform and deterministic. Already works on macOS./procsession scan (session.goscanSessions) — best-effort auto-detection of live agent sessions. It walks/proc/<pid>to record, per agent process:clauderunning in a worktree)chdirinto the worktree but read/write its files)scanSessions()early-returnssupported: falsewhenruntime.GOOS != "linux"(session.go:31), andsupportsProcScan()(main.go:158) reports it unsupported. So on macOS only signal (1) fires.Goal
Implement a darwin equivalent of the
/procscan so live agent sessions are auto-detected on macOS without requiring the marker file — matching the Linux experience (top-level sessions and in-process subagents).Approach
macOS has no
/proc. Equivalent process introspection is available vialibproc:proc_listpids/proc_listallpidsproc_pidinfo(pid, PROC_PIDVNODEPATHINFO, ...)->vnodePathInfo.vip_pathproc_pidinfo(pid, PROC_PIDLISTFDS, ...)thenproc_pidfdinfo(..., PROC_PIDFDVNODEPATHINFO, ...)per fd to resolve regular-file pathsEither via cgo against
<libproc.h>or by shelling out tolsofas a fallback. cgo/libproc is preferred (no external dependency, faster, no per-pid process spawn).Suggested structure
session_linux.go(existing/proclogic) andsession_darwin.go(new libproc logic), with the sharedsessionScanstruct and the agent-matching / decay-tracker logic staying platform-neutral.isAgentProcessandresolvedLink/openFileshelpers need darwin counterparts.supportsProcScan()/ the help text inmain.go:37so the "Linux-only" caveat reflects darwin support.Acceptance criteria
claude/agent session running in a worktree is marked●on macOS with no marker file.Out of scope