Run terminal surfaces under zmx via a Ghostty command-wrapper#368
Merged
Conversation
…ull integration Surfaces used to be launched by handing Ghostty `command = "zmx attach <id>"`, which overrode the user's `command` config and made Ghostty's shell detection and integration target zmx instead of the real shell. The fallout: OSC 7 cwd reporting stopped working unless the user's own rc emitted it (so split cwd inheritance went stale), a custom `command` (e.g. nushell) was ignored, and the macOS login(1) treatment was lost. Add a `command-wrapper` option to GhosttyKit (a small out-of-tree patch applied to the pinned submodule at build time; the pin is never moved and no fork is created). The wrapper's argv is prepended to the command Ghostty resolves after shell resolution, shell integration, and the macOS login(1) wrapping, so the resolved shell runs as a child of the wrapper. Supacode now leaves `command` unset for interactive surfaces and instead passes `zmx attach <id>` as the wrapper. Ghostty resolves and integrates the user's real shell exactly as it would without zmx (honoring `command` and `shell-integration` config), login(1) preserves the integration env via `-p`, and zmx wraps the whole thing for session persistence. Explicit commands (scripts) keep wrapping the command string as before. The global `shell-integration = none` override is dropped, since Ghostty now integrates the real shell rather than the zmx command. scripts/build-ghostty.sh applies patches/*.patch to the submodule working tree before building and reverts on exit, so the submodule stays clean and pinned to upstream. A patch that no longer applies fails the build loudly.
# Conflicts: # supacodeTests/ZmxClientTests.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Terminal surfaces run under zmx for session persistence. The surface command was set to
zmx attach <id>, which had two side effects:commandconfig, so a custom default shell (e.g.command = /opt/homebrew/bin/nu) was ignored and$SHELLran instead (Closes Using custom shell in Supacode #362).zmxinstead of the real shell, so OSC 7 working-directory reporting only worked if the user's own shell config emitted it. When it did not, the tracked pane cwd went stale and new splits inherited the wrong directory.Fix
Add a
command-wrapperoption to GhosttyKit and use it instead of overridingcommand:commandunset and passzmx attach <id>as acommand-wrapper. Ghostty resolves and integrates the real shell (or the user's configuredcommand), applies the macOSlogin(1)wrapping, then the wrapper argv is prepended to the result. The shell behaves exactly as it would without zmx, and zmx wraps the whole thing for persistence.disable_shell_integration, preserving their self-managed OSC 133 mechanics.The GhosttyKit change ships as an out-of-tree patch (
patches/ghostty-command-wrapper.patch) applied to the pinned submodule at build time byscripts/build-ghostty.shand reverted on exit. The submodule pin tracks upstream; there is no fork. The feature is generic and upstreamable.Result
command(e.g. nushell) is honored under zmx. Fixes Using custom shell in Supacode #362.Notes
shell-integration = noneoverride is removed, since Ghostty now integrates the real shell rather than the zmx command.wait-after-commandis left at Ghostty's default for interactive surfaces, so a pane closes on shell exit (matching stock Ghostty).