Status: Accepted Date: 2026-04-13
Context: The macOS client has complex state: multiple terminal tabs, server connections, git worktrees, agent orchestration. State changes flow between features (closing a tab affects the tab bar, the session registry, and potentially the server connection).
Decision: Use The Composable Architecture (TCA) by Point-Free as the application architecture. Features are modeled as TCA reducers that compose hierarchically.
Alternatives considered:
- Vanilla SwiftUI + ObservableObject — simpler for small apps, but state coordination between features becomes ad-hoc (notifications, delegates, shared singletons). Testing requires mocking at the SwiftUI layer.
- MVVM — standard but doesn't provide a composition mechanism for cross-feature state. Each ViewModel is independent; coordinating between them requires a separate coordination layer.
- Redux-like (custom) — similar benefits to TCA but without the library's testing infrastructure, dependency injection, and effect management.
Consequences:
- Composable state:
MainFeaturescopes intoAgentOrchestrator,WorktreeManager,TabFeature,ServerListFeature - Unidirectional data flow: state down, actions up
- Testable: reducers are pure functions, effects are injectable
- Reducer ordering matters:
MainFeature.ReducebeforeTabFeaturescope allows intercepting close actions AsyncStream<TerminalEvent>integrates naturally as TCA Effect source- Trade-off:
@MainActor+Sendablerequirements create friction with TCA'sDependencyValues(hence singletons for engine/registry viasharedTerminalEngineBox,sharedTerminalRegistry) - Steeper learning curve for contributors unfamiliar with TCA