fix: Orphan process check now correctly detects tmux server on macOS
The orphan-processes check was incorrectly killing active crew sessions because pgrep -x tmux does not reliably find the tmux server on macOS. Root cause: - pgrep -x tmux was finding tmux attach-session processes but missing the actual tmux server process - Claude processes running in tmux panes were incorrectly flagged as orphaned because their parent (tmux server) was not in the allowed list Fixes: 1. Use ps + awk instead of pgrep to find tmux processes more reliably 2. Exclude Claude.app desktop processes from orphan detection (they are not Gas Town CLI processes) Closes: gt-ronyn Generated with Claude Code Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -324,13 +324,15 @@ type processInfo struct {
|
||||
cmd string
|
||||
}
|
||||
|
||||
// getTmuxSessionPIDs returns PIDs of all tmux server processes.
|
||||
// getTmuxSessionPIDs returns PIDs of all tmux server processes and pane shell PIDs.
|
||||
func (c *OrphanProcessCheck) getTmuxSessionPIDs() (map[int]bool, error) {
|
||||
// Get tmux server PID and all pane PIDs
|
||||
pids := make(map[int]bool)
|
||||
|
||||
// Find tmux server process
|
||||
out, err := exec.Command("pgrep", "-x", "tmux").Output()
|
||||
// Find tmux server processes using ps instead of pgrep.
|
||||
// pgrep -x tmux is unreliable on macOS - it often misses the actual server.
|
||||
// We use ps with awk to find processes where comm is exactly "tmux".
|
||||
out, err := exec.Command("sh", "-c", `ps ax -o pid,comm | awk '$2 == "tmux" || $2 ~ /\/tmux$/ { print $1 }'`).Output()
|
||||
if err != nil {
|
||||
// No tmux server running
|
||||
return pids, nil
|
||||
@@ -363,7 +365,8 @@ func (c *OrphanProcessCheck) getTmuxSessionPIDs() (map[int]bool, error) {
|
||||
return pids, nil
|
||||
}
|
||||
|
||||
// findClaudeProcesses finds all running claude/claude-code processes.
|
||||
// findClaudeProcesses finds all running claude/claude-code CLI processes.
|
||||
// Excludes Claude.app desktop application and its helpers.
|
||||
func (c *OrphanProcessCheck) findClaudeProcesses() ([]processInfo, error) {
|
||||
var procs []processInfo
|
||||
|
||||
@@ -374,8 +377,12 @@ func (c *OrphanProcessCheck) findClaudeProcesses() ([]processInfo, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Regex to match claude processes
|
||||
claudePattern := regexp.MustCompile(`(?i)claude`)
|
||||
// Regex to match claude CLI processes (not Claude.app)
|
||||
// Match: "claude" or paths ending in "/claude"
|
||||
claudePattern := regexp.MustCompile(`(?i)(^claude$|/claude$)`)
|
||||
|
||||
// Pattern to exclude Claude.app and related desktop processes
|
||||
excludePattern := regexp.MustCompile(`(?i)(Claude\.app|claude-native|chrome-native)`)
|
||||
|
||||
for _, line := range strings.Split(string(out), "\n") {
|
||||
fields := strings.Fields(line)
|
||||
@@ -383,8 +390,15 @@ func (c *OrphanProcessCheck) findClaudeProcesses() ([]processInfo, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if command contains "claude"
|
||||
// Check if command matches claude CLI
|
||||
cmd := strings.Join(fields[2:], " ")
|
||||
|
||||
// Skip desktop app processes
|
||||
if excludePattern.MatchString(cmd) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Only match CLI claude processes
|
||||
if !claudePattern.MatchString(cmd) {
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user