Rolls up everything since v2.6.5 (36 commits across remote-perf,
project wizard, dashboard widgets, OAuth resilience, ScarfMon
instrumentation, and the v2.7 skeleton-then-hydrate redesign) into
a single 2.7.0 release.
* releases/v2.7.0/RELEASE_NOTES.md — full consolidated notes,
reorganized around the throughline (slow-remote performance) with
five thematic sections: skeleton-then-hydrate loaders, SSH
cancellation, project wizard + Keychain cron secrets, dashboard
widgets, OAuth resilience, and ScarfMon. Replaces the previously-
drafted dashboard-only v2.7.0 stub and the separate v2.8 wizard
stub (both unreleased).
* releases/v2.8/ — deleted; folded into v2.7.
* README.md — "What's New in 2.6" → "What's New in 2.7" with the
five-section summary linking out to the full notes.
* tools/render-release-notes.py — stdlib-only Markdown → HTML
renderer covering the subset of GitHub-flavored markdown that
release notes use (## / ### headings, paragraphs, ul lists,
fenced code, inline code/bold/italic/links, hr). Output includes
a small <style> block tuned for Sparkle's update alert WebKit
view (light + dark variants via prefers-color-scheme).
* scripts/release.sh — render the active RELEASE_NOTES.md and
inject the result as <description><![CDATA[...]]></description>
on the appcast item. Sparkle's standard updater renders this in
the in-app update sheet so users see release-specific "what's
new" alongside the version number, not just the bare version.
Falls back to a "see GitHub release page" placeholder when the
notes file is missing.
User runs ./scripts/release.sh 2.7.0 to ship.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three coordinated additions to the project surface:
1. New Project from Scratch wizard. Toolbar entry that scaffolds a
Scarf-standard project skeleton (`<project>/.scarf/dashboard.json`
placeholder + `AGENTS.md` marker block), registers it, opens an ACP
chat session in the project's cwd, and auto-sends a kickoff prompt
that activates the bundled `scarf-template-author` skill. The skill
drives the substantive setup conversationally — widgets, optional
config schema, optional cron, AGENTS.md content.
2. Keychain secrets mirror into ~/.hermes/.env. Cron jobs can now
reference Keychain-backed config values via env vars named
`SCARF_<UPPER_SLUG>_<UPPER_FIELDKEY>`. Hermes reloads .env per cron
tick (cron/scheduler.py:897-903), so credential rotation is free.
Source of truth stays in the Keychain — config.json keeps
`keychain://` URIs unchanged. Mirror runs at install, post-install
Configuration save, uninstall, "Remove from List", and on app
launch (reconcileAll). Mode 0600 on `.env` enforced by
LocalTransport's existing `.env` heuristic.
3. Configuration form layout recursion fix (issue #75). Per-stage
frame sizes on `ConfigEditorSheet` triggered
`_NSDetectedLayoutRecursion` for projects with manifest.json.
Stabilized the outer frame at the editing stage's intrinsic size so
transitions only swap content, never resize the container.
New services:
- `ProjectScaffolder` (Mac) — bare-shell project + AGENTS.md marker
- `SkillBootstrapService` (Mac) — copies bundled skills into ~/.hermes/skills/
- `KeychainEnvMirror` (Mac) — splice/unmirror/reconcileAll over ~/.hermes/.env
- `SecretsEnvBlock` (ScarfCore) — pure marker-block helpers
Bundled skill `scarf-template-author` v1.1.0 ships in
`Resources/BuiltinSkills.bundle/`; SkillBootstrapService copies it
into `~/.hermes/skills/scarf-template-author/` on launch (idempotent +
version-gated). The skill grew a "Using secrets in cron prompts"
section documenting the env-var convention.
Migration: launch reconciler auto-populates .env on first v2.8 launch.
Users with cron prompts authored against the old (broken) pattern need
to update them to use $SCARF_… references — see release notes.
Tests:
- SecretsEnvBlockTests: 24/24 (`swift test --filter SecretsEnvBlock`)
- KeychainEnvMirrorTests: 11/11 (`xcodebuild ... -only-testing:scarfTests/KeychainEnvMirror`)
The idempotent-mirror test caught a real bug: applyBlock's replace
path consumed the trailing newline from blockRange but didn't restore
it, breaking the no-op-when-unchanged contract that the launch
reconciler relies on. Fixed.
v2.8 RELEASE_NOTES.md committed but no release cut yet.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Major project-dashboard release. Five new widget types (markdown_file, log_tail,
cron_status, image, status_grid), inline sparkline on stat, typed status enum
shared by list + status_grid, structured WidgetErrorCard, and a project-wide
.scarf/ directory watch that picks up files cron jobs write next to dashboard.json.
- ProjectDashboard: extend DashboardWidget with path/lines/jobId/cells/gridColumns/sparkline; add StatusGridCell + ListItemStatus (lenient parse with synonyms)
- HermesFileWatcher: watch each project's .scarf/ dir alongside dashboard.json (local FSEvents + remote SSH mtime poll); updateProjectWatches signature now takes dashboardPaths + scarfDirs
- New widget views: CronStatus, Image, LogTail, MarkdownFile, StatusGrid, plus WidgetErrorCard for structured failure messaging; legacy "Unknown" placeholder replaced everywhere
- WidgetPathResolver: project-root-anchored path resolution that rejects absolute paths + ".." escapes pre and post canonicalization
- Stat widget gains optional inline sparkline (pure SwiftUI Path, no Charts dep); list widget rows route through typed status with semantic icons + ScarfColor tints
- iOS list widget + unsupported card adopt typed status + warning-toned error card (parity with Mac error styling); new widget types remain Mac-only
- Site mirror: widgets.js renders all five new types (file-reading widgets show annotated catalog placeholders), sparkline SVG, status-grid grid; styles.css adds typed-status palette + error-card + sparkline + grid styles
- Catalog validator: tools/widget-schema.json is the single source of truth; build-catalog.py loads it and enforces per-type required fields. 8 new test cases in test_build_catalog.py covering schema load, v2.7 additions, and missing-required rejection
- Template-author skill (SKILL.md) gains v2.7 Widget Catalog section + canonical status guidance; CONTRIBUTING.md points authors at widget-schema.json; template-author bundle rebuilt
- Localizable.xcstrings picks up auto-extracted strings for the previously-shipped OAuth keepalive feature
- Release notes drafted at releases/v2.7.0/RELEASE_NOTES.md
Backwards compatible — existing dashboard.json renders byte-identically, status synonyms (ok/up/down/active/etc.) keep working.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a "Chat composer + transcript (post-merge round)" subsection
to the bug-fixes block covering #67, #68, #65, #62, #63, #64,
#66, and the partial #61 ACP-timeout bump. The pre-merge
test-target / iOS-build fixes stay grouped under "Pre-merge".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds releases/v2.6.0/RELEASE_NOTES.md covering every Phase A-H surface
(Curator, multimodal image input, 5 new providers, Skills v0.12,
Settings deltas, Cron workdir, Teams + Yuanbao, read-only Kanban, iOS
read-only Webhooks/Plugins/Profiles, version banner, internal
capability detector). Drops a paragraph at the top noting Hermes
v0.11 hosts continue to work — every new surface is gated on
HermesCapabilities so v2.6 against v0.11 looks identical to v2.5.2
against v0.11.
Polishes CLAUDE.md inaccuracies introduced in Phase A's first pass:
- ACP image wire shape: corrected to {"type":"image","data":...,"mimeType":...}
(matches acp.schema.ImageContentBlock); previous Anthropic-style
source: {type: base64, ...} sketch was wrong.
- Cron --context-from: clarified that Hermes hasn't exposed it as a
CLI flag yet (read-only via HermesCronJob.contextFrom), only
--workdir is writable.
- hermes memory setup: noted that the interactive verb stays in
Terminal (no in-app shellout); Settings → Memory just exposes the
provider picker.
- Skills surface: more precise about which CLI verbs back the Mac UI
affordances and why the disable-toggle is deferred to v2.7.
215 ScarfCore tests green; both Mac and iOS schemes build clean. Wiki
update + the actual release.sh ship are deferred to the user's
typical release-prep flow (the wiki repo is a separate worktree
that needs scripts/wiki.sh pull/commit/push, and release.sh expects
a clean working tree pointed at main).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
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>