Skip to content

Conversation

@ethanndickson
Copy link
Member

Fixes the "Open Terminal" button for SSH workspaces, which was failing with ENOENT errors because it tried to open a local path that doesn't exist locally.

Changes

The IPC handler now accepts workspaceId instead of workspacePath, looks up the workspace metadata, and spawns the appropriate terminal:

  • SSH workspaces: Spawns a local terminal that runs ssh -t <host> 'cd <path> && exec $SHELL'
    • Supports SSH options: port (-p), identity file (-i)
    • Works on all platforms: macOS (Ghostty, Terminal.app), Windows (cmd), Linux (9+ terminal emulators)
  • Local workspaces: Works exactly as before (spawn terminal with cwd set)

All callers updated to pass workspaceId instead of namedWorkspacePath.

Testing

  • make typecheck passes ✅
  • For local workspaces: Should work exactly as before
  • For SSH workspaces: Should spawn a local terminal that SSHs in and opens in the workspace directory

Generated with cmux

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ethanndickson ethanndickson added this pull request to the merge queue Nov 12, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Nov 13, 2025
@ethanndickson ethanndickson added this pull request to the merge queue Nov 13, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Nov 13, 2025
- Change IPC handler to accept workspaceId instead of workspacePath
- Look up workspace metadata to determine if SSH or local
- For SSH: spawn local terminal that runs 'ssh -t host "cd path && exec $SHELL"'
- For local: spawn terminal with cwd set (existing behavior)
- Support SSH options: port (-p), identity file (-i)
- Handle all platforms: macOS (Ghostty, Terminal.app), Windows (cmd), Linux (9+ terminal emulators)
- Update all callers to pass workspaceId instead of path

Generated with `cmux`
Fixes P1 issue where nested single quotes in the remote command would break
Terminal.app's AppleScript parsing. Now uses proper shell escaping: 'foo'\''bar'

Generated with `cmux`
Ghostty on macOS requires: open -n -a Ghostty --args --command="ssh ..."
instead of passing SSH args directly.

Generated with `cmux`
Use multi-line AppleScript with activate and end tell:
tell application "Terminal"
activate
do script "ssh ..."
end tell

Generated with `cmux`
The isSSH check already validates runtimeConfig.type === "ssh",
so the redundant check in the if condition is unnecessary.

Generated with `cmux`
Added isSSHRuntime() type guard to RuntimeConfig that provides
proper type narrowing, replacing manual type === 'ssh' checks.

Generated with `cmux`
The previous commit referenced isSSHRuntime but the function
wasn't actually added to the file.

Generated with `cmux`
Applied isSSHRuntime() to RuntimeBadge, GitStatusStore, and ipcMain
to replace manual type === 'ssh' checks with type-safe guards.

Generated with `cmux`
Store config.type === 'ssh' check in isSSH constant at the start
of openTerminal() to avoid multiple type checks throughout.

Generated with `cmux`
Use the type guard function instead of manual type === 'ssh' check
for consistency with the rest of the codebase.

Generated with `cmux`
The config parameter in openTerminal has a different shape than
RuntimeConfig (workspacePath vs srcBaseDir), so we can't use the
isSSHRuntime type guard here.

Generated with `cmux`
After rebase, getAllWorkspaceMetadata() is now async.

Generated with `cmux`
@ethanndickson ethanndickson added this pull request to the merge queue Nov 13, 2025
Merged via the queue into main with commit 3a00c83 Nov 13, 2025
14 checks passed
@ethanndickson ethanndickson deleted the remote-terminal branch November 13, 2025 02:02
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.

2 participants