diff --git a/Home.md b/Home.md index bba40bd..1005154 100644 --- a/Home.md +++ b/Home.md @@ -2,18 +2,20 @@ A native macOS companion app for the [Hermes AI agent](https://github.com/hermes-ai/hermes-agent). Full visibility into what Hermes is doing, when, and what it creates — across one local install or many remote ones. -**Latest release:** [v2.2.1](https://github.com/awizemann/scarf/releases/tag/v2.2.1) (v2.3.0 queued — bump this line after `scripts/release.sh` completes) +**Latest release:** [v2.5.0](https://github.com/awizemann/scarf/releases/tag/v2.5.0) — ScarfGo iOS companion + Mac Sessions parity. Bump this line after `scripts/release.sh` completes the v2.5 publish in Phase G. +**Latest mobile:** ScarfGo public TestFlight — see [ScarfGo](ScarfGo) for the invite link. **Targets Hermes:** v0.10.0 (v2026.4.16) — Tool Gateway features require this **Available in:** English, Simplified Chinese (zh-Hans), German (de), French (fr), Spanish (es), Japanese (ja), Brazilian Portuguese (pt-BR). See [Localization](Localization). ## Quick links -- [Installation](Installation) — download, first launch, system requirements +- [Installation](Installation) — download, first launch, system requirements (Mac) +- **[ScarfGo](ScarfGo)** — the iPhone companion (public TestFlight from v2.5) +- [Platform Differences](Platform-Differences) — Mac vs iOS feature matrix - [First Run](First-Run) — what Scarf expects in `~/.hermes/` - [Project Templates](Project-Templates) — `.scarftemplate` bundles, install / export / author - [Architecture Overview](Architecture-Overview) — MVVM-F, services, transport - [Servers & Remote](Servers-and-Remote) — adding remote Hermes hosts over SSH -- [ScarfGo](ScarfGo) — the iPhone companion (on-the-go agent management) - [Localization](Localization) — supported languages + how to contribute a new one - [Release Notes Index](Release-Notes-Index) — every version's notes - [Wiki Maintenance](Wiki-Maintenance) — how this wiki is edited and kept in sync @@ -34,4 +36,4 @@ Scarf 2.0 is a multi-window app — one window per Hermes server, local or remot Open-source (MIT), 160+ stars, actively maintained. See [Roadmap](Roadmap) for what's coming. --- -_Last updated: 2026-04-24 — Scarf v2.3.0 queued_ +_Last updated: 2026-04-25 — Scarf v2.5.0 queued + ScarfGo public TestFlight_ diff --git a/Platform-Differences.md b/Platform-Differences.md new file mode 100644 index 0000000..7614799 --- /dev/null +++ b/Platform-Differences.md @@ -0,0 +1,81 @@ +# Platform differences — Scarf (Mac) vs ScarfGo (iOS) + +Both clients talk to the same Hermes host with the same paths and the same data. They differ where iOS's constraints make a Mac feature impractical or unnecessary. This page is the canonical "what's missing on iOS, and why" reference. + +## Feature matrix + +| Feature | Mac (Scarf) | iOS (ScarfGo) | Why the gap | +|---|:---:|:---:|---| +| **Dashboard** | Full (stats + recent sessions + Surfaces + Connected info) | Stripped (stats + recent + Sessions sub-tab with project filter) | iOS density. Surfaces (gateway state / pgrep / config.yaml health) read Mac-only filesystems. | +| **Chat (ACP)** | Yes | Yes | — | +| **Project-scoped chat** | Yes | Yes | Shared `ProjectContextBlock` / `SessionAttributionService` in ScarfCore. | +| **Session resume** | Yes | Yes | — | +| **Sessions list — global** | Yes, with project filter + badges (v2.5) | Yes, with project filter + badges | — | +| **Sessions list — per-project** | Yes (Projects sidebar) | No (global Sessions tab covers it) | Different navigation: Mac has a Projects sidebar, iOS has tabs + per-tab filter. Same data. | +| **Memory editor** | Yes | Yes | — | +| **Cron list (read)** | Yes | Yes | — | +| **Cron editor (write)** | Yes | No | Mac builds a richer editor sheet; iOS read-only in v1. Coming. | +| **Skills tree** | Yes | Yes (read-only) | iOS won't grow a skill editor — too cramped. | +| **Settings (read)** | Yes (full YAML) | Yes (full YAML) | — | +| **Settings (write)** | Yes (full YAML editor) | **No** | iOS deferred. The plan was a curated `hermes config set ` shell-out for 7 keys; that landed in the codebase but isn't surfaced in v1 because changing settings remotely without local validation is too easy to break. Mac stays the canonical editor. | +| **Templates — install** | Yes | No | Templates are a content-creation surface; iOS won't get a UI for it in v1. Use Mac. | +| **Templates — uninstall** | Yes | No | Same. | +| **Templates — author / export** | Yes | No | Same. | +| **Messaging Gateway (Discord, etc.)** | Yes (status + config) | No | Mac-only filesystem checks (`gateway_state.json`, pgrep). Could be lifted into ScarfCore with effort. | +| **Health view** | Yes (full) | No | Mac reads `~/.hermes/logs/`, gateway state, config sanity, the `hermes dashboard` web link. Could be ported in chunks. | +| **Logs viewer** | Yes (errors + gateway tails) | No | Could ride on `HermesLogService.streamLines` (already remote-capable). Pending UX design for iOS. | +| **Tool Gateway (Nous Portal)** | Yes (provider picker + Auxiliary tab + Health surface) | Provider exists in catalog | iOS Settings is read-only, so tool-gateway routing toggles aren't editable. Use Mac. | +| **Insights / activity charts** | Yes | No | Charts are richer on bigger screens; deferred. | +| **Terminal (SwiftTerm)** | Mac doesn't have it either | No | Hermes shell mode is CLI-only; neither client wraps it. | +| **Localization** | 7 languages (de, es, fr, it, ja, pt-BR, zh-Hans) | English only | iOS strings are extracted but no translations contributed in v1. | +| **Multi-server** | Yes (one window per server) | Yes (sidebar-adaptable Tab root) | — | +| **Push notifications** | n/a (Mac uses local notifications + the menu bar) | Skeleton present, gated `apnsEnabled = false` | Push sender doesn't exist on Hermes side yet. Capability disabled in target. Flips on simultaneously when both lights are green. | +| **Sparkle auto-update** | Yes | n/a | iOS uses TestFlight / App Store. | +| **iPad support** | n/a | Wired (`.tabViewStyle(.sidebarAdaptable)`) but not smoke-tested | iPad target flag is off; layout probably free, but verify before flipping. | + +## Why the iOS surface is intentionally smaller + +ScarfGo is a **monitor + steer** client. It's optimised for: + +- Running a chat with the agent. +- Looking at sessions, memory, scheduled jobs. +- Resuming work you started somewhere else. +- Approving or denying pending permissions (when push lands). + +It's intentionally NOT optimised for: + +- Authoring templates or skills. +- Editing settings to deeply tune behaviour. +- Operations work — log triage, gateway debugging, deployment. + +Those belong on Mac, where you have a keyboard, real screen, and the full Hermes filesystem layout. Trying to cram them into an iPhone produces a worse Mac and a worse iPhone. + +## Things that won't ever come to iOS + +- **`hermes` daemon** — Hermes is Python; iOS doesn't sandbox Python well. +- **Local Hermes filesystem** — `~/.hermes/` is on a server, always. +- **Process management** — `pgrep`, `kill`, `launchctl` flows stay Mac-only. + +## Things that should come to iOS but haven't yet + +These are gaps without a fundamental reason; they just need engineering time: + +- **Cron editor.** Add / remove jobs from the phone. The data model is shared; only the editor sheet is missing. +- **Scoped Settings editor.** A whitelisted "Quick edits" sheet for the 7 keys most users actually change (`model.default`, `model.provider`, `agent.approval_mode`, `agent.max_turns`, `display.show_cost`, `display.show_reasoning`, `display.streaming`). +- **Health summary card.** A reduced version of the Mac Health view — just enough to answer "is the gateway running, is the DB reachable, is the agent crashy?" +- **Localization.** Translate the strings the Mac app already has; reuse the `.strings` files. +- **iPad layout pass.** Probably one afternoon's verification. + +## Things that are intentionally **not** mirrored + +| Mac feature | Why not on iOS | +|---|---| +| Project sidebar | Replaced by Sessions filter — same outcome, different navigation idiom. | +| Window-per-server | Tabs replace it. iPhone has one focus at a time anyway. | +| Sparkle | TestFlight / App Store does the same job. | +| Menu bar / Dock | iOS has neither. | +| AppleScript / URL scheme `scarf://` | iOS apps don't get the same routing surface; can be added if needed. | + +--- + +_Last updated: 2026-04-25 — v2.5._ diff --git a/Release-Notes-Index.md b/Release-Notes-Index.md index accf233..ca3f8e8 100644 --- a/Release-Notes-Index.md +++ b/Release-Notes-Index.md @@ -4,6 +4,8 @@ Every Scarf release in chronological order. The notes themselves live in `releas | Version | Date | GitHub release | Notes file | |---|---|---|---| +| **v2.5.0** | 2026-04-25 | [v2.5.0](https://github.com/awizemann/scarf/releases/tag/v2.5.0) | [`releases/v2.5.0/RELEASE_NOTES.md`](https://github.com/awizemann/scarf/blob/main/releases/v2.5.0/RELEASE_NOTES.md) | +| **v2.3.0** | 2026-04-24 | [v2.3.0](https://github.com/awizemann/scarf/releases/tag/v2.3.0) | [`releases/v2.3.0/RELEASE_NOTES.md`](https://github.com/awizemann/scarf/blob/main/releases/v2.3.0/RELEASE_NOTES.md) | | **v2.2.1** | 2026-04-23 | [v2.2.1](https://github.com/awizemann/scarf/releases/tag/v2.2.1) | [`releases/v2.2.1/RELEASE_NOTES.md`](https://github.com/awizemann/scarf/blob/main/releases/v2.2.1/RELEASE_NOTES.md) | | **v2.2.0** | 2026-04-23 | [v2.2.0](https://github.com/awizemann/scarf/releases/tag/v2.2.0) | [`releases/v2.2.0/RELEASE_NOTES.md`](https://github.com/awizemann/scarf/blob/main/releases/v2.2.0/RELEASE_NOTES.md) | | **v2.1.0** | 2026-04-21 | [v2.1.0](https://github.com/awizemann/scarf/releases/tag/v2.1.0) | [`releases/v2.1.0/RELEASE_NOTES.md`](https://github.com/awizemann/scarf/blob/main/releases/v2.1.0/RELEASE_NOTES.md) | @@ -17,6 +19,10 @@ Every Scarf release in chronological order. The notes themselves live in `releas ## Highlights by major +**2.5** — **[ScarfGo](ScarfGo) iOS companion** ships in public TestFlight: native iPhone app speaking SSH (Citadel) to your Hermes hosts, with multi-server, project-scoped chat, session resume, memory editor, cron list, skills tree, and read-only settings. Mac side gets project filter + badges on the global Sessions list (parity with ScarfGo's Sessions tab) and human-readable cron schedules everywhere. Under the hood, `SessionAttributionService` / `ProjectContextBlock` / `CronScheduleFormatter` consolidate into ScarfCore so both apps consume one source of truth. See [Platform Differences](Platform-Differences) for what is and isn't shared. + +**2.3** — [Projects sidebar grows up](https://github.com/awizemann/scarf/blob/main/releases/v2.3.0/RELEASE_NOTES.md): folders, rename, archive, search, ⌘1-9 keyboard jumps, per-project Sessions tab, and Scarf-managed `AGENTS.md` context block injected at chat-start so the agent always knows what project it's in. Catches up to Hermes v0.10.0's [Tool Gateway](Hermes-Version-Compatibility) — Nous Portal subscription routing, in-app sign-in, Health-tab visibility for tool routing. + **2.2** — [Project Templates](Project-Templates): shareable `.scarftemplate` bundles with typed configuration schemas, Keychain-backed secrets, a public template catalog at [awizemann.github.io/scarf/templates/](https://awizemann.github.io/scarf/templates/), `scarf://install?url=…` deep links, CI-enforced PR validator, and a Site tab for webview-bearing dashboards. Cross-agent by default via the `AGENTS.md` standard — works in Claude Code, Cursor, Codex, Aider, and every other agent that reads it. v2.2.1 adds the `awizemann/template-author` scaffolding-skill template and fixes the Configuration sheet's segmented-picker overflow on schemas with long enum labels. **2.1** — Full UI translations for six locales on top of English (Simplified Chinese, German, French, Spanish, Japanese, Brazilian Portuguese); locale-aware currency / byte-size / compact-number formatting; chat slash-command menu with filtering and argument hints; auto-scroll polish and loading state for chat session reconnects. @@ -38,4 +44,4 @@ When `scripts/release.sh ` completes a full (non-draft) release, this p This is one of the [wiki update triggers](Wiki-Maintenance) that future Claude Code sessions will follow automatically. --- -_Last updated: 2026-04-23 — Scarf v2.2.1_ +_Last updated: 2026-04-25 — Scarf v2.5.0 + ScarfGo public TestFlight_ diff --git a/Roadmap.md b/Roadmap.md index 1ce5534..e20af4c 100644 --- a/Roadmap.md +++ b/Roadmap.md @@ -2,24 +2,27 @@ What's next for Scarf. Public, opinionated, subject to change. The internal version of this lives in [`scarf/docs/ROADMAP.md`](https://github.com/awizemann/scarf/blob/main/scarf/docs/ROADMAP.md) — the public wiki version is a distillation. -## Now (2.0.x) +## Now (2.5) -- **Stability.** 2.0 was a big multi-server release. Expect 2.0.x patches focused on edge cases in remote diagnostics, snapshot recovery, ACP reconnection, and correctness. -- **Wiki bootstrap.** This wiki is new — Phase 2 is filling it out, Phase 3 is keeping it in sync (ongoing). +- **[ScarfGo](ScarfGo) public TestFlight.** First public iPhone companion build. Pulse the beta tester pool; iterate on feedback over 2.5.x patches. +- **Mac Sessions parity.** Project filter + badges shipped in 2.5 alongside the iOS work. Watch for follow-up on per-project Insights views. +- **Documentation pass.** Wiki reorganized to surface ScarfGo as a first-class section. [Platform Differences](Platform-Differences) is the new canonical reference for "what's different on iOS". -## Near-term +## Near-term (2.6 candidates) -These are the unblocked candidates for 2.1 / 2.2: - -- **Test coverage.** A `MockTransport` unlocks unit-testing the service layer; protocol-oriented testing for `HermesEnvService`, `ACPClient` framing, `HermesPathSet`, `HermesConfig` decoding. See [Testing](Testing). -- **Mermaid diagrams in the wiki.** Architecture pages get a lot of value from one good diagram; deferred to keep Phase 1 focused on text. -- **Per-project FSEvents on remote.** Remote currently has one global mtime-poll loop ([HermesFileWatcher](Core-Services) line 84 has a TODO); per-project paths would reduce remote chattiness. +- **iOS cron editor.** Add / remove / toggle cron jobs from the phone. Data model is already shared; just needs the editor sheet. +- **iOS scoped Settings editor.** The codebase already has the `hermes config set` shell-out wired for 7 keys; needs UX work + the curated whitelist before exposing. +- **iOS push notifications, lit up.** Three things need to happen together: enable the Push Notifications capability in the Xcode target, ship a Hermes-side push sender, flip `apnsEnabled = true`. Skeleton + lock-screen action category are already in place. +- **iPad layout pass.** `.tabViewStyle(.sidebarAdaptable)` is wired; needs verification + a target-flag flip. - **More MCP presets.** The curated list grows as MCP ecosystem matures. +- **Mermaid diagrams in the wiki.** Architecture pages get a lot of value from one good diagram. +- **Per-project FSEvents on remote.** Remote currently has one global mtime-poll loop ([HermesFileWatcher](Core-Services) line 84 has a TODO); per-project paths would reduce remote chattiness. ## Medium-term -- **[ScarfGo](ScarfGo) — iPhone companion.** On-the-go remote agent management. Pre-TestFlight dogfood as of 2026-04-24 — see the dedicated page for full roadmap (M7 stabilization → M8 UX density → M9 multi-server + push + project-chat → M10 TestFlight) and [Known Issues](ScarfGo#known-issues). -- **Custom commands palette.** A ⌘K-style palette for quick actions across all sidebar sections. +- **iOS localization.** Translate the strings the Mac app already has; reuse the `.strings` files. 7 languages on Mac; iOS is English-only in v1. +- **iOS Health summary card.** Reduced version of the Mac Health view — gateway / DB / agent crash status. Read-mostly, doesn't need a full editor. +- **Custom commands palette.** A ⌘K-style palette for quick actions across all sidebar sections (Mac). - **Better Insights.** Rolling heatmaps, drill-downs from any chart, exportable summaries. - **Voice mode polish.** Speaker selection, partial-results display, better handling of long-form dictation. - **In-app log filtering by structured fields.** Currently text-search; a typed query (level=error AND component=gateway AND session=...) would help. @@ -42,4 +45,4 @@ These are the unblocked candidates for 2.1 / 2.2: Open an issue at with what you want and why. Star the repo if you'd use it (signal helps prioritization). --- -_Last updated: 2026-04-20 — Scarf v2.0.1_ +_Last updated: 2026-04-25 — Scarf v2.5.0 + ScarfGo public TestFlight_ diff --git a/ScarfGo-Roadmap.md b/ScarfGo-Roadmap.md new file mode 100644 index 0000000..3e6d982 --- /dev/null +++ b/ScarfGo-Roadmap.md @@ -0,0 +1,129 @@ +# ScarfGo — Roadmap & development reference + +> **Looking for the user guide?** See **[ScarfGo](ScarfGo)**. This page tracks engineering milestones (M6 / M7 / M8 / M9) and the pass-1 / pass-2 smoke-test punch list — useful for contributors and history, less useful for users. + +ScarfGo is the on-the-go iPhone companion to [Scarf](Home). Its scope is deliberately narrower than the Mac app: **remotely manage and interact with a running Hermes agent** from your phone. It is **not** a feature-parity port — Mac handles the full operator surface; ScarfGo handles what's valuable away from a desk. + +**Current state:** **public TestFlight** as of v2.5. M6 → M7 → M8 → M9 all shipped. See [Known Issues](#known-issues) below for residual items + this page for the historical milestone narrative. + +**Tech stack:** + +- **Transport:** pure-Swift SSH via [Citadel](https://github.com/orlandos-nl/Citadel) 0.12.x — no OpenSSH client subprocess (iOS sandbox). +- **Shared core:** `ScarfCore` SPM package — Models / Transport / Services / ViewModels portable across macOS and iOS, unit-tested on Linux in CI. +- **iOS-only code:** `ScarfIOS` package (Citadel glue, Keychain key storage) + `Scarf iOS/` SwiftUI views. +- **Target:** iPhone, iOS 18+. iPad / macCatalyst deferred. + +## What's shipped today (M6) + +| Feature | Behavior | +|---|---| +| **Onboarding** | 8-step: host form → generate or import Ed25519 → show public key → you add to `~/.ssh/authorized_keys` → test probe → done. Single server v1 — multi-server in M9. | +| **Dashboard** | Session count, message count, tool-call count, token totals, last 5 sessions. Pulled from remote `~/.hermes/state.db` via `sqlite3 .backup` + SFTP download (WAL-safe snapshot). | +| **Chat** | Real-time ACP over a dedicated SSH exec channel. Markdown, tool-call cards, permission sheets, reasoning disclosure, streaming. **No** embedded terminal — rich chat only. | +| **Memory** | Read + write MEMORY.md, USER.md, SOUL.md (SOUL is in the Personalities feature on Mac; on iOS we fold it in here because you rarely want them separately on a phone). | +| **Cron** | List jobs, toggle enabled/disabled, edit schedule / prompt / skills / delivery route, add new, swipe-to-delete. Writes `~/.hermes/cron/jobs.json` atomically. | +| **Skills** | Read-only browse — categories + skill files per skill. | +| **Settings** | Read-only view of `config.yaml` grouped by section. Editing deferred — see M9. | + +## Deliberately not on ScarfGo + +- **Analytics features** (Activity, Logs, Health, Insights) — belong on the Mac where screen real-estate supports them. +- **Full-surface configuration** (CredentialPools, Gateway, Templates, MCP Servers, Platforms, Plugins, Profiles, Personalities, Tools, Webhooks, QuickCommands) — config flows live on the Mac. On the go you want to run and interact, not configure. +- **Terminal mode** (embedded SwiftTerm) — out of scope for a chat-first companion. +- **Local Hermes** — iOS can't spawn subprocesses (sandbox). ScarfGo is remote-only by design. + +## Roadmap + +### M7 — Stabilization (pre-TestFlight) + +Bug fixes only, no new features. Unblocks the first internal TestFlight build. See the full issue list in [Known Issues](#known-issues). + +### M8 — UX density pass + +ScarfGo is a developer tool; it needs to show more on-screen than Apple's spacious defaults. Research-driven changes: + +- Migrate root navigation from "Dashboard-is-hub" to a `TabView` with `.sidebarAdaptable` style — Chat, Dashboard, Memory, More. Primary nav stops hiding below the fold. +- Clamp Dynamic Type at scene root: `.dynamicTypeSize(.xSmall ... .accessibility2)`. Semantic fonts + `@ScaledMetric`. +- Tighten list density — `.listRowSpacing(0)` + 6pt vertical insets + `.defaultMinListRowHeight(36)`, preserving 44pt hit targets via `.contentShape(Rectangle()).frame(minHeight: 44)`. +- Chat code blocks: horizontal scroll inside bubble, never wrap, `maxHeight: 240` + Expand. +- Chat tool calls: `DisclosureGroup` collapsed; title = action + elapsed ms. +- Chat scroll anchoring: iOS 18 `.defaultScrollAnchor(.bottom, for: .sizeChanges)` + suspend auto-follow on user scroll-up + "↓ new messages" pill. +- Message/row actions via `.contextMenu` — not visible buttons. +- Sheets with custom peek detents (`.presentationDetents([.height(180), .large])`) — never `.medium`. + +### M9 — On-the-go essentials + +Features that only make sense on mobile, in priority order: + +1. **Multi-server support.** Root becomes a server list (nickname + host + status pill). Each server has two actions: **Disconnect** (soft — closes live transport, keeps Keychain key + config, one-tap to reconnect) and **Forget** (destructive — wipes credentials, re-onboards). The underlying transport factory is already `ServerID`-keyed; changes are storage layer + root nav + onboarding entry point. +2. **Project-scoped chat.** The `+` button in Chat opens a picker: "Quick chat" (default) or "In project…" — SFTP-read `~/.hermes/scarf/projects.json`, pick one, SFTP-write the scarf-managed project-context block into `/AGENTS.md`, spawn `hermes acp` with `cwd = project.path`. After session id comes back, SFTP-write the attribution row into `session_project_map.json`. Unlocks the iOS parity of `ProjectAgentContextService` + `SessionAttributionService`. +3. **Session resume.** Dashboard's Recent Sessions list becomes tappable — taps call `ACPClient.loadSession(id:)` instead of starting a new session. Resume a conversation that was started on a Mac, continue it on the phone. +4. **APNs push — cron completion + pending permissions.** Notification for "your cron just ran" or "your agent needs approval to run X." The client half is ~200 LOC; the Hermes-side sender is a separate upstream feature. +5. **Lock-screen quick-approve.** Notification action button for "Approve" / "Deny" on pending permissions so the agent keeps running while you're away from the app. +6. **Scoped Settings editor.** Not a generic YAML round-trip editor — a curated set of high-value fields (model / provider / approval mode / max turns / display toggles) that save via `hermes config set ` over SSH exec. Hermes owns the YAML round-trip; Scarf just picks values. + +### M10 — TestFlight + +App Store Connect + provisioning profile + internal TestFlight group of 1 (Alan). Public TestFlight after 2–3 real sessions on a real iPhone without crashes. + +## Known Issues + +All tracked from the 2026-04-24 pass-1 smoke test. This list is the truth about what's broken today — filed publicly in the interest of transparency. A ✅ means the fix has already landed on the `scarf-mobile-development` branch. + +### Blocking TestFlight — must fix in M7 + +| # | Summary | Scope | Status | +|---|---|---|---| +| 1 | **Primary navigation hidden below Dashboard fold.** Chat / Memory / Cron / Skills / Settings links lived as the 4th section in a `List`. Replaced with `.tabViewStyle(.sidebarAdaptable)` root: 4 primary tabs (Chat / Dashboard / Memory / More) + collapse to sidebar on iPadOS later with zero UI code change. | ScarfGo | ✅ Fixed | +| 2 | **Non-retryable provider errors → perpetual spinner.** ACP error triplet (`acpError`, `acpErrorHint`, `acpErrorDetails`) promoted to ScarfCore so Mac + ScarfGo share state; ChatView renders an inline banner with Copy Details / Expand. `handlePromptComplete` now calls `recordPromptStopFailureUsingProvider(stopReason:)` on non-`end_turn` stops with the stderr tail appended. | Cross-platform | ✅ Fixed | +| 3 | **No connecting feedback when entering Chat.** ChatController's existing `.connecting` state now drives a `.regularMaterial` overlay with "Connecting to …" + ProgressView. | ScarfGo | ✅ Fixed | +| 4 | **`isAgentWorking` doesn't clear after primary response.** Split into computed `isGenerating` (agent still producing text) + `isPostProcessing` (agent done producing; ACP `promptComplete` not yet fired). Prominent spinner drops as soon as the reply is visible; subtle "Finishing up…" pill covers auxiliary post-work. Applied cross-platform. | Cross-platform | ✅ Fixed | +| 5 | **ACP command missing PATH prefix.** SSH exec runs a non-interactive shell whose PATH is `/usr/bin:/bin:/usr/sbin:/sbin`. Fixed by prepending common install locations (`~/.local/bin`, `/opt/homebrew/bin`, `/usr/local/bin`, `~/.hermes/bin`) to PATH inline in the exec command. Mirrors `HermesPathSet.hermesBinaryCandidates`. | ScarfGo | ✅ Fixed | +| 6 | **SFTP `~` tilde not expanded.** Per-connection cached `resolveHome()` on `ConnectionHolder` + `resolveSFTPPath()` helper applied to every SFTP entry point (`readFile` / `writeFile` / `fileExists` / `stat` / `listDirectory` / `createDirectory` / `removeFile`). | ScarfGo | ✅ Fixed | +| 7 | **No loading state on Memory editor.** Switched to throwing read (#8) so `lastError` populates on real failures instead of silently showing "empty" — the existing error banner now renders. | ScarfGo | ✅ Fixed | +| 8 | **`ServerContext.readText` swallows errors.** New `readTextThrowing(_:)` distinguishes "file absent" from "transport error"; old nil-returning `readText` stays as a `try?` shim for callers that really don't care. Memory editor uses the throwing variant. | Cross-platform | ✅ Fixed | +| 9 | **TextEditor keyboard obscures cursor.** `.scrollDismissesKeyboard(.interactively)` on the TextEditor, error pill + Saved pill moved into `.safeAreaInset(edge: .bottom)` so SwiftUI draws them above the keyboard. | ScarfGo | ✅ Fixed | +| 10 | **Save confirmation not visible.** Saved pill is now a full-width material strip inside `.safeAreaInset`, holds 2.5s (up from 1.5s), and cancels any in-flight hide task on subsequent saves so rapid saves don't drop the pill mid-fade. | ScarfGo | ✅ Fixed | +| 11 | **Cron schedule + next-run shown as machine formats.** New `CronScheduleFormatter` in ScarfCore translates the common cron shapes (every N minutes / hourly / daily at H / weekdays at H / weekends / specific weekday / monthly on day D + @-macros) into English phrases and falls back to raw expression on unrecognised shapes. Sibling `formatNextRun(iso:)` parses Hermes's ISO-8601 next-run and renders `"in 4 hours"` etc. 17 unit tests. Applied Mac + ScarfGo. | Cross-platform | ✅ Fixed | +| 12 | **"Disconnect" is factory reset.** Split properly into **Disconnect** (soft — keeps Keychain key + config, returns to ServerListView, next tap reconnects with no re-onboarding) and **Forget** (hard — removes that server's key + config, returns to list or onboarding if list becomes empty). Lives on the More tab. | ScarfGo | ✅ Fixed | + +### Cross-platform (fix on Mac too) + +- **Model picker accepts unknown models.** `ModelCatalogService.validateModel(_:for:)` returns `.valid` / `.unknownProvider(id)` / `.invalid(providerName, suggestions)`. Overlay-only providers (Nous / OpenAI Codex / Qwen OAuth) short-circuit to `.valid` because their catalogs aren't in models.dev. Mac `ModelPickerSheet.submitSelection` routes through the validator and raises an alert with suggestions on `.invalid`. 5 unit tests. — ✅ Fixed + +### Hermes-side (upstream, not ours) + +- Auxiliary `title_generation` appears to hang when the main provider returns a 404 — likely retries the failed call. Worth filing upstream; causes bug #4 to manifest. — still open upstream. + +## Post-pass-1 feature work + +The pass-1 session also surfaced the user-facing roadmap we delivered through M8 (UX density) and M9 (on-the-go features): + +### M8 — UX density (all shipped) + +- Dynamic Type clamped at scene root to `.xSmall ... .accessibility2`. +- TabView root nav replacing Dashboard-as-hub (see fix #1 above). +- `.scarfGoCompactListRow()` + `.scarfGoListDensity()` tokens applied to Memory / Cron / Skills / Dashboard / MoreTab / ServerList for ~48pt rows that still meet the 44pt tap-target invariant. +- Chat: fenced code blocks render in a horizontally-scrollable `CodeBlockView` (240pt collapsed, Expand to full) instead of soft-wrapping into unreadable columns; message bubbles gained `.contextMenu` (Copy + Share); iOS 17+ `.defaultScrollAnchor(.bottom)` + iOS 18's `.defaultScrollAnchor(.bottom, for: .sizeChanges)` replace the manual `scrollTo` dance. +- Custom `.presentationDetents` per sheet — `[.height(220), .large]` for permission sheet, `[.large]` for cron editor; never the misleading `.medium`. + +### M9 — Multi-server + on-the-go (all shipped) + +- **Multi-server** — storage layer (UserDefaults + Keychain) now keys by `ServerID`, with one-shot v1 → v2 migration so updating the app doesn't re-onboard anyone. New `ServerListView` root shows every configured server with nickname / user@host:port / tap-to-connect / swipe-to-forget. "+" button re-enters onboarding for a fresh server. ScarfGoTabRoot splits the old factory-reset "Disconnect" into soft Disconnect + destructive Forget rows in the More tab. +- **Session resume** — Dashboard Recent Sessions rows are now tappable; `ScarfGoCoordinator` routes the tap to the Chat tab with a `pendingResumeSessionID`; ChatController.startResuming calls `session/resume` (or falls back to `session/load` on older Hermes) with the full transcript preserved. +- **Project-scoped chat** — "+" in Chat opens a picker: Quick chat vs. In project…. Project list loads from `~/.hermes/scarf/projects.json` over SFTP. On project select, ScarfGo SFTP-writes the Scarf-managed block into `/AGENTS.md` via the shared `ProjectContextBlock` service (same byte-for-byte markers as the Mac app — projects round-trip cleanly), spawns `hermes acp` with `cwd = project.path`, and records the session attribution in `session_project_map.json`. `SessionAttributionService` moved from Mac target into ScarfCore so both apps use the same store. +- **Scoped Settings editor** — curated list of 7 editable keys (model.default, model.provider, approvals.mode, agent.max_turns, display.show_cost / show_reasoning / streaming) as a Quick Edits section at the top of Settings. Save routes through `hermes config set ` on the remote (Hermes owns the YAML round-trip); Scarf just picks the value. Inline error banner on sheet if the remote command fails. +- **APNs push skeleton** — `APNSTokenStore` + `NotificationRouter` ship ready for a future Hermes-side push sender. Lock-screen "Approve" / "Deny" action category is registered. Capability stays OFF in Xcode until Hermes gains a sender + we have an APNs auth key; flipping the capability on is a ~5-line follow-up. + +## Reporting issues + +- **Bugs:** — tag with `component: scarfgo`. +- **Feature requests:** same, tag with `feature: scarfgo`. +- **Security / credential handling concerns:** use the repo's security policy. + +## For contributors + +See [Architecture Overview](Architecture-Overview) for how ScarfCore + ScarfIOS fit together. The `scarf-mobile-development` branch is the working branch; the M7/M8/M9 changes above live there pending a pass-2 smoke test before merging to `main`. + +--- +_Last updated: 2026-04-24 — post M7/M8/M9 implementation, pass-2 pending_ diff --git a/ScarfGo.md b/ScarfGo.md index 58a9482..8d19fa2 100644 --- a/ScarfGo.md +++ b/ScarfGo.md @@ -1,127 +1,115 @@ -# ScarfGo — the iOS companion +# ScarfGo — iOS companion for Hermes -ScarfGo is the on-the-go iPhone companion to [Scarf](Home). Its scope is deliberately narrower than the Mac app: **remotely manage and interact with a running Hermes agent** from your phone. It is **not** a feature-parity port — Mac handles the full operator surface; ScarfGo handles what's valuable away from a desk. +ScarfGo is the iPhone companion to [Scarf](Home), the macOS GUI for the [Hermes AI agent](https://github.com/awizemann/hermes-agent). It connects from your phone to a Hermes server you operate (your Mac, a home Linux box, a cloud VM — anywhere reachable over SSH), and lets you run sessions, review memory, manage cron jobs, and resume conversations on the go. -**Current state:** pre-TestFlight dogfood. M6 milestone merged; pass-1 smoke test has completed against a local Hermes install. See [Known Issues](#known-issues) below before filing bugs. +> **Status:** Public beta in TestFlight. See **[Installation](#installation)** below. -**Tech stack:** +## What ScarfGo is, in one paragraph -- **Transport:** pure-Swift SSH via [Citadel](https://github.com/orlandos-nl/Citadel) 0.12.x — no OpenSSH client subprocess (iOS sandbox). -- **Shared core:** `ScarfCore` SPM package — Models / Transport / Services / ViewModels portable across macOS and iOS, unit-tested on Linux in CI. -- **iOS-only code:** `ScarfIOS` package (Citadel glue, Keychain key storage) + `Scarf iOS/` SwiftUI views. -- **Target:** iPhone, iOS 18+. iPad / macCatalyst deferred. +ScarfGo is a fully native iOS app — not a web view, not a remote desktop. It speaks SSH (Citadel under the hood, no `ssh` binary needed on iOS), reads your Hermes state directly via SFTP + SQLite snapshots, and streams real-time agent output over the [Agent Client Protocol](ACP-Subprocess) on a long-lived SSH exec channel. Every byte stays between your device and the Hermes host you configured. There are no developer-controlled servers in between. -## What's shipped today (M6) +## System requirements -| Feature | Behavior | +- iPhone running **iOS 18.0** or later. +- An **SSH-reachable Hermes host** running Hermes v0.10.0 or later. See [Hermes Version Compatibility](Hermes-Version-Compatibility). +- Your iPhone needs to reach that host on the network — same Wi-Fi, VPN, Tailscale, port-forwarded public address, or anything else SSH can dial. +- A spare second or two for onboarding to generate an SSH keypair. + +## Installation + +ScarfGo is in **public TestFlight**. Apple-provided test environment, free to join, no payment, no Apple ID needed for beta installs. + +1. **Get the TestFlight app** — install from the App Store if you don't have it. +2. **Open the public TestFlight invite link** — _link will appear here once Apple's Beta Review approves the first build. Bookmark this page._ +3. **Tap "Accept" and "Install"** — TestFlight installs ScarfGo alongside your other apps. +4. **Open ScarfGo** — onboarding walks you through host details, generates a new SSH keypair, and gives you the public-key snippet to paste into your Hermes host's `~/.ssh/authorized_keys`. + +Onboarding details: + +- ScarfGo generates a fresh Ed25519 keypair on first run. The private half lives in the iOS Keychain (`kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly` — never iCloud-synced). +- The public-key snippet is shown for you to copy and append to `~/.ssh/authorized_keys` on your Hermes host. Plain `ssh-copy-id` doesn't work from iPhone, so the manual paste is the safest path. +- A one-tap "Test connection" verifies SSH + the `hermes` binary's path before saving. + +## Features + +| Feature | What you can do | |---|---| -| **Onboarding** | 8-step: host form → generate or import Ed25519 → show public key → you add to `~/.ssh/authorized_keys` → test probe → done. Single server v1 — multi-server in M9. | -| **Dashboard** | Session count, message count, tool-call count, token totals, last 5 sessions. Pulled from remote `~/.hermes/state.db` via `sqlite3 .backup` + SFTP download (WAL-safe snapshot). | -| **Chat** | Real-time ACP over a dedicated SSH exec channel. Markdown, tool-call cards, permission sheets, reasoning disclosure, streaming. **No** embedded terminal — rich chat only. | -| **Memory** | Read + write MEMORY.md, USER.md, SOUL.md (SOUL is in the Personalities feature on Mac; on iOS we fold it in here because you rarely want them separately on a phone). | -| **Cron** | List jobs, toggle enabled/disabled, edit schedule / prompt / skills / delivery route, add new, swipe-to-delete. Writes `~/.hermes/cron/jobs.json` atomically. | -| **Skills** | Read-only browse — categories + skill files per skill. | -| **Settings** | Read-only view of `config.yaml` grouped by section. Editing deferred — see M9. | +| **Multi-server** | Configure as many Hermes hosts as you like. Soft Disconnect keeps credentials; Forget wipes a server end-to-end. | +| **Dashboard** | Total sessions / messages / tool calls + a 25-session list with project badges. Filter by project. | +| **Chat** | Streamed agent responses, tool-call disclosure groups, code blocks with horizontal scroll. Project-scoped chat picks a project from your registry, writes the same Scarf-managed `AGENTS.md` block as the Mac app, and spawns `hermes acp` with the project as the working directory. | +| **Session resume** | Tap a row on the Dashboard → opens that session's transcript in Chat. CLI-started sessions hydrate from `state.db`; ACP sessions show an empty-state because Hermes doesn't persist ACP transcripts to the DB (same on Mac). | +| **Memory** | Read + edit `MEMORY.md` and `USER.md`. The "Saved" pill survives keyboard dismissal; Revert undoes unsaved edits. | +| **Cron** | List view of `~/.hermes/cron/jobs.json` with **human-readable schedules** ("Every 6 hours", "Weekdays at 09:00") and a relative next-run ("in 4 hours"). Read-only in v1 — editing comes later. | +| **Skills** | Browse the skills tree from `~/.hermes/skills/`. Read-only. | +| **Settings** | Read-only view of `config.yaml`. An in-app editor is planned but not in v1 — see [Platform Differences](Platform-Differences). | -## Deliberately not on ScarfGo +## Project-scoped chat -- **Analytics features** (Activity, Logs, Health, Insights) — belong on the Mac where screen real-estate supports them. -- **Full-surface configuration** (CredentialPools, Gateway, Templates, MCP Servers, Platforms, Plugins, Profiles, Personalities, Tools, Webhooks, QuickCommands) — config flows live on the Mac. On the go you want to run and interact, not configure. -- **Terminal mode** (embedded SwiftTerm) — out of scope for a chat-first companion. -- **Local Hermes** — iOS can't spawn subprocesses (sandbox). ScarfGo is remote-only by design. +Picking a project at the start of a chat tells the agent exactly which directory it's operating in. ScarfGo does the same handshake the Mac app does: -## Roadmap +1. SFTP-reads `~/.hermes/scarf/projects.json` for the project registry. +2. On selection, SFTP-writes a managed block into `/AGENTS.md` (between `` and `:end -->` markers — preserves anything outside). +3. Spawns `hermes acp` with `cwd = `. +4. After the session ID returns, records the attribution in `~/.hermes/scarf/session_project_map.json`. -### M7 — Stabilization (pre-TestFlight) +The block contains the project name, directory, dashboard path, configuration field names (never values — secrets stored in the Keychain are surfaced as field names only), and any cron jobs registered to the project. Hermes's startup context scan picks it up automatically. Ask a fresh chat _"what project am I in?"_ and the agent answers with the right name + path. -Bug fixes only, no new features. Unblocks the first internal TestFlight build. See the full issue list in [Known Issues](#known-issues). +If the SFTP write fails (permissions, disk full, network drop), ScarfGo surfaces a banner — "Project context not written — agent will proceed without it" — and starts the session anyway. The session works; it just doesn't have the augmented context. -### M8 — UX density pass +## Limitations in v1 -ScarfGo is a developer tool; it needs to show more on-screen than Apple's spacious defaults. Research-driven changes: +- **No local mode.** ScarfGo only operates against an SSH-reachable Hermes host. There's no local Hermes runtime on iOS. +- **No push notifications yet.** The skeleton (UNNotificationCenter delegate, "Approve / Deny" action category) ships in the binary but is gated behind an internal feature flag because: (a) the Push Notifications capability is not yet enabled in the Xcode target, (b) Hermes doesn't yet have a push sender. When both land, push lights up on the iOS side without an app update — well, with one update to flip the flag. Watch this page. +- **No in-app config editor.** Settings is read-only in v1. Use the Mac app or a remote shell to change values. +- **No template install UI.** `.scarftemplate` install + uninstall is Mac-only in v1. +- **No terminal mode.** Rich-chat (ACP) only. +- **English only.** The Mac app ships in 7 languages; ScarfGo is English-only for v1. +- **Push from Hermes server-side is upstream work.** The iOS side is ready; Hermes needs the sender. -- Migrate root navigation from "Dashboard-is-hub" to a `TabView` with `.sidebarAdaptable` style — Chat, Dashboard, Memory, More. Primary nav stops hiding below the fold. -- Clamp Dynamic Type at scene root: `.dynamicTypeSize(.xSmall ... .accessibility2)`. Semantic fonts + `@ScaledMetric`. -- Tighten list density — `.listRowSpacing(0)` + 6pt vertical insets + `.defaultMinListRowHeight(36)`, preserving 44pt hit targets via `.contentShape(Rectangle()).frame(minHeight: 44)`. -- Chat code blocks: horizontal scroll inside bubble, never wrap, `maxHeight: 240` + Expand. -- Chat tool calls: `DisclosureGroup` collapsed; title = action + elapsed ms. -- Chat scroll anchoring: iOS 18 `.defaultScrollAnchor(.bottom, for: .sizeChanges)` + suspend auto-follow on user scroll-up + "↓ new messages" pill. -- Message/row actions via `.contextMenu` — not visible buttons. -- Sheets with custom peek detents (`.presentationDetents([.height(180), .large])`) — never `.medium`. +See [Platform Differences](Platform-Differences) for a full Mac-vs-iOS feature matrix. -### M9 — On-the-go essentials +## Troubleshooting -Features that only make sense on mobile, in priority order: +**Onboarding can't connect.** First check that `ssh user@host` works from your Mac with the same hostname/port. If that fails, ScarfGo can't connect either — fix SSH first. If the Mac connection works: -1. **Multi-server support.** Root becomes a server list (nickname + host + status pill). Each server has two actions: **Disconnect** (soft — closes live transport, keeps Keychain key + config, one-tap to reconnect) and **Forget** (destructive — wipes credentials, re-onboards). The underlying transport factory is already `ServerID`-keyed; changes are storage layer + root nav + onboarding entry point. -2. **Project-scoped chat.** The `+` button in Chat opens a picker: "Quick chat" (default) or "In project…" — SFTP-read `~/.hermes/scarf/projects.json`, pick one, SFTP-write the scarf-managed project-context block into `/AGENTS.md`, spawn `hermes acp` with `cwd = project.path`. After session id comes back, SFTP-write the attribution row into `session_project_map.json`. Unlocks the iOS parity of `ProjectAgentContextService` + `SessionAttributionService`. -3. **Session resume.** Dashboard's Recent Sessions list becomes tappable — taps call `ACPClient.loadSession(id:)` instead of starting a new session. Resume a conversation that was started on a Mac, continue it on the phone. -4. **APNs push — cron completion + pending permissions.** Notification for "your cron just ran" or "your agent needs approval to run X." The client half is ~200 LOC; the Hermes-side sender is a separate upstream feature. -5. **Lock-screen quick-approve.** Notification action button for "Approve" / "Deny" on pending permissions so the agent keeps running while you're away from the app. -6. **Scoped Settings editor.** Not a generic YAML round-trip editor — a curated set of high-value fields (model / provider / approval mode / max turns / display toggles) that save via `hermes config set ` over SSH exec. Hermes owns the YAML round-trip; Scarf just picks values. +- Make sure you appended the ScarfGo-shown public-key to `~/.ssh/authorized_keys` on the host. +- Make sure `hermes` is in the SSH user's PATH on the host. ScarfGo prepends common pipx / Homebrew install paths to the exec command, but if `hermes` lives somewhere unusual, run `which hermes` over SSH and ensure the path is one of: `~/.local/bin`, `/opt/homebrew/bin`, `/usr/local/bin`, or `~/.hermes/bin`. -### M10 — TestFlight +**Dashboard shows zero sessions but I know there are some.** ScarfGo downloads a snapshot of `~/.hermes/state.db` over SFTP. If your Hermes install hasn't yet written the DB (no sessions ever started), the snapshot is empty. Start a session via the Mac app or CLI first. -App Store Connect + provisioning profile + internal TestFlight group of 1 (Alan). Public TestFlight after 2–3 real sessions on a real iPhone without crashes. +**Memory says "Save failed" silently.** Pull-to-refresh — usually a transient SFTP hiccup. If it persists, check the SSH user has write permission on `~/.hermes/memories/`. -## Known Issues +**The agent's running forever after a non-retryable error.** v2.5 added a banner for HTTP 4xx/5xx provider errors; older builds (or upstream Hermes hangs we haven't worked around yet) might still show "Thinking…" indefinitely. Tap the Stop button in Chat to abort — that always works. -All tracked from the 2026-04-24 pass-1 smoke test. This list is the truth about what's broken today — filed publicly in the interest of transparency. A ✅ means the fix has already landed on the `scarf-mobile-development` branch. +**Biometric prompt loops or fails.** Cancelling Face ID / passcode prompts no longer drops you into fresh onboarding (v2.5 fix); the app surfaces a banner on the server list with a Dismiss button. Re-tap the server to retry. -### Blocking TestFlight — must fix in M7 +## FAQ -| # | Summary | Scope | Status | -|---|---|---|---| -| 1 | **Primary navigation hidden below Dashboard fold.** Chat / Memory / Cron / Skills / Settings links lived as the 4th section in a `List`. Replaced with `.tabViewStyle(.sidebarAdaptable)` root: 4 primary tabs (Chat / Dashboard / Memory / More) + collapse to sidebar on iPadOS later with zero UI code change. | ScarfGo | ✅ Fixed | -| 2 | **Non-retryable provider errors → perpetual spinner.** ACP error triplet (`acpError`, `acpErrorHint`, `acpErrorDetails`) promoted to ScarfCore so Mac + ScarfGo share state; ChatView renders an inline banner with Copy Details / Expand. `handlePromptComplete` now calls `recordPromptStopFailureUsingProvider(stopReason:)` on non-`end_turn` stops with the stderr tail appended. | Cross-platform | ✅ Fixed | -| 3 | **No connecting feedback when entering Chat.** ChatController's existing `.connecting` state now drives a `.regularMaterial` overlay with "Connecting to …" + ProgressView. | ScarfGo | ✅ Fixed | -| 4 | **`isAgentWorking` doesn't clear after primary response.** Split into computed `isGenerating` (agent still producing text) + `isPostProcessing` (agent done producing; ACP `promptComplete` not yet fired). Prominent spinner drops as soon as the reply is visible; subtle "Finishing up…" pill covers auxiliary post-work. Applied cross-platform. | Cross-platform | ✅ Fixed | -| 5 | **ACP command missing PATH prefix.** SSH exec runs a non-interactive shell whose PATH is `/usr/bin:/bin:/usr/sbin:/sbin`. Fixed by prepending common install locations (`~/.local/bin`, `/opt/homebrew/bin`, `/usr/local/bin`, `~/.hermes/bin`) to PATH inline in the exec command. Mirrors `HermesPathSet.hermesBinaryCandidates`. | ScarfGo | ✅ Fixed | -| 6 | **SFTP `~` tilde not expanded.** Per-connection cached `resolveHome()` on `ConnectionHolder` + `resolveSFTPPath()` helper applied to every SFTP entry point (`readFile` / `writeFile` / `fileExists` / `stat` / `listDirectory` / `createDirectory` / `removeFile`). | ScarfGo | ✅ Fixed | -| 7 | **No loading state on Memory editor.** Switched to throwing read (#8) so `lastError` populates on real failures instead of silently showing "empty" — the existing error banner now renders. | ScarfGo | ✅ Fixed | -| 8 | **`ServerContext.readText` swallows errors.** New `readTextThrowing(_:)` distinguishes "file absent" from "transport error"; old nil-returning `readText` stays as a `try?` shim for callers that really don't care. Memory editor uses the throwing variant. | Cross-platform | ✅ Fixed | -| 9 | **TextEditor keyboard obscures cursor.** `.scrollDismissesKeyboard(.interactively)` on the TextEditor, error pill + Saved pill moved into `.safeAreaInset(edge: .bottom)` so SwiftUI draws them above the keyboard. | ScarfGo | ✅ Fixed | -| 10 | **Save confirmation not visible.** Saved pill is now a full-width material strip inside `.safeAreaInset`, holds 2.5s (up from 1.5s), and cancels any in-flight hide task on subsequent saves so rapid saves don't drop the pill mid-fade. | ScarfGo | ✅ Fixed | -| 11 | **Cron schedule + next-run shown as machine formats.** New `CronScheduleFormatter` in ScarfCore translates the common cron shapes (every N minutes / hourly / daily at H / weekdays at H / weekends / specific weekday / monthly on day D + @-macros) into English phrases and falls back to raw expression on unrecognised shapes. Sibling `formatNextRun(iso:)` parses Hermes's ISO-8601 next-run and renders `"in 4 hours"` etc. 17 unit tests. Applied Mac + ScarfGo. | Cross-platform | ✅ Fixed | -| 12 | **"Disconnect" is factory reset.** Split properly into **Disconnect** (soft — keeps Keychain key + config, returns to ServerListView, next tap reconnects with no re-onboarding) and **Forget** (hard — removes that server's key + config, returns to list or onboarding if list becomes empty). Lives on the More tab. | ScarfGo | ✅ Fixed | +**Q: Can ScarfGo run Hermes locally on the iPhone?** +A: No. Hermes is a Python agent that needs Python plus a model provider's CLI plus a writable filesystem. iOS doesn't make any of that practical. ScarfGo is a thin client. -### Cross-platform (fix on Mac too) +**Q: Will my SSH key sync to my other devices?** +A: No. The Keychain entry is `ThisDeviceOnly` — explicitly excluded from iCloud Keychain sync. Adding a second device means a second key + a second `authorized_keys` line. -- **Model picker accepts unknown models.** `ModelCatalogService.validateModel(_:for:)` returns `.valid` / `.unknownProvider(id)` / `.invalid(providerName, suggestions)`. Overlay-only providers (Nous / OpenAI Codex / Qwen OAuth) short-circuit to `.valid` because their catalogs aren't in models.dev. Mac `ModelPickerSheet.submitSelection` routes through the validator and raises an alert with suggestions on `.invalid`. 5 unit tests. — ✅ Fixed +**Q: Can I use ScarfGo with a Hermes host that's not on my LAN?** +A: Yes — anywhere reachable over SSH. Tailscale, port forwarding, a VPS, anything. The Hermes host doesn't know it's being driven by an iPhone vs a Mac. -### Hermes-side (upstream, not ours) +**Q: Why is push disabled?** +A: Two reasons that need to land together: (1) the Push Notifications capability requires Apple Developer Program enrollment + an APNs auth key, (2) Hermes needs a server-side push sender to actually emit pushes. The iOS skeleton ships ready; flipping it on is one app update + one Hermes update. -- Auxiliary `title_generation` appears to hang when the main provider returns a 404 — likely retries the failed call. Worth filing upstream; causes bug #4 to manifest. — still open upstream. +**Q: Is my data sent to anyone?** +A: No. See the [privacy policy](https://awizemann.github.io/scarf/privacy/). The apps make exactly three kinds of network connections: (1) SSH to your Hermes hosts, (2) Sparkle update checks (Mac only), (3) HTTPS to GitHub Pages for the public template catalog. Zero analytics. -## Post-pass-1 feature work - -The pass-1 session also surfaced the user-facing roadmap we delivered through M8 (UX density) and M9 (on-the-go features): - -### M8 — UX density (all shipped) - -- Dynamic Type clamped at scene root to `.xSmall ... .accessibility2`. -- TabView root nav replacing Dashboard-as-hub (see fix #1 above). -- `.scarfGoCompactListRow()` + `.scarfGoListDensity()` tokens applied to Memory / Cron / Skills / Dashboard / MoreTab / ServerList for ~48pt rows that still meet the 44pt tap-target invariant. -- Chat: fenced code blocks render in a horizontally-scrollable `CodeBlockView` (240pt collapsed, Expand to full) instead of soft-wrapping into unreadable columns; message bubbles gained `.contextMenu` (Copy + Share); iOS 17+ `.defaultScrollAnchor(.bottom)` + iOS 18's `.defaultScrollAnchor(.bottom, for: .sizeChanges)` replace the manual `scrollTo` dance. -- Custom `.presentationDetents` per sheet — `[.height(220), .large]` for permission sheet, `[.large]` for cron editor; never the misleading `.medium`. - -### M9 — Multi-server + on-the-go (all shipped) - -- **Multi-server** — storage layer (UserDefaults + Keychain) now keys by `ServerID`, with one-shot v1 → v2 migration so updating the app doesn't re-onboard anyone. New `ServerListView` root shows every configured server with nickname / user@host:port / tap-to-connect / swipe-to-forget. "+" button re-enters onboarding for a fresh server. ScarfGoTabRoot splits the old factory-reset "Disconnect" into soft Disconnect + destructive Forget rows in the More tab. -- **Session resume** — Dashboard Recent Sessions rows are now tappable; `ScarfGoCoordinator` routes the tap to the Chat tab with a `pendingResumeSessionID`; ChatController.startResuming calls `session/resume` (or falls back to `session/load` on older Hermes) with the full transcript preserved. -- **Project-scoped chat** — "+" in Chat opens a picker: Quick chat vs. In project…. Project list loads from `~/.hermes/scarf/projects.json` over SFTP. On project select, ScarfGo SFTP-writes the Scarf-managed block into `/AGENTS.md` via the shared `ProjectContextBlock` service (same byte-for-byte markers as the Mac app — projects round-trip cleanly), spawns `hermes acp` with `cwd = project.path`, and records the session attribution in `session_project_map.json`. `SessionAttributionService` moved from Mac target into ScarfCore so both apps use the same store. -- **Scoped Settings editor** — curated list of 7 editable keys (model.default, model.provider, approvals.mode, agent.max_turns, display.show_cost / show_reasoning / streaming) as a Quick Edits section at the top of Settings. Save routes through `hermes config set ` on the remote (Hermes owns the YAML round-trip); Scarf just picks the value. Inline error banner on sheet if the remote command fails. -- **APNs push skeleton** — `APNSTokenStore` + `NotificationRouter` ship ready for a future Hermes-side push sender. Lock-screen "Approve" / "Deny" action category is registered. Capability stays OFF in Xcode until Hermes gains a sender + we have an APNs auth key; flipping the capability on is a ~5-line follow-up. +**Q: Where can I see what's planned next?** +A: [ScarfGo Roadmap](ScarfGo-Roadmap) tracks shipped milestones (M6 / M7 / M8 / M9) and remaining work. The [main Roadmap](Roadmap) covers cross-platform plans. ## Reporting issues -- **Bugs:** — tag with `component: scarfgo`. -- **Feature requests:** same, tag with `feature: scarfgo`. -- **Security / credential handling concerns:** use the repo's security policy. - -## For contributors - -See [Architecture Overview](Architecture-Overview) for how ScarfCore + ScarfIOS fit together. The `scarf-mobile-development` branch is the working branch; the M7/M8/M9 changes above live there pending a pass-2 smoke test before merging to `main`. +- **Bugs:** [github.com/awizemann/scarf/issues](https://github.com/awizemann/scarf/issues) — tag `component: scarfgo`. +- **Feature requests:** same, tag `feature: scarfgo`. +- **TestFlight feedback:** the Send Beta Feedback button in TestFlight goes straight to the developer. +- **Security / credential concerns:** use the repo's security policy. --- -_Last updated: 2026-04-24 — post M7/M8/M9 implementation, pass-2 pending_ + +_Last updated: 2026-04-25 — v2.5 public TestFlight._ diff --git a/_Sidebar.md b/_Sidebar.md index d500ff9..e0dd586 100644 --- a/_Sidebar.md +++ b/_Sidebar.md @@ -4,6 +4,10 @@ - [Updating](Updating) - [Uninstalling](Uninstalling) +**ScarfGo (iOS)** +- [ScarfGo](ScarfGo) +- [Platform Differences](Platform-Differences) + **User Guide** - [Dashboard](Dashboard) - [Insights & Activity](Insights-and-Activity) @@ -39,6 +43,7 @@ **Contributing** - [Contributing](Contributing) - [Wiki Maintenance](Wiki-Maintenance) +- [ScarfGo Roadmap](ScarfGo-Roadmap) (dev reference) **Release History** - [Release Notes Index](Release-Notes-Index)