Session-scoped terminals: switch tabs on worktree/session select#290
Open
kirich1409 wants to merge 9 commits intomainfrom
Open
Session-scoped terminals: switch tabs on worktree/session select#290kirich1409 wants to merge 9 commits intomainfrom
kirich1409 wants to merge 9 commits intomainfrom
Conversation
…ting - MainFeature.Action.newRemoteSession gains optional session: RemoteSession? parameter - Reducer looks up tabs by remoteSessionID before creating a new one; if found, focuses it - MainFeature.State.init respects a non-empty tabs argument instead of always creating default tab - AppFeature.openRemoteSession passes the session through to MainFeature - TerminalFeature.start adds a catch handler so gRPC connection errors update connectionState instead of leaking as unhandled throws (fixes test isolation) - SessionSwitchTerminalTests: all 6 tests now pass
newClaudeSession now checks for an existing tab with matching worktreeID before creating a new one. New tabs created via orchestrator(.newSession) receive worktreeID from the current worktree selection so future lookups can find them. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MainFeature now intercepts selectWorktree action and focuses the tab bound to the selected worktree (worktreeID match). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Shell tabs (newShellTab, newShellSession) now receive worktreeID from selectedWorktreeID. Default tab is bound to the main worktree when its path matches the project root — both eagerly (on shell session start) and lazily (on selectWorktree with path fallback). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
selectWorktree now auto-opens a shell in the worktree directory when no existing tab is found, instead of silently doing nothing. This gives every worktree its own terminal on first selection. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
selectWorktree Fallback B now creates the tab synchronously before sending the shell session effect — no race between effect dispatch and test assertion. orchestrator(.newShellSession) skips tab creation when a tab for the current worktree already exists. New tests: selectWorktreeFocusesExistingTab, selectWorktreeAutoCreatesShell. All 48 tests green. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TabBarView now accepts sessionFilter: UUID? and shows only tabs whose worktreeID matches the selected worktree. AppRootView passes worktree.selectedWorktreeID as the filter, so each worktree/session sees only its own set of terminals. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
newShellSession no longer calls _projectOpened when workingDirectory is inside the current project (worktree path). Fixes bug where every worktree selection added the worktree as a Recent Project entry. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Restore currentProject == nil guard in orchestrator(.newSession) (sed replacement was too broad and broke the Claude session path) - Add two unit tests for the isKnownWorktree guard logic: known worktree path → guard true → registration skipped unknown path → guard false → registration allowed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
Implements session-scoped terminal navigation and fixes duplicate tab creation.
Problem
Changes
Model (
Tab)Tab.remoteSessionID: String?— links tab to cloud session (dedup key)Tab.worktreeID: UUID?— links tab to local worktree (now populated everywhere)Reducer (
MainFeature)selectWorktreeintercept — focuses existing tab for that worktree; if none exists, auto-creates a shell session and tab synchronouslyselectWorktreenow auto-opens a shell when switching to a worktree with no open terminalnewRemoteSession(server:session:)looks up existing tab byremoteSessionIDbefore creating a new onenewClaudeSessionlooks up existing tab byworktreeIDworktreeIDpopulated everywhere — shell tabs, default tab bound to main worktreenewShellSessionskips_projectOpenedfor known worktree paths (isKnownWorktreecheck), preventing worktrees from appearing in Recent ProjectsUI (
TabBarView)sessionFilter: UUID?parameter — shows only tabs for the selected worktree/sessionAppRootViewpassesstore.worktree.selectedWorktreeIDas filterTest plan
SessionSwitchTerminalTests— 10 TCA/unit tests (50 total, all green):remoteSessionID; reopen → focus existing, no duplicateselectWorktree→ focus existing tab; auto-create shell when no tabisKnownWorktreetrue for worktree paths; false for unknown pathsxcodebuild test— 50/50 passedswiftlint lint --strict— 0 violations🤖 Generated with Claude Code