cmux NEXT: terminals opened from an agent chat or Cmd-N start in the exact folder you work in

Merged
AU
17d ago
+116-19

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.cwd is 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 in AcpmuxPaneSessions), 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 strip
    • PanePlacementRouting.aimed
    • PaneController.newTerminalTab
    • TabLifecycle (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- and split-inherit-working-directory = false still 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.py at head 0aa414ee reports no new violations.
  • New test: CmuxNext cmux-ci step at head 0aa414ee: AgentPaneTerminalFolderTests passes. Run daf4912318f37ca30f171bf8 had 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: its palette.newAgentChat CLI-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 on origin == .user; every other edit only picks a folder value). Likely a flake; not yet proven.
  • Tagged build: fleet job 86c8af048caa72bac607be8e at 0aa414ee, tag 23795-chat-terminal-inherits-folder, published.
  • Not run: GUI dogfood of each path in the tagged app; pwd against 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