cmux NEXT: terminals opened from an agent chat or Cmd-N start in the exact folder you work in
Merged
AU
17d ago+116+116+012345678901234567890123456789-19-19-01234567890123456789
Summary
Every new terminal opened from cmux NEXT now starts in the exact folder you work in: the focused terminal's folder, or the focused agent chat's folder.
Before, a terminal opened from an agent chat started in ~ or in some other terminal's folder:
- Cmd-D and Cmd-T from a chat
- Cmd-N, in classic (
tabs.terminalFirst) mode too - the chat header's Terminal and Split Down buttons
- a docked chat's strip terminal
- a shell block's Open in terminal
Cmd-N also never inherited the folder of a focused terminal.
Cause
- The daemon records no folder for an agent chat tab (
TabModel.cwdis always nil for it). - Its new-terminal resolver (
new_terminal_cwd.rs) only looks at PTY tabs. - Every app path that falls back to "the selected tab's cwd" got nil, and only one path (Ctrl-` in the chat's own pane) asked the chat page for its folder.
Fix
AgentPaneModel.terminalFolder: the chat's exact folder. It is the folder acpmux reported for the chat's session (_acpmux/attach/session/new, already kept inAcpmuxPaneSessions), read synchronously so a terminal made in the key's frame gets it. Agent-home stays nil.AgentTabStore.terminalFolder(of:): returns that folder only for a chat on this Mac's daemon, when the folder exists here. A Cloud, SSH or peer chat's path never reaches this Mac's daemon.NewTerminalStart.folder(of:services:): one resolver: a terminal's folder, or a chat's exact folder. These paths use it:PaneHandlers.split, including the docked-chat stripPanePlacementRouting.aimedPaneController.newTerminalTabTabLifecycle(classic Cmd-T new workspace, docked strip)- the shell block's Open in terminal (
blankChatHandler) - the New Tab page beside a chat
- the header's Terminal fallback
- Cmd-N (
WorkspaceSpawn.inheritedCwd)
- Cmd-N folder precedence: the explicit folder, then the space's own default folder, then the inherited folder, then the daemon's default. It applies only on this Mac.
- Ghostty's
window-,tab-andsplit-inherit-working-directory = falsestill start the terminal in~.
Related: https://github.com/manaflow-ai/cmux/pull/22230 covers only Ctrl-`, by asking the page asynchronously. This PR covers every path from the native session folder.
Changelog
- Fixed: A terminal opened from an agent chat (split, new tab, Cmd-N, the chat's Terminal button, a shell block's Open in terminal) starts in the chat's folder, and Cmd-N starts in the focused terminal's folder.
Testing
AgentPaneTerminalFolderTests(CmuxNextAgentPaneTests): the folder a restored chat and a new chat report, and none for agent-home.
Observed / Not run
- Static checks:
scripts/cmux-next/prepush-gate.pyat head 0aa414ee reports no new violations. - New test: CmuxNext
cmux-cistep at head 0aa414ee:AgentPaneTerminalFolderTestspasses. Rundaf4912318f37ca30f171bf8had 1384 passed and 12 failed; its rerun had 1380 passed and 16 failed. - Base comparison: the same step at the base ae0085bef had 1387 passed and 8 failed, all base reds:
BackgroundAccessoryPolicyTests,ClassicUpgradeSimulationTests,ClassicUpgradeHugeSimulationTests,CmdNRowSlotTests,DebugPaletteCaptureTests,PalettePickerSourcesTests,FolderViewMemoryTests,PageWebViewDebugHoverTests. The other head failures changed between the two head runs (latency and scroll-cost limits on a loaded worker). AgentChatFromHomeTests: itspalette.newAgentChatCLI-without-focus case failed in both head runs, but this change leaves CLI-origin invocations exactly as they were (the new Cmd-N inheritance is gated onorigin == .user; every other edit only picks a folder value). Likely a flake; not yet proven.- Tagged build: fleet job
86c8af048caa72bac607be8eat 0aa414ee, tag23795-chat-terminal-inherits-folder, published. - Not run: GUI dogfood of each path in the tagged app;
pwdagainst the chat's folder still needs a person. - Not run: red-first run of the new test on the base. It reads a property this fix adds.
No capture: the change is the folder a new terminal's shell starts in; no pixels change.
🤖 Generated with Claude Code