-
-
Notifications
You must be signed in to change notification settings - Fork 43
Sidebar and Navigation
Navigation state lives in a single @Observable coordinator. The sidebar is a List bound to it; feature views observe it. There is no router, no NavigationStack stack tracking, no global state library — just one source of truth for "where am I?".
AppCoordinator.swift holds three pieces of state:
-
selectedSection: SidebarSection— defaults to.dashboard. -
selectedSessionId: String?— optional deep link into the Sessions browser. -
selectedProjectName: String?— optional deep link into a project dashboard.
It is injected at the root of each window via .environment(coordinator) in ContextBoundRoot so any view can read it with @Environment(AppCoordinator.self) private var coordinator.
Each Scarf window has its own AppCoordinator — selection in one window doesn't bleed into another. The coordinator is paired with one ServerContext for the lifetime of the window.
SidebarSection (AppCoordinator.swift) is the source of truth for every sidebar item. Each case has a rawValue (display name) and an icon (SF Symbol name). 22 cases grouped into 5 sidebar headers (the order is hardcoded in SidebarView.swift):
| Section | Icon |
|---|---|
| Dashboard | gauge.with.dots.needle.33percent |
| Insights | chart.bar |
| Sessions | bubble.left.and.bubble.right |
| Activity | bolt.horizontal |
| Section | Icon |
|---|---|
| Projects | square.grid.2x2 |
Projects has its own header — not a Manage sub-item — because per-project work (Dashboard / Sessions / Site / Slash Commands tabs, template install) is a top-level workflow surface in v2.5.
| Section | Icon |
|---|---|
| Chat | text.bubble |
| Memory | brain |
| Skills | lightbulb |
| Section | Icon |
|---|---|
| Platforms | dot.radiowaves.left.and.right |
| Personalities | theatermasks |
| Quick Commands | command.square |
| Credential Pools | key.horizontal |
| Plugins | app.badge.checkmark |
| Webhooks | arrow.up.right.square |
| Profiles | person.2.crop.square.stack |
| Section | Icon |
|---|---|
| Tools | wrench.and.screwdriver |
| MCP Servers | puzzlepiece.extension |
| Messaging Gateway | antenna.radiowaves.left.and.right |
| Cron | clock.arrow.2.circlepath |
| Health | stethoscope |
| Logs | doc.text |
| Settings | gearshape |
The Gateway item's displayName is "Messaging Gateway" — disambiguates from the v2.3 Tool Gateway (Nous Portal subscription routing) which is a Health-tab surface, not its own sidebar item. The enum case is still .gateway and the persisted state file path (~/.hermes/gateway_state.json) is unchanged.
SidebarView.swift is a List with hardcoded Section headers. Selection is two-way bound to coordinator.selectedSection:
List(selection: $coordinator.selectedSection) {
Section("Monitor") { … }
Section("Projects") { … }
Section("Interact") { … }
Section("Configure") { … }
Section("Manage") { … }
}
.listStyle(.sidebar)There is no search bar, no collapsible-section state to persist — every section is always expanded.
ContentView's detailView is a single switch coordinator.selectedSection over every SidebarSection case, returning the right view for the current selection. New features add one case here (see Adding a Feature Module).
Each window is bound to one ServerContext and one AppCoordinator. The window menu (and ⌘1…⌘9 keyboard shortcuts) opens additional windows for other servers — see Keyboard Shortcuts. Closing a window destroys its coordinator; reopening reads the section back from defaults.
ScarfGo uses a different model — a 5-tab TabView rather than a sidebar. The tabs (Dashboard | Projects | Chat | Skills | System) are wrapped in their own NavigationStacks so push navigation (Cron editor, Memory detail, Project detail, Settings) stays scoped to the tab. Cross-tab signalling (Dashboard row → Chat tab resume, Project Detail → in-project chat handoff, notification deep-link → Chat) flows through ScarfGoCoordinator.
.tabViewStyle(.sidebarAdaptable) is wired so the system can switch to a sidebar layout on larger devices — but as of v2.5 the iOS target ships iPhone-only (TARGETED_DEVICE_FAMILY = 1, SUPPORTS_MACCATALYST = NO, SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO). iPad polish is on the ScarfGo Roadmap but not in scope for v2.5.
The Mac sidebar's "System" / advanced sections collapse into the iOS System tab (server identity, Memory link, Cron link, Settings link, Disconnect / Forget). See Platform Differences for the full Mac↔iOS feature matrix.
Last updated: 2026-04-25 — Scarf v2.5.0 (audit pass: 5 sidebar groups not 4, 22 cases not 23, Projects own group, Messaging Gateway display name, iPhone-only iOS target)
Wiki edited via the local .wiki-worktree/ clone. See Wiki Maintenance for the workflow. Last sync: 2026-04-20.
Getting Started
ScarfGo (iOS)
User Guide
- Dashboard
- Insights & Activity
- Chat
- Slash Commands
- Memory & Skills
- Projects & Profiles
- Project Templates
- Template Catalog
- Template Ideas
- Platforms / Personalities / Quick Commands
- Servers & Remote
- MCP, Plugins, Webhooks, Tools
- Gateway / Cron / Health / Logs
Architecture
- Overview
- Core Services
- Design System
- Data Model
- Transport Layer
- ScarfCore Package
- Sidebar & Navigation
- ACP Subprocess
Developer Guide
Reference
Troubleshooting
Contributing
Release History
Legal & Support
Unsorted