Skip to content

fix: orphaned agent processes when deleting a worktree in the TUI - #21

Merged
xico42 merged 1 commit into
mainfrom
fix/deleting-session
Jul 16, 2026
Merged

fix: orphaned agent processes when deleting a worktree in the TUI#21
xico42 merged 1 commit into
mainfrom
fix/deleting-session

Conversation

@xico42

@xico42 xico42 commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Deleting a worktree and its session from the TUI left the agent's tmux session and the whole process tree under it alive, consuming resources and pointed at a directory that had just been removed. The session stayed invisible to the dashboard, so the only way to notice was to run tmux ls or watch the machine get slower.

The delete path killed its two sessions by different mechanisms. The shell session was killed by its tmux session ID, which always works. The agent session went through sesSvc.Stop, which rebuilds the session name from (project, branch) and looks it up in tmux list-sessions. When that lookup missed, Stop returned ErrSessionNotFound, the caller discarded it with _ =, and the worktree was force-deleted anyway.

The rebuilt name misses for two independent reasons. Stop derives it from Item.Branch, which carries the display branch — a value items.go deliberately lets diverge from the identity branch the session was named after. Stop also hardcodes an empty profile, so under an active profile it searches for myapp-feat while the session is really work-myapp-feat.

Both sessions are now killed by the tmux session ID the item already carries, which is immune to both hazards because it never reconstructs a name, and a failed kill surfaces as an error instead of letting the worktree be deleted out from under a live process. This matches what confirmDeleteAgent and confirmDeleteShell already did.

Deleting a worktree and its session from the TUI left the agent's tmux
session and the whole process tree under it alive, consuming resources and
pointed at a directory that had just been removed. The session stayed
invisible to the dashboard, so the only way to notice was to run tmux ls
or watch the machine get slower.

The delete path killed its two sessions by different mechanisms. The shell
session was killed by its tmux session ID, which always works. The agent
session went through sesSvc.Stop, which rebuilds the session name from
(project, branch) and looks it up in tmux list-sessions. When that lookup
missed, Stop returned ErrSessionNotFound, the caller discarded it with
`_ =`, and the worktree was force-deleted anyway.

The rebuilt name misses for two independent reasons. Stop derives it from
Item.Branch, which carries the display branch — a value items.go
deliberately lets diverge from the identity branch the session was named
after. Stop also hardcodes an empty profile, so under an active profile it
searches for myapp-feat while the session is really work-myapp-feat.

Both sessions are now killed by the tmux session ID the item already
carries, which is immune to both hazards because it never reconstructs a
name, and a failed kill surfaces as an error instead of letting the
worktree be deleted out from under a live process. This matches what
confirmDeleteAgent and confirmDeleteShell already did.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@xico42
xico42 merged commit 75177ee into main Jul 16, 2026
7 checks passed
@xico42
xico42 deleted the fix/deleting-session branch July 16, 2026 21:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant