Add remote SSH repositories and worktrees#407
Merged
Conversation
Brand the per-repository settings key with the remote host so two hosts that point at the same path no longer share settings, and so a remote repository never reads or writes a local supacode.json at that path on the local disk. The branded key mirrors RepositoryLocation.id, leaving a local repository at the same path on its own bare-path key. RemoteHost gains the id-bearing authority, threaded through every settings call site and the repository settings feature (which now carries its host through the settingsChanged delegate). Stop collapsing a multi-worktree remote to a single synthetic main when the worktree listing throws transiently: that case now surfaces a load failure and keeps the placeholder so the next reload re-lists in full, while a genuinely empty listing still falls back to a synthetic main. Distinguish a reachable host with a missing path from an unreachable one: classifyRemotePath reports a dedicated missing kind so the failure names the path instead of blaming the connection.
Remote repos were pinned below the local ones and excluded from the reorder machinery, so dragging them did nothing. Treat every repository uniformly in `orderedRepositoryIDs()`: the persisted sidebar order wins and local roots and host-keyed remote ids interleave freely, so a drag sticks across recompute and reload. The sidebar structure now renders in that single order and exposes every repo id as reorderable. Open / Reveal in Finder target local paths that an SSH host can't serve, so disable them for a remote row across the sidebar context menu, the toolbar Open menu, and the Worktrees menu, and reject them in `openWorktreeEffect` so a hotkey can't reach the workspace client.
A failed remote repository's id is a `remote://` authority, not a local path, so deriving the window title name from a file URL mangled it. Prefer the placeholder repository's resolved name, keeping the file-URL leaf only for a local failure that has no placeholder.
…ositories # Conflicts: # supacode/Features/Repositories/Reducer/RepositoriesFeature.swift # supacode/Features/Repositories/Views/WorktreeDetailView.swift # supacode/Features/Terminal/Models/WorktreeTerminalState.swift # supacodeTests/AgentPresenceFeatureTests.swift
The prompted worktree-creation duplicate check and the whole rename-branch flow (name validation, availability, and the rename itself) resolved the injected local git client unconditionally, so for a remote repository they ran against the local machine instead of the SSH host. Route both through a host-aware client: a `gitClient(for: repository)` overload for the creation duplicate check, and a host carried on the rename prompt's state.
…ositories # Conflicts: # supacode/Features/Terminal/Models/WorktreeTerminalState.swift # supacodeTests/WorktreeTerminalManagerTests.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.
Summary
Adds first-class support for repositories and worktrees that live on a remote SSH host, alongside the existing local repositories. A remote repository is identified by a
RemoteHostand a host-keyed branded id (remote://[user@]host[:port]/path); local repositories keep their path-based ids. The repositories feature, clients, terminal, settings, and menus all route through this branded local/remote identity.What's included
RemoteHostsettings model ([user@]host[:port], worktree base path) and an SSH command/transport layer that runs commands on the host.RepositoryID/WorktreeIDcarry local-vs-remote provenance so nothing has to re-parse a path to know where a repo lives.worktree add/worktree remove, fetch, and remote info all execute on the host. Archive/delete scripts run on the remote host viassh -tt.remote://id through a file URL.Notes / intentional asymmetries
Testing
make build-app: Build Succeeded.make test: full suite passes (includes new coverage for remote reorder, interleaved ordering, the remote-Open no-op, and the failed-remote window title).make check: format + lint clean.Closes #65