Phase 8 of the v2.5 plan — fold the Hermes v2026.4.23 integration into
the existing v2.5 release artifacts rather than creating a v2.6 set.
releases/v2.5.0/RELEASE_NOTES.md:
- Lead paragraph extended to mention slash commands, chat parity,
Spotify, design-md.
- Six new sections: Portable project-scoped slash commands, Hermes
v2026.4.23 chat parity, Spotify + design-md skill onboarding,
SKILL.md frontmatter chips, "What's New" pill, state.db deltas,
hermes memory reset.
- All inserted before the existing "Mac global Sessions" section so
the Hermes-v0.11 work reads as the headline alongside ScarfGo.
README.md:
- "What's New in 2.5" lead bullets gain slash commands, Hermes v0.11
chat parity, Spotify+design-md, SKILL.md chips, snapshot pill.
- Test count bumped 163 → 179.
- Requirements: Hermes recommended bumped from v0.10.0+ to v0.11.0+
with feature attribution.
- Compatibility table: v0.11.0 row added as the current target;
v0.10.0 row demoted to "Tool Gateway introduced".
- Targeting paragraph rewritten for v2.5/v0.11.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Authored locally (not pushed). Phase D of the v2.5 release plan needs:
- A privacy policy at a stable URL before App Store Connect lets you
submit for Beta App Review.
- A pre-flight checklist so the Xcode + App Store Connect dance
doesn't lose state.
`scarf/docs/PRIVACY_POLICY.md` — minimal, accurate. The apps don't
collect data on developer-controlled servers (no analytics, no
telemetry, no ads, no IDFA). Covers SSH credentials, Hermes state
cache, the project + attribution sidecars, the network connections the
apps make. Ready to host on gh-pages at /privacy/ when the user opts to
push it.
`releases/v2.5.0/TESTFLIGHT_CHECKLIST.md` — step-by-step from Apple
Developer Program prerequisites through Beta Review submission, with a
beta-description copy block, "What to test" copy, and a rollback note.
Explicitly calls out NOT bumping versions manually (release.sh does it
in Phase G) and NOT enabling Push Notifications until APNs cert +
sender land together.
Both files stay local until the user pushes them — the checklist is
the user's reference, the privacy policy gets copied into the
gh-pages worktree when ready to submit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Authored before `release.sh` so it gets included in the version-bump
commit auto-generated by the script in Phase G.
Highlights: ScarfGo iOS public TestFlight, Mac Sessions project filter
+ badges (parity with ScarfGo's Sessions tab), human-readable cron
schedules cross-platform, shared-services refactor, silent-failure
hardening on the iOS lifecycle, test-suite consolidation that fixes the
cross-suite factory races we hit during pre-release verification.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v2.3 now lands two themes together: Projects Grow Up (existing) and
Hermes v0.10.0 Tool Gateway support (new, just merged on the feature
branch). The release notes and the repo README's "What's New" section
are updated to reflect both.
Release notes:
- Headline intro rewritten to frame both themes as the v2.3 story.
- New "Tool Gateway — Nous Portal support" section between "Icon
tweak" and "Migrating from 2.2.x": picker overlay merge surfacing 6
previously-invisible providers, in-app device-code sign-in sheet,
per-task Nous routing in the Auxiliary tab, Health card, Credential
Pools dead-end fix + auth-type gating, Messaging Gateway rename.
- "Under the hood" gains the Tool Gateway services paragraph
(NousSubscriptionService, NousAuthFlow, NousSignInSheet,
CredentialPoolsOAuthGate) + the PYTHONUNBUFFERED=1 subprocess-env
fix note. Test count bumped from 93 → 120 (14 new tests in
ToolGatewayTests, NousAuthFlowParserTests, CredentialPoolsGatingTests).
- "Migrating from 2.2.x" gains a Hermes version paragraph spelling
out that v0.10.0 is required for the Tool Gateway features (rest
of 2.3 works on earlier Hermes, just without Nous in the picker
or subscription data in Health).
- "Documentation" section lists the new Hermes Version Compatibility
+ Core Services wiki updates that accompany this release.
README:
- v2.3 "What's New" bullet list gains a Tool Gateway bullet
positioned between the chat-indicator bullet and the window-layout
bullet.
- Trailing "See the full release notes" line expanded to reference
the Hermes Version Compatibility wiki page so users on Hermes v0.9
know why they don't see Nous in their picker.
Companion wiki update already pushed in 741b253 on the wiki repo
(Hermes-Version-Compatibility, Core-Services, Home).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Prep commit for the v2.3 release. Covers the 16 feature + fix
commits landed on the v2.3-projects branch:
- releases/v2.3.0/RELEASE_NOTES.md — new file. release.sh picks
this up automatically as the GitHub release body at tag time.
Sections: sidebar grows up (folders/rename/archive/search/
keyboard jumps), per-project Sessions tab + sidecar, the
AGENTS.md marker-block injection (with the invariants —
secret-safe, idempotent, bounded, non-fatal, bare-project
friendly — called out explicitly), chat-UI project awareness
(folder chip + nav title), window-layout cleanup, under-the-
hood (new services, 22 new tests), migration, thanks.
- README.md — "What's New in 2.3" block at the top; demotes
the prior 2.2 block to "Previously, in 2.2" (condensed to the
four most user-facing points since the full 2.2 notes live at
the release link).
- Localizable.xcstrings — Xcode auto-regen from the new string
literals introduced across the v2.3 feature commits (folder
chip tooltip, Sessions tab header, etc.). Riding along.
93/93 Swift tests still pass. No code change here — pure docs.
Wiki Home + Release-Notes-Index updates land as a separate
wiki commit after the release is cut (standard post-release
chore per CLAUDE.md).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Covers the four commits landed since v2.2.0:
- New catalog template: awizemann/template-author (scaffolding skill)
- Config sheet fix: EnumControl always uses Menu picker, not Segmented
(the long-option-label overflow that clipped the form)
- Config sheet fix: maxWidth constraint on inner VStacks so descriptions
with unbreakable tokens wrap cleanly
- SKILL.md authoring guidance: prefer markdown link syntax over raw URLs
- Devops: scripts/catalog.sh accepts git worktrees
release.sh picks up this file as the GitHub release body.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The pre-existing release notes and README "What's New in 2.2" block
only covered the original Project Templates feature. This expands
both to reflect everything that's actually shipping in 2.2:
- Template Configuration (schemaVersion 2): typed schema, 7 field
types, Keychain-backed secrets, configure step in install flow,
post-install Configuration editor, model recommendations.
- Template Catalog: gh-pages site with live dashboard previews,
stdlib-only Python validator mirroring Swift invariants, PR CI
gate, install-URL hosting from raw main.
- Example template `awizemann/site-status-checker` exercising every
v2.2 surface — config form, cron, Site tab webview, dashboard
updates.
- Site tab — a webview widget in any dashboard exposes a second
tab next to Dashboard, rendering a live URL.
- UX clarifications: Remove from List (keep files) vs. Uninstall
Template (remove installed files), preserved-files banner on
uninstall success, Run Now no longer blocks on long agent runs.
- Install-time {{PROJECT_DIR}} / {{TEMPLATE_ID}} / {{TEMPLATE_SLUG}}
token substitution in cron prompts.
Release-notes link + wiki link surfaced at the bottom of the README
block so readers have a jump to full details.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First installable template demonstrating the format:
- Dashboard with stat widgets (up/down/last-checked) + configured-sites
list + quick-start markdown.
- Cross-agent AGENTS.md with the full cron-prompt contract so any agent
that reads agents.md (Claude Code, Cursor, Codex, Aider, Jules,
Copilot, Zed, …) picks up the behavior on first run.
- Cron job (0 9 * * *) that ships paused with the [tmpl:…] tag, pinging
a user-editable sites.txt and writing results to status-log.md.
- First-run bootstrap logic in AGENTS.md: if sites.txt doesn't exist
yet the agent creates it with two placeholder URLs, then proceeds.
Plus examples/templates/README.md explaining the staging/ layout,
authoring conventions, and how to rebuild a bundle after editing. CI
validates the bundle via ProjectTemplateExampleTemplateTests so drift
between staging/ and the built .scarftemplate fails on every build.
v2.2.0 release notes cover the full feature surface including the
install preview sheet, scarf:// + file:// URL handling, skills
namespacing, cron-job tagging, memory-block markers, and the
lock-driven uninstall flow.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-release prep so that when `./scripts/release.sh 2.1.0` runs on main,
the notes file is already in tree (script's `git add` is then a no-op,
bump commit contains only the pbxproj version change).
- README gains a 2.1 "What's New" section covering translations + the
chat slash-menu; 2.0 moves down to "Previously".
- Badge row gains a language list line.
- Full release notes at releases/v2.1.0/RELEASE_NOTES.md — covers the
three stacked i18n PRs (infra, audit burn-down, translations) and the
chat slash-menu work merged in parallel.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reflect the three post-initial-commit fixes:
- log-noise suppression (skill.yaml / optional-file 'No such file'
warnings no longer spam Console via the new Result-returning readers)
- diagnostics script now stdin-pipes to sh -s instead of sh -c <script>
argv, so it runs as one sh process with variable scope preserved
- pill UX: replaced colored dot with state-specific SF Symbol
(checkmark / stethoscope / arrows / triangle), removed custom
background, kept .principal placement for centering
Also expanded the 'Known follow-ups' section so users know what's
explicitly deferred post-2.0.1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three users reported on day-one of v2.0 that SSH connections showed a
green "Connected" pill but every data view read as empty / "not running"
/ "not configured". The common thread across Docker, homelab VM, and
Ubuntu VPS setups: file-access failures on the remote that Scarf
silently swallowed into nil/empty defaults.
Stop swallowing errors
- HermesFileService gains Result-returning variants for the four
dashboard-critical readers: loadConfigResult, loadGatewayStateResult,
hermesPIDResult, plus readFileResult / readFileDataResult as
primitives. Each logs os.Logger warnings on failure. Legacy nil-
returning signatures remain as thin forwarders.
- HermesDataService.open records lastOpenError with humanized hints
for the top three failure modes — sqlite3 not installed, permission
denied, file not found. Each maps to concrete remediation (`apt
install sqlite3`, "check file perms", "set Hermes data directory").
Dashboard surfaces the error
- DashboardViewModel collects errors from every loader into
lastReadError, only on remote contexts (local skips the banner).
- DashboardView renders an orange banner above the stats with the
specific error text, a copy-selectable detail, and a "Run
Diagnostics…" button.
New Remote Diagnostics sheet (stethoscope icon)
- RemoteDiagnosticsViewModel runs 14 checks in one SSH round-trip via
a pipe-delimited "KEY|STATUS|DETAIL" protocol. Covers: SSH
connectivity, remote user/$HOME, Hermes dir existence + readability,
config.yaml readability + actual read (distinct from just `test -e`
which can't detect permission issues), state.db readability, sqlite3
binary presence, sqlite3 open test, hermes binary on non-login AND
login PATH, pgrep availability.
- Each probe row shows a targeted hint on fail (e.g. "check perms on
~/.hermes", "apt install sqlite3", "move PATH export from .bashrc
to .zshenv"). A Copy Full Report button dumps plain-text output
for GitHub issues.
- Accessible from Manage Servers (stethoscope button per row) and
directly from the yellow pill.
Yellow "degraded" connection state
- ConnectionStatusViewModel.Status gains .degraded(reason:) between
.connected and .error. After tier-1 `true` passes, the probe runs
tier-2 `test -r $HOME/.hermes/config.yaml` in the same SSH round-
trip. On tier-2 fail, pill is orange with "Connected — can't read
Hermes state" tooltip.
- Clicking a degraded pill opens Remote Diagnostics directly. Exactly
the symptom in #19 is now one click from a specific answer.
Auto-suggest remoteHome for non-default installs
- TestConnectionProbe.TestResult.success gains suggestedRemoteHome:
String?. When state.db isn't found at the configured path, the
probe also checks /var/lib/hermes/.hermes, /opt/hermes/.hermes,
/home/hermes/.hermes, /root/.hermes — the common alternates for
systemd services, Docker containers, and single-user VPSes — and
surfaces the first hit as a "Use this" suggestion in Add Server.
- AddServerSheet relabels "Remote ~/.hermes override" to "Hermes data
directory" with an explanation of when you'd use it.
README
- New "Remote setup requirements" subsection lists the four concrete
prereqs (SSH, sqlite3, pgrep, read access to ~/.hermes).
- New "Troubleshooting remote connections" paragraph describes the
diagnostics sheet and remoteHome auto-suggest for the two most
common failure modes.
Releases
- releases/v2.0.1/RELEASE_NOTES.md for the GitHub release body.
- Ship via `./scripts/release.sh 2.0.1`.
Closes#19.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The multi-window / multi-server / remote-SSH work that landed in
00ca722 (feat: multi-window + remote SSH server support (Phases 0-4))
was feature-complete but accumulated rough edges during dogfooding
against a remote Mac mini. This commit finishes the 2.0 release:
correctness fixes on remote, a chat-view UX overhaul, and a Swift 6
complete-concurrency sweep across the service layer.
Correctness on remote
- Kill the WAL-error spam: snapshotSQLite now runs `PRAGMA
journal_mode=DELETE` on the remote temp DB before scp, so the
pulled file is self-contained. Open remote snapshots with
`file:...?immutable=1` URI as defense-in-depth, and drop the
pointless `PRAGMA journal_mode=WAL` from HermesDataService.open.
- loadSessionHistory and refreshMessages now force a fresh snapshot
via refresh(), so resuming a session on a remote shows messages
persisted since launch (previously stuck on the first snapshot).
- New SnapshotCoordinator actor dedupes concurrent snapshotSQLite
calls per ServerID — Dashboard + Sessions + Activity no longer
issue three parallel SSH backups for the same fetch.
- ACP cwd comes from the remote's $HOME (probed once, cached per
server in UserHomeCache), not the local Mac's NSHomeDirectory().
- Typing into a blank Chat always creates a new session. The old
auto-resume-most-recent fallback was picking up cron-spawned
sessions that Hermes had already GC'd, producing silent prompt
failures.
- handlePromptComplete surfaces non-success stopReasons ("refusal",
"error", "max_tokens") as a system message so failed prompts no
longer sit under a forever-spinning "Agent working…".
Chat UX
- Replace six racing onChange-driven scrollTo calls with
`.defaultScrollAnchor(.bottom)` alone. Manual proxy.scrollTo
against a LazyVStack that hadn't finished laying out was
overshooting into whitespace. Layout-pass-integrated anchor
behaves correctly at stream start and finish.
- Remove ContentUnavailableView swap in RichChatView — it tore down
the whole ScrollView hierarchy on first message. Empty state now
lives inside the scroll view.
- continueLastSession surfaces an acpError banner if open() fails,
instead of silently returning.
Lifecycle hygiene
- ServerRegistry.removeServer closes the server's SSH ControlMaster
(`ssh -O exit`), prunes its snapshot cache dir, and invalidates
UserHomeCache for that ID. App launch sweeps orphan snapshot dirs
whose UUIDs aren't in the registry anymore.
- NSWorkspace.activateFileViewerSelecting (backup-saved-to dialog)
gated on !context.isRemote; remote surfaces the remote path in the
saveMessage instead of silently no-op'ing on a nonexistent local
path.
Swift 6 concurrency — 230 warnings → 1
- Mark ServerContext, HermesPathSet, ServerTransport (protocol),
LocalTransport, SSHTransport, HermesFileService, and every value-
type accessor as `nonisolated`. Prevents AppKit-import-driven
MainActor inference from bleeding onto data-only types.
- Hand-written Codable conformances (vs. synthesized) for
ACPRequest, ACPRawMessage, ACPError, GatewayState, PlatformState,
HermesCronJob, CronSchedule, CronJobsFile, AuthFile, AuthEntry.
Synthesized inits were inferred @MainActor by Swift 6's default-
isolation rule; hand-written ones are explicitly nonisolated.
- Captured-var refactors in MCPServerEditorViewModel, PluginsView
Model, LocalTransport.watchPaths. Thread.sleep → Task.sleep in
TestConnectionProbe.
- Remaining warning is AnyCodable.value mutation in init(from:) —
Any-typed storage can't be strictly Sendable; acknowledged via
@unchecked Sendable.
ACP adapter upstream bug (not fixed here, but handled)
- Hermes's ACP adapter returns JSON-RPC success `{"result":{}}` for
session/load on a missing session, logging the warning only to
stderr. Scarf can't distinguish "loaded" from "silently missing"
at that layer; the stopReason=refusal surfacing above catches the
downstream symptom. Upstream issue worth filing.
Release docs
- releases/v2.0.0/RELEASE_NOTES.md with full user-facing breakdown.
- README.md "What's New" bumped to 2.0 with a multi-server section.
Compatibility table adds v0.10.0 as verified.
- GitHub repo description updated (via `gh repo edit`) to call out
multi-server + remote SSH.
35 files changed, +809/-350.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drafts skip the appcast push and main tag, so a draft release won't
show up in users' Sparkle update feed and v1.6.0 stays "latest" until
explicitly promoted. The signed appcast entry is saved to the release
dir for later manual promotion.
Also adds release notes file convention: releases/v<VERSION>/RELEASE_NOTES.md
is auto-included in the version-bump commit and used as the GitHub
release body.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reorganize the Features section to match the app's sidebar (Monitor, Interact,
Configure, Manage, Project Dashboards, System) so readers find features the
same way they find them in the app. Add a "What's New in 1.6" callout with
links to the release notes.
Binaries: ARM64 (15 MB) and Universal (19 MB). Both signed with the Apple
Development identity (Team 3Q6X2L86C4). Universal contains both arm64 and
x86_64 slices verified with lipo.
Two related bugs surfaced when testing MCP servers that spawn npx, node,
python, etc. from Homebrew/nvm/asdf/mise installs.
1. MCP test reported success even when the connection failed.
`hermes mcp test <server>` exits 0 even when the inner connection
fails — it prints the error to stdout instead. Scarf trusted the
exit code and rendered a green checkmark while the output said
"✗ Connection failed: [Errno 2] No such file or directory: 'npx'".
Fix: also scan output for ✗, "Connection failed", "No such file or
directory", and "Error:" markers.
2. .app launches start with a minimal PATH that excludes Homebrew.
When Scarf is launched from Finder/Dock, ProcessInfo's PATH is
`/usr/bin:/bin:/usr/sbin:/sbin` — no /opt/homebrew/bin, no
/usr/local/bin, no nvm/asdf/mise shims. Hermes inherits this and
can't find npx/node/python when spawning MCP server subprocesses.
Fix: query the user's login shell PATH once via `/bin/zsh -lc 'echo
$PATH'`, cache it on HermesFileService, and inject it into both
`runHermesCLI` and the ACP subprocess. Falls back to a sane default
covering both Apple Silicon and Intel Homebrew if zsh query fails.
Bumps version to 1.5.8 (build 10). Includes signed Universal + ARM64
binaries.
Fixes a bug where adding a second MCP server caused the first to disappear
from the list view, and any args containing YAML reserved characters (e.g.
"@modelcontextprotocol/server-fetch") corrupted the config file.
Three root causes in HermesFileService MCP YAML patching:
1. extractMCPBlock extended through trailing comments to EOF when
mcp_servers was the last top-level key in config.yaml. Trailing
comments became part of the "block", so subsequent inserts landed
at end-of-file rather than inside the entry.
2. patchMCPServerField's entry boundary similarly absorbed trailing
blanks/comments, making the entry "own" everything until the next
sibling — or until EOF for the last entry.
3. yamlScalar did not quote values starting with YAML reserved
indicators (@ * & ? | > ! % , [ ] { } < ` ' "). Args like
"@modelcontextprotocol/server-fetch" were written bare, producing
invalid YAML that broke subsequent reads/writes.
Fix: trim trailing blanks/comments off both the block and the entry
in the locator/extractor; quote any scalar starting with a reserved
first character.
Bumps version to 1.5.7 (build 9). Includes signed Universal + ARM64
binaries.
Note: users with an already-corrupted ~/.hermes/config.yaml from the
1.5.6 bug should manually clean up their mcp_servers block (delete the
orphan args at end of file) before upgrading. New writes will be clean.
The first 1.5.6 zips contained `linker-signed` bundles with no Sealed
Resources, plus a stray nested scarf.app from a case-insensitive cp.
macOS Gatekeeper rejected the ARM64 download as "damaged"; the
Universal one ran only because the user had already trusted it.
Now both bundles are properly ad-hoc-signed (`Sealed Resources
version=2`) with the hardened runtime preserved. Sizes dropped
significantly (Universal 33MB→16MB, ARM64 27MB→13MB) because the
nested junk is gone.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Includes the MCP Servers management UI shipped in 219bca2:
- Add via curated presets (GitHub, Linear, Notion, Sentry, Stripe, …)
or fully custom (stdio command + args, or HTTP URL with bearer auth)
- Per-server detail view: enable/disable, env + headers editor,
tool include/exclude filters, resources/prompts toggles, request
and connect timeouts, OAuth token detection + clearing
- One-click "Test Connection" runs `hermes mcp test` and surfaces
the discovered tool list
- Gateway-restart banner after config changes that need a reload
README updated with the MCP Servers section, the new MCPServers/
feature module entry, and the `hermes mcp` + `mcp-tokens/` entries
in the Data Sources table.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ship Hermes v0.9.0 compatibility plus new features (log component
filter, session pill, Fast Mode, Backup/Restore, iMessage, /compress,
Discord threads). README lists both universal and ARM64 downloads.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>