docs(v2.5): home-page focus + RELEASE_NOTES under-the-hood + App Store metadata

README: strip the "Previously, in 2.3" subsection per release direction —
the home page is now a single-version forward-looking surface with prior
releases linked off to the wiki Release Notes Index. Promote the
ScarfGo TestFlight callout to its own subsection with the public link
(testflight.apple.com/join/qCrRpcTz) embedded inline. Add a
"Connect ScarfGo to your Hermes server" five-step walkthrough between
What's New and Multi-server, mirroring OnboardingRootView's state
machine so users can follow it cold without opening the wiki first.

RELEASE_NOTES: extend the Under-the-hood section with the iOS-side
maintenance work that landed in the last 48h — Citadel
executeCommandStream rewrite (preserves stdout on non-zero remote
exit; was eating Skills hub Browse output), inline PATH=
prepend on every iOS runProcess (Citadel's raw exec channel doesn't
source shell rc files), fd-leak cleanup across the three transports
+ ProcessACPChannel, ServerLiveStatus 10/30/60/120/300s exponential
backoff for unreachable remotes, and the print() -> os.Logger sweep.

APP_STORE_METADATA.md: full App Store Connect copy ready for paste —
app name, subtitle, promotional text (153/170 chars), 2873/4000-char
description in three paragraphs (what / features / privacy),
brand-safe keywords (85/100 chars; no competitor product names),
support / marketing / privacy URLs, category, age rating,
1150/4000-char "What's New" text. Screenshots flagged as out-of-scope
for this prep pass — user captures from the simulator before App
Store submission. TestFlight checklist remains the canonical doc for
the in-flight beta submission.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alan Wizemann
2026-04-25 17:12:27 +02:00
parent 87fcbad1ac
commit b1e2fc5dcd
3 changed files with 253 additions and 11 deletions
+31 -11
View File
@@ -21,27 +21,47 @@
## What's New in 2.5
- **ScarfGo, the iPhone companion, ships in public TestFlight.** Same Hermes server you've been running on your Mac — now reachable from your phone over SSH. Multi-server, project-scoped chat, session resume, memory editor, cron list, skills tree, settings (read), all native iOS. Pure-Swift SSH (Citadel under the hood — no `ssh` binary needed on iOS). Per-project chat writes the same Scarf-managed `AGENTS.md` block the Mac app does, so the agent boots with the same project context regardless of which client opened the session. **TestFlight invite + onboarding walkthrough:** [ScarfGo wiki page](https://github.com/awizemann/scarf/wiki/ScarfGo).
- **Portable project-scoped slash commands.** Author reusable prompt templates as Markdown files at `<project>/.scarf/slash-commands/<name>.md` with YAML frontmatter (name, description, argumentHint, optional model override). Invoke as `/<name> [args]` from chat — Scarf substitutes `{{argument}}` (with optional `default:` fallback) in the body and sends the expanded prompt to Hermes. Mac authoring tab + iOS read-only browser. Templates carry them via the new `slash-commands/` block in `.scarftemplate` bundles (schemaVersion 3).
### ScarfGo the iPhone companion ships in public TestFlight
Same Hermes server you've been running on your Mac — now reachable from your phone over SSH. Multi-server, project-scoped chat, session resume, memory editor, cron list, skills tree, settings (read), all native iOS. Pure-Swift SSH (Citadel under the hood — no `ssh` binary needed on iOS). Per-project chat writes the same Scarf-managed `AGENTS.md` block the Mac app does, so the agent boots with the same project context regardless of which client opened the session.
**[Join the public TestFlight](https://testflight.apple.com/join/qCrRpcTz)** — the link is live now but only accepts new beta testers once Apple's Beta Review approves the first build. If you hit a "not accepting testers" splash, bookmark it and try again in 2448h.
See the [ScarfGo wiki page](https://github.com/awizemann/scarf/wiki/ScarfGo) for the full feature tour, [ScarfGo Onboarding](https://github.com/awizemann/scarf/wiki/ScarfGo-Onboarding) for the SSH-key setup walkthrough, and [Platform Differences](https://github.com/awizemann/scarf/wiki/Platform-Differences) for what is and isn't shared between Mac and iOS.
### Everything else in 2.5
- **Portable project-scoped slash commands.** Author reusable prompt templates as Markdown files at `<project>/.scarf/slash-commands/<name>.md` with YAML frontmatter (name, description, argumentHint, optional model override). Invoke as `/<name> [args]` from chat — Scarf substitutes `{{argument}}` (with optional `default:` fallback) in the body and sends the expanded prompt to Hermes. Mac authoring tab + iOS read-only browser. Templates carry them via the new `slash-commands/` block in `.scarftemplate` bundles (schemaVersion 3). See [Slash Commands](https://github.com/awizemann/scarf/wiki/Slash-Commands) for the full schema.
- **Hermes v2026.4.23 chat parity.** `/steer` non-interruptive guidance command, per-turn stopwatch on assistant bubbles, numbered keyboard shortcuts (19) on the permission sheet, git branch chip in the chat header. The new `messages.reasoning_content` and `sessions.api_call_count` columns surface as a richer reasoning disclosure + an "API" chip on session rows.
- **Spotify + design-md skills.** Mac ships an in-app Spotify OAuth sheet (mirrors the v2.3 Nous Portal pattern); design-md gets a host-side `npx` prereq check on both platforms. SKILL.md frontmatter (`allowed_tools`, `related_skills`, `dependencies`) renders as chip rows. A "What's New" pill on the Skills tab tells you when remote skills changed since you last looked.
- **Mac global Sessions: project filter + project badges** — parity with ScarfGo's Sessions tab. The list grows a filter Menu (All projects / Unattributed / each registered project) and each row carries a tinted folder chip with the project name when attributed.
- **Human-readable cron schedules everywhere.** New `CronScheduleFormatter` in ScarfCore translates the common cron shapes into English phrases and falls back to the raw expression on anything custom. Mac and iOS render the same.
- **Mac design-system overhaul.** Rust palette, typed token bundle (`ScarfColor`, `ScarfFont`, `ScarfSpace`, `ScarfRadius`), reusable components (`ScarfPageHeader`, `ScarfCard`, `ScarfBadge`, `ScarfTextField`, four button styles), redesigned 3-pane chat. iOS adopts the same tokens with a hybrid Dynamic Type policy so accessibility scaling on body text is preserved. See [Design System](https://github.com/awizemann/scarf/wiki/Design-System) for the full reference.
- **Under the hood** — `SessionAttributionService`, `ProjectContextBlock`, `CronScheduleFormatter`, `GitBranchService`, `SkillPrereqService`, `SkillSnapshotService`, `ProjectSlashCommandService`, and the ACP error triplet (`acpError` / `acpErrorHint` / `acpErrorDetails`) consolidated into ScarfCore so Mac and iOS consume one source of truth. 179 tests across 13 suites, three consecutive green runs. Several `try?` swallows in iOS lifecycle code now surface real failures (Keychain unlock errors no longer drop people into onboarding; partial Forget operations report what failed).
- **iOS push notifications skeleton** — `NotificationRouter` ships with foreground presentation + a lock-screen "Approve / Deny" action category gated by `apnsEnabled = false`. Lights up when Hermes ships a server-side push sender + an APNs cert.
See the full [v2.5.0 release notes](https://github.com/awizemann/scarf/releases/tag/v2.5.0), the [ScarfGo wiki page](https://github.com/awizemann/scarf/wiki/ScarfGo), and [Platform Differences](https://github.com/awizemann/scarf/wiki/Platform-Differences) for what is and isn't shared between Mac and iOS.
See the full [v2.5.0 release notes](https://github.com/awizemann/scarf/releases/tag/v2.5.0).
### Previously, in 2.3
**Previous releases:** see the [Release Notes Index](https://github.com/awizemann/scarf/wiki/Release-Notes-Index) on the wiki for v2.3, v2.2, v2.0, v1.6, and earlier.
- **Projects sidebar grows up** — group projects into folders, rename / archive / unarchive in place, filter the list with ⌘F, jump to the first nine with ⌘1–⌘9. Archived projects hide by default; a toggle in the bottom bar surfaces them. Non-destructive on the v2.2 registry file — downgrade stays clean.
- **Per-project Sessions tab** — alongside Dashboard and Site. Shows chats attributed to the project, with a **New Chat** button that spawns `hermes acp` with the project's directory as the session cwd and attributes the result via a Scarf-owned sidecar (`~/.hermes/scarf/session_project_map.json`). Click any listed session to resume it with project context automatically restored.
- **Agent actually knows what project it's in** — the architectural headline. Every project-scoped chat gets a Scarf-managed block auto-injected into the project's `AGENTS.md` before the session starts. Hermes reads AGENTS.md from the session's cwd at startup and picks up the block as part of its system prompt. Ask the agent *"what project am I in?"* and it answers with the project name, directory, template id + version, configuration field names, and registered cron jobs — pulled from the injected block. Secret-safe (field names only, never values), idempotent, bounded to `<!-- scarf-project:begin/end -->` markers so template-author content outside the block is preserved across refreshes.
- **Project indicator in Chat** — folder chip in `SessionInfoBar` and `Chat · <ProjectName>` in the nav title when you're in a project-scoped chat. Resumed sessions keep the indicator by looking up the attribution sidecar at resume time.
- **Tool Gateway — Nous Portal support** — Hermes v0.10.0 introduced subscription-routed tools (web search, image gen, TTS, browser automation). Scarf 2.3 merges Hermes's provider-overlay table into the model picker so **Nous Portal + 5 other previously-invisible providers** now appear, and ships a dedicated **Sign in to Nous Portal** sheet that runs the device-code flow end-to-end in-app — no terminal. Each of the 8 auxiliary sub-model tasks gets a per-task Nous toggle, a Tool Gateway card lands in Health, and Credential Pools' silent-fail dead-end for device-code providers is closed. Scarf's existing messaging-gateway section is renamed **Messaging Gateway** to disambiguate from the new Tool Gateway.
- **Window-layout cleanup** — switching to Chat or a Sessions tab no longer grows the window past the screen. `.windowResizability(.contentMinSize)` + targeted `idealHeight` caps keep the window's floor at a sensible content minimum while letting users freely drag larger or smaller.
## Connect ScarfGo to your Hermes server
See the full [v2.3.0 release notes](https://github.com/awizemann/scarf/releases/tag/v2.3.0). Earlier release summaries (1.6 / 2.0 / 2.1 / 2.2) live at [Release Notes Index](https://github.com/awizemann/scarf/wiki/Release-Notes-Index) on the wiki.
ScarfGo speaks SSH directly — no companion service, no developer-controlled server in between. Onboarding takes about a minute:
1. **Install via TestFlight.** Open the [public TestFlight link](https://testflight.apple.com/join/qCrRpcTz) on your phone, accept the invite, install ScarfGo from TestFlight (just like any other beta).
2. **Tap Add Server.** Enter the host (IP or DNS), SSH user, port (default 22), and an optional nickname. Same details you'd type into `ssh user@host`.
3. **Generate Key.** ScarfGo creates a fresh Ed25519 keypair on the device. The private half lives in the iOS Keychain (`kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly`) and is excluded from iCloud sync — it never leaves the phone.
4. **Add the public key to your Hermes host.** Tap **Copy public key**, then on the host run:
```bash
cat >> ~/.ssh/authorized_keys <<'EOF'
<paste the line ScarfGo showed you>
EOF
chmod 600 ~/.ssh/authorized_keys
```
This is its own line per device — the convention any second SSH client uses. Mac (Scarf) keeps using your existing ssh-agent / `~/.ssh/config` and is unaffected.
5. **Tap Test connection.** ScarfGo opens an SSH session, probes for the `hermes` binary, and saves the server on success. If it can't find `hermes`, see the [troubleshooting section](https://github.com/awizemann/scarf/wiki/ScarfGo-Onboarding#troubleshooting) — it's almost always a `PATH` quirk on non-interactive SSH.
Done. Open the Dashboard tab and tap any session to resume it; tap the **+** in Chat to start a new project-scoped session.
## Multi-server, one window per server
+218
View File
@@ -0,0 +1,218 @@
# ScarfGo — App Store Connect submission copy
Single source of truth for every field you paste into App Store Connect → My Apps → ScarfGo. TestFlight-specific fields (Beta App Description, "What to test") live in [TESTFLIGHT_CHECKLIST.md](TESTFLIGHT_CHECKLIST.md). This file covers the full App Store listing for when ScarfGo graduates from TestFlight to the public store.
All character counts are pre-counted against Apple's published limits. Counts include trailing punctuation but exclude the leading `> ` Markdown blockquote markers.
## App information (set once, persists across builds)
### App name (max 30 chars)
```
ScarfGo
```
_7 / 30 chars._
### Subtitle (max 30 chars)
```
On-the-go Hermes companion
```
_26 / 30 chars._
### Bundle ID
```
com.scarfgo.app
```
### Primary category
Developer Tools
### Secondary category (optional)
Productivity
### Age rating
4+ (no restricted content)
### Support URL
```
https://github.com/awizemann/scarf/wiki/Support
```
### Marketing URL (optional)
```
https://github.com/awizemann/scarf
```
### Privacy Policy URL
```
https://awizemann.github.io/scarf/privacy/
```
### Copyright
```
© 2026 Alan Wizemann
```
### Trade representative information
Not required for sole-developer accounts.
---
## Per-version metadata (resubmit on each App Store release)
### Promotional text (max 170 chars, editable without resubmission)
```
Manage your Hermes AI agent from your phone. Connect to any SSH-reachable Hermes host, run sessions, edit memory, browse cron jobs, resume conversations.
```
_153 / 170 chars._
### Description (max 4000 chars)
```
ScarfGo is the iPhone companion to Scarf, the open-source macOS GUI for the Hermes AI agent. It connects from your phone to a Hermes server you operate — your Mac, a home Linux box, a cloud VM, anything reachable over SSH — and lets you run sessions, browse memory, manage cron jobs, and resume conversations on the go.
A fully native iOS app, not a web view or a remote desktop. ScarfGo speaks SSH directly using a pure-Swift implementation, reads Hermes state via SFTP and SQLite snapshots, and streams real-time agent output over the Agent Client Protocol on a long-lived SSH exec channel. Every byte stays between your device and the Hermes host you configured.
What you can do:
• Multi-server. Configure as many Hermes hosts as you like and switch between them with a tap. Soft Disconnect keeps your credentials cached; Forget wipes a server end-to-end.
• Dashboard. Stats and the 25 most recent sessions, with project badges so you can tell at a glance which work is which.
• Project-scoped chat. Pick a project from your registry and ScarfGo writes the same Scarf-managed AGENTS.md context block the Mac app does, so the agent boots with the right project context. The resulting session is attributed correctly across both clients.
• Session resume. Tap any row on the Dashboard to open that session's transcript in Chat. CLI-started sessions hydrate from the Hermes state database; ACP sessions show an empty-state because Hermes does not persist ACP transcripts to the database.
• Memory editor. Read and edit MEMORY.md and USER.md with a Saved indicator that survives keyboard dismissal and a one-tap Revert.
• Cron list. Human-readable schedules ("Every 6 hours", "Weekdays at 09:00") instead of raw cron expressions, plus a relative next-run estimate. Read-only in this release; editing comes in a future update.
• Skills browser. Read-only category tree with the SKILL.md frontmatter chips (allowed tools, related skills, dependencies) the Mac app shows.
• Settings viewer. Read-only inspection of your config.yaml. Edit values from the Mac app or a remote shell.
Privacy. ScarfGo does not collect, transmit, or store your data on any server controlled by the developer. There are no analytics, no telemetry, no ad identifiers. SSH keys are generated on-device and stored in the iOS Keychain with the ThisDeviceOnly attribute, so they are unreachable while the device is locked and never sync to iCloud. The complete privacy policy lives at awizemann.github.io/scarf/privacy.
Open-source under the MIT license. Source, issue tracker, and contributor docs at github.com/awizemann/scarf. Bug reports tagged component:scarfgo go straight to the developer.
Requirements. iOS 18.0 or later. An SSH-reachable Hermes server (Hermes v0.10.0 or later recommended; full v0.11.0 features supported). Your phone needs to reach that server on the network — same Wi-Fi, VPN, Tailscale, or any port-forwarded address SSH can dial.
```
_2873 / 4000 chars._
### Keywords (max 100 chars, comma-separated, no spaces between terms)
```
hermes,ai agent,ssh,terminal,llm,assistant,developer tools,coding,remote,monitor,chat
```
_85 / 100 chars._
Brand-safe — no competitor product names. Apple flags trademarks like "Claude" or "OpenAI" as unauthorized brand use during review even when they appear as descriptive context.
### What's New text (max 4000 chars)
For v2.5.0 — first public App Store release. Trimmed from `RELEASE_NOTES.md`'s ScarfGo section to fit the iOS audience.
```
First public release of ScarfGo, the iPhone companion to the Scarf macOS app.
What's in this release:
• Multi-server. Configure multiple Hermes hosts and switch between them with a tap.
• Dashboard. Sessions, messages, and tool-call counts, plus the 25 most recent sessions with project badges and a project filter.
• Chat. Streamed agent responses over SSH with tool-call disclosure groups, code blocks, and project-scoped session start.
• Session resume. Tap any session on the Dashboard to open it in Chat.
• Memory editor. Read and edit MEMORY.md and USER.md with on-device save indication and one-tap Revert.
• Cron list. Human-readable schedules ("Every 6 hours", "Weekdays at 09:00") with relative next-run.
• Skills browser. Read-only category tree with SKILL.md frontmatter chips.
• Settings viewer. Read-only inspection of config.yaml. Edit values from the Mac app.
Known limitations in v1: no push notifications (the skeleton is in the binary, gated behind an internal flag pending Apple Developer Program enrollment and an APNs key); no in-app config editor; no template install UI; English only. iPad layout works via the system sidebar adaptive style but has not been polished — feedback welcome via TestFlight.
Privacy. No analytics, no telemetry, no developer-controlled servers. Read the full policy at awizemann.github.io/scarf/privacy.
```
_1150 / 4000 chars._
### Build (autopopulated)
Apple fills this in once the binary uploads + processes. The same build that went through TestFlight Beta Review is the one you ship to the public store.
### Version
Marketing version: `2.5.0` — the same number `release.sh` will write to `MARKETING_VERSION` for the macOS Scarf release. Keeping the iOS + Mac versions in lockstep is the convention this project uses.
---
## Build artifact
### App icon (1024×1024)
```
scarf/Scarf iOS/Assets.xcassets/AppIcon.appiconset/AW Mac OS Applications-macOS-Default-1024x1024@1x.png
```
The full appiconset is in repo and the Xcode target references it via `AppIcon`. App Store Connect pulls the 1024 from the binary on upload — no separate upload step.
### Screenshots
**Required for the public App Store, NOT required for TestFlight.** Scope deliberately excluded from this prep pass — capture from the simulator before flipping the App Store listing live. Apple requires:
- iPhone 6.7" (e.g. iPhone 16 Pro Max) — at least 5, up to 10
- iPhone 6.5" (e.g. iPhone 14 Plus) — at least 5, up to 10
- iPhone 5.5" (e.g. iPhone 8 Plus) — at least 5, up to 10
- iPad — only if you flip the iPad flag in the target. Skip for v2.5.
Suggested screen captures (rough order):
1. Dashboard with stats + recent sessions list
2. Chat in mid-stream with a tool-call disclosure expanded
3. Project picker sheet
4. Sessions tab with project filter active
5. Memory editor with Saved indicator
6. Skills detail with frontmatter chips visible
7. Server list (showing multi-server)
8. Onboarding step 5 (public-key display)
### App preview video (optional)
Skip for v1. Apple will accept the listing without it.
---
## Beta App Review (TestFlight) — already submitted
Cross-reference [TESTFLIGHT_CHECKLIST.md](TESTFLIGHT_CHECKLIST.md). Once Apple's Beta Review approves the first build, the public TestFlight URL `https://testflight.apple.com/join/qCrRpcTz` accepts new joiners. Until then the link 404s with a "not accepting testers" splash.
## Public App Store submission flow (after TestFlight stabilizes)
1. App Store Connect → My Apps → ScarfGo → App Store tab → iOS App.
2. Paste every field above into the matching form.
3. Set the build to the same one that's been on TestFlight (Apple lets you reuse a TestFlight build verbatim — no re-upload).
4. Submit for review. Apple's standard App Review queue (separate from Beta Review) is typically 2472h. Watch your inbox for "We have a question" emails and reply via App Store Connect's review-team chat.
5. On approval, choose "Manually release this version" so you can announce on a schedule.
## Update cadence
The same `releases/v<VERSION>/` directory pattern this file lives in is the canonical staging area for every future iOS release. When v2.6 (or whatever ships next) bumps the iOS app, copy this file forward and update:
- **Promotional text** — refreshed marketing wedge.
- **What's New text** — what changed since the last App Store release.
- Everything else above stays unless you're changing categories, support URL, or privacy stance.
The Mac `release.sh` does not yet drive the iOS release — that's a separate Xcode Archive + App Store Connect upload. See `TESTFLIGHT_CHECKLIST.md` Phase 4 for the archive flow.
+4
View File
@@ -83,6 +83,10 @@ Pre-2.5, both Mac and iOS rendered cron jobs as `0 */6 * * *` raw. The new `Cron
- **`RichChatViewModel`** carries the ACP error triplet (`acpError`, `acpErrorHint`, `acpErrorDetails`) for both platforms — Mac's `ChatViewModel` now delegates instead of duplicating.
- **Test reliability.** Cross-suite races on `ServerContext.sshTransportFactory` resolved by consolidating every factory-touching test into a single `.serialized` suite. 163 tests across 12 suites, three consecutive green runs.
- **Surface silent failures.** Several `try?` swallows in iOS lifecycle code now surface to the user — Keychain unlock errors no longer dump people back into onboarding, partial Forget operations report what failed, project-context-block writes that fail surface a banner instead of silently degrading agent context.
- **iOS exec channel hardening.** `CitadelServerTransport.runProcess` was wrapping Citadel's `executeCommand`, which throws `CommandFailed` on non-zero exit and discards the captured stdout buffer in the throw path. `hermes skills browse` happens to print its full table and *then* exit non-zero on some hosts, so iOS got nothing while Mac (Foundation `Process`) got the full output with `exitCode=1`. v2.5 drives `executeCommandStream` directly, drains stdout + stderr regardless of outcome, and recovers the actual exit code from the `CommandFailed` catch. Same channel now also inline-prepends `PATH="$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"` on every invocation — Citadel's raw exec channel doesn't source the user's shell rc files, so non-interactive sessions land with a stripped `PATH` (`/usr/bin:/bin`) and pipx's default install dir is invisible. Mac's OpenSSH sshd handles this transparently; we now match.
- **fd-leak cleanup.** `LocalTransport` / `SSHTransport` / `ProcessACPChannel` all close the parent's copy of every pipe write end after spawn so EOF reaches the reader once the child exits, plus close read ends after draining. Was leaking one fd per `runProcess` / `streamLines` / ACP turn under load.
- **Status-poll backoff.** `ServerLiveStatus` now uses 10s → 30s → 60s → 120s → 300s exponential backoff on consecutive probe failures, resetting on the first full success. Previously a registered remote going unreachable hammered `pgrep` + `gateway_state.json` every 10s indefinitely; offline servers now settle to a 5-minute cadence while live ones stay snappy.
- **Logger conversion.** Remaining `print("[Scarf] …")` debug statements in `HermesDataService`, `HermesLogService`, and `ProjectDashboardService` swap to `os.Logger` calls (subsystem `com.scarf`), matching the global rule that production code uses `Logger` and `print()` is reserved for previews + test helpers.
### Notes for users running 2.3