🐛 fix: close companion pane immediately when Lazygit/Yazi exits#82
🐛 fix: close companion pane immediately when Lazygit/Yazi exits#82
Conversation
When Lazygit or Yazi ran in the companion pane and the user quit the
process (e.g. `q` in lazygit), the Ghostty surface-close notification
was handled by the pane's TerminalAreaViewController as a dead tmux
session, so it rendered the empty state ("No active session") inside
the pane. The pane stayed docked with the old title, un-closable
without relaunching Mori.
Add an onSurfaceExited hook on TerminalAreaViewController that, when
set, replaces the default empty-state/auto-reconnect path. The
CompanionToolPaneController wires it to a new onToolExited callback
that AppDelegate uses to close the pane and return focus to the main
terminal — matching the manual ⌘G toggle behavior.
Fixes #79.
Assisted-by: claude-code:claude-opus-4-7
Ghostty's embedded API at vendor/ghostty/src/apprt/embedded.zig force- sets `wait-after-command = true` whenever a command is passed, so on child exit it would render "Process exited. Press any key to close." inside the companion pane and wait for user input before firing the surface-close callback. That's the press-any-key delay users were hitting after `q` in lazygit. Handle `GHOSTTY_ACTION_SHOW_CHILD_EXITED` in Mori's action callback: look up the surface's userdata, post a `.ghosttySurfaceDidClose` notification, and return true — which suppresses ghostty's fallback terminal message. The existing close handler then tears the surface down immediately, so the pane collapses with no keypress. Refine the changelog entry to reflect the new behavior. Assisted-by: claude-code:claude-opus-4-7
fe256ff to
6ded54f
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fe256ff0ef
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ) | ||
| } | ||
| } | ||
| return true |
There was a problem hiding this comment.
Handle child-exit only for active terminal surface
Returning true here suppresses Ghostty’s built-in child-exit UI for every surface, including cached/background surfaces that are not currently attached. TerminalAreaViewController.handleSurfaceClosed only acts when the notification matches currentSurface (see the currentSurface/userdata guards at Sources/Mori/App/TerminalAreaViewController.swift:525-531), so exits from non-current surfaces are dropped and their dead views remain cached. When users later switch back to that worktree/tool, they can land on a stale blank surface with no reconnect/close flow.
Useful? React with 👍 / 👎.
The previous fix intercepted GHOSTTY_ACTION_SHOW_CHILD_EXITED for every surface but only cleaned up when the exit matched the current surface. Surfaces cached but not currently attached (e.g. a background companion pane) stayed in the cache pointing at a dead process, so the next attach would bind to a surface that ghostty had already torn down. Split the notification handler: when userdata matches currentSurface, run the existing teardown path; otherwise evict the matching entry from the surface cache via TerminalSurfaceCache.removeByUserdata. The notification fans out to every TerminalAreaViewController; each walks its own cache and exactly one owns the exited surface. Comment the handler so a future reader does not try to "optimize" by routing it. Assisted-by: claude-code:claude-opus-4-7
|
Addressed in bc487f9. Split Fan-out to every Diff: bc487f9 |
Summary
Fixes #79. The right-side Git / Files pane now closes immediately when the embedded tool exits, instead of leaving a blank panel that could only be dismissed by restarting Mori.
GHOSTTY_ACTION_SHOW_CHILD_EXITEDin Mori's action callback — returningtruesuppresses ghostty's fallback "Process exited. Press any key to close." message, and we post.ghosttySurfaceDidCloseourselves so the surface tears down with no keypress.onSurfaceExitedhook onTerminalAreaViewController;CompanionToolPaneControllerwires it to a newonToolExitedcallback thatAppDelegateuses to collapse the pane and return focus to the main terminal (matches the manual⌘Gtoggle path).Root cause
vendor/ghostty/src/apprt/embedded.zig:533force-setswait-after-command = truewhenever a command is passed toghostty_surface_new, so on child exit ghostty rendered the "press any key" message and blocked. Theclose_surface_cbonly fired after the keypress — the pane had no signal to close on its own.Test plan
swift build -c release --product Morimise run test— all packages passTmux → Open Lazygit→ pressq→ pane closes immediately, no keypress required, focus returns to main terminal🤖 Generated with Claude Code