-
-
Notifications
You must be signed in to change notification settings - Fork 39
ScarfCore Package
ScarfCore is the local SwiftPM package at scarf/Packages/ScarfCore/ that holds every piece of code shared between the Mac (scarf) and iOS (scarf mobile) targets — models, services, view-models, the transport protocol, the ACP client, parsers, and security helpers. v2.5 extracted it from the Mac target so iOS could reuse it byte-for-byte instead of duplicating logic.
If you're touching a service, model, or parser that needs to work on both platforms, that's ScarfCore's job. If you're touching something that only compiles on one platform (Sparkle, SwiftTerm, Citadel, KeychainSSHKeyStore), it lives in the per-platform target instead.
Packages/
ScarfCore/ # platform-agnostic core, no UI
Sources/ScarfCore/
ACP/ # ACP wire types + ProcessACPChannel + SSHExecACPChannel
Models/ # HermesSession, HermesMessage, HermesConfig, ProjectEntry, etc.
Parsing/ # CronScheduleFormatter, HermesSkillsHubParser
Persistence/ # Codable structs for JSON sidecars
Security/ # OnboardingViewModel, IOSServerConfig, OnboardingState
Services/ # HermesDataService, ProjectDashboardService, SkillsScanner, …
ServerContext/ # ServerContext + ServerTransport protocol + factory
Transport/ # LocalTransport (Mac), SSHTransport (Mac remote)
ViewModels/ # IOSDashboardViewModel, IOSCronViewModel, SkillsViewModel, …
Tests/ScarfCoreTests/ # 163 tests across 12 suites — runs on Linux CI
ScarfIOS/ # iOS-only glue
Sources/ScarfIOS/
CitadelServerTransport.swift # ServerTransport via Citadel SSH (replaces system ssh)
KeychainSSHKeyStore.swift # iOS Keychain-backed Ed25519 key persistence
CitadelSSHService.swift # Pure-Swift keypair gen + connection probes
ScarfDesign/ # rust palette, ScarfFont, ScarfSpace, ScarfRadius, components
Sources/ScarfDesign/ # See: Design System
Both scarf (Mac target) and scarf mobile (iOS target) declare local SPM dependencies on the three packages via XCLocalSwiftPackageReference entries in project.pbxproj. No registry, no fetch step — they live next to the app code in the repo.
Models — plain Codable Sendable structs. HermesSession, HermesMessage, HermesSkill, HermesConfig, HermesProject, ProjectEntry, ProjectDashboard, IOSServerConfig, ServerID, etc. No reference types.
Services — actor-isolated or Sendable struct services that read/write Hermes state through a transport. See Core Services for the catalog.
ViewModels — @Observable @MainActor classes that drive feature UI. Mac and iOS both consume IOSDashboardViewModel, IOSCronViewModel, SkillsViewModel, IOSSettingsViewModel, RichChatViewModel, etc. (The IOS prefix is historical — the view-models are platform-agnostic now; renaming them is a v2.6 cleanup item.)
Transport — ServerTransport protocol declaring the I/O surface every backend implements. LocalTransport (local file ops + Process exec) and SSHTransport (system ssh via OpenSSH) live here because they don't pull in iOS-specific dependencies. CitadelServerTransport lives in ScarfIOS because Citadel is iOS-only.
ACP — ACPChannel protocol + ACPRequest/ACPResponse/ACPNotification types + ProcessACPChannel (Mac-spawned subprocess) + SSHExecACPChannel (iOS SSH-tunneled JSON-RPC). Both channels surface the same async event stream.
Parsing — HermesSkillsHubParser (Rich-table parser for hermes skills browse/search output), CronScheduleFormatter (cron string → English).
Security / Onboarding — OnboardingViewModel (state machine for the iOS onboarding flow), OnboardingState enum, IOSServerConfig (host/user/port/binaryHint shape).
iOS-specific glue that can't compile on macOS:
-
CitadelServerTransport—ServerTransportimplementation via Citadel 0.12.x. Pure-Swift SSH; nosshsubprocess dependency. DrivesexecuteCommandStreamdirectly so stdout survives non-zero exits, prependsPATH=$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin:$PATHso non-interactive sessions resolvehermes. -
KeychainSSHKeyStore— Ed25519 keypair persistence in the iOS Keychain. Servicecom.scarf.ssh-key, accountserver-key:<UUID>, accessibilityThisDeviceOnly. WrapsSecItemCopyMatching/SecItemAdd/SecItemDeletebehind a typed API. -
CitadelSSHService— pure-Swift keypair generation + connection probes for the onboarding flow.
Tokens + components. See Design System.
Security.framework is available on both Mac and iOS but the Keychain item attributes that make sense differ between platforms. Mac uses kSecClassGenericPassword with file-protection levels; iOS uses kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly to opt out of iCloud Keychain sync (which doesn't exist on Mac in the same form). Trying to share one type across both led to a parameter explosion.
Mac doesn't need an in-app SSH key store because it uses the system ~/.ssh/ directory and ssh-agent. iOS does need one because there's no system SSH agent. The asymmetry is the reason the type lives in ScarfIOS and not ScarfCore.
- Decide the service is platform-agnostic (no
AppKit/UIKit/WatchKitimports, noProcess()/NSWorkspace, no Citadel-specific types). If any of those creep in, the service belongs in the platform target instead. - Add a Swift file under
Packages/ScarfCore/Sources/ScarfCore/Services/. - Take a
ServerContextininit, decide isolation (actorfor stateful,Sendable structfor stateless), expose async public methods, route I/O throughcontext.transport. - Add a corresponding row to Core Services so the wiki catalog stays current.
- Write a
Tests/ScarfCoreTests/<service>Tests.swiftsuite. Tests run on Linux CI, so no Foundation-mac-only APIs.
The current breakdown: 30+ services, 12 test suites, 163 tests, three consecutive green runs as of v2.5.0.
Pre-v2.5, services lived in scarf/scarf/Core/Services/ and the iOS target either duplicated them or imported them via a brittle target membership trick. The duplication path drifted (project context block subtly differed between platforms); the trick path didn't survive Swift 6 strict concurrency. Pulling everything into a proper SPM package solved both: one source of truth, one set of tests, both targets import ScarfCore.
The split between ScarfCore (platform-agnostic) and ScarfIOS (iOS glue) keeps the package builds clean — ScarfCore compiles on Linux without dragging Citadel into the dependency tree.
- Architecture Overview — high-level layering.
- Core Services — service catalog.
-
Transport Layer —
ServerTransportprotocol details. - Design System — ScarfDesign package reference.
- Adding a Service — full recipe for new shared services.
Last updated: 2026-04-25 — Scarf v2.5.0 (initial publication)
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
- Contributing
- Wiki Maintenance
- ScarfGo Roadmap (dev reference)
Release History
Legal & Support