Hermes-Agent Weekly: Multi-Terminal Panel, Shared WebSocket Layer, Security Hardening, and Live Agent Terminal Mirrors
- Commits summarized
- 1,143
- Period
- Jun 29 - Jul 05, 2026
- Published
- Jul 06, 2026
Hermes-Agent Weekly: Multi-Terminal Panel, Shared WebSocket Layer, Security Hardening, and Live Agent Terminal Mirrors
Issue: Week of 2026-06-29 – 2026-07-05
This edition highlights the most impactful changes from ~200 commit summaries sampled from 1,143 total commits this week. If you're building on the desktop app, running Hermes in Docker, or deploying a multi-tenant gateway, the notes below cover what changed and why.
Desktop: Multi-Terminal Panel with Read-Only Agent Mirrors
The desktop terminal pane has been rewritten to support multiple persistent user terminals and live read-only agent background terminals — a major step toward VS Code-level terminal parity.
Multi-Terminal Panel & Tab Rail
- Side tab rail: A thin VS Code-style icon rail on the outer edge of the terminal pane manages multiple persistent in-app terminals. Each tab is a live xterm+PTY that survives tab switches, session switches, and hiding the pane; only an explicit close or
exitkills a shell. (6875d6c) - Visibility-based tab hiding: Inactive tabs use
visibility: hidden(absolute-stacked at full size) instead ofdisplay: noneto prevent ResizeObserver bailout and buffer garbling on re-show. (c1bb34d) - ⌘W closes focused terminal: The keybind now routes to the focused terminal tab (user or agent) via the new
isFocusWithinprimitive, preventing accidental preview tab closure. (2d55ff8, b02f453) - Forced repaint on reactivation: WebGL terminals don't paint while
visibility: hidden; reactivation now clears the glyph atlas and forces a full refresh. (6e12f8c) - ⌘W closes agent tab: Agent mirror instances are marked
data-terminaland focused on activation soisFocusWithinroutes ⌘W to them. (e117cfd) - Close all action added to terminal tab context menu. (1a1e00f)
- Ctrl-L injection removed: The prompt-gap cleanup that sent Ctrl-L into the user's shell is gone; it could render as literal
^L. Initial newline striping is now renderer-side only. (1a1e00f)
Read-Only Agent Background Terminals
- Agent background tabs: When the agent runs
terminal(background=true), it surfaces as a read-only "agent" tab in the rail (distinct sparkle icon). The status row links to the tab instead of an inline disclosure. (ad831dd) - Live streaming via push: Replaced the 5s output_tail poll with a real push stream from the process registry. Chunks route by process ID directly into the read-only xterm via a capped backlog. (520212c)
- Snapshot seeding: Agent terminal tabs consume both live chunks and process snapshot data so they never open blank while output is pending. (6ac9ba9, 5d661a3, 7cfa2fa)
- Agent-driven tab close: A new
close_terminaltool (HERMES_DESKTOP-gated) drops a read-only tab without killing the process; output continues buffering. (e117cfd) - Scrollback parity: Agent terminal tabs use the same 1,000-line scrollback cap as user tabs and full unicode/WebGL rendering. (6c52e4a, adacb16)
Terminal Tab Persistence Across Relaunch
- User terminal tabs and scrollback persist across app restart. Tabs, active selection, cwd, and serialized scrollback snapshots are written to localStorage (750ms throttle). Processes are NOT revived — a new shell starts below the restored history. (1c0fa12)
- Teardown guard:
pagehide/beforeunloadflags prevent the persisted tabs from being wiped on quit. Agent mirror tabs remain runtime-only. (1c0fa12)
Infrastructure: Shared WebSocket Layer & Headless hermes serve
Extracted Shared WebSocket/JSON-RPC Client
- The Electron desktop app and web dashboard now share a common
@hermes/sharedWebSocket+JSON-RPC client, eliminating ~210 lines of duplicated plumbing. The dashboard is a thin subclass with dashboard-specific auth selection. (dfb561a, 5a4bdfda) - Dashboard WS URLs centralized: All dashboard WebSocket endpoints now route through
buildHermesWebSocketUrl. (6c52e4a) - Deterministic WS close: Intentional closes now reject pending RPCs immediately instead of relying on browser close events. (5a4bdfda)
- Dashboard gains 15s connect timeout (previously desktop-only). (dfb561a)
New hermes serve Command
hermes serveis a dedicated headless backend command that boots the same gateway without opening a browser. The desktop app now spawnsserveexclusively. (dff491a)- Backward compatibility: If the runtime doesn't register
serve(older install), the desktop falls back todashboard --no-open. (e684b80) - Contract tests added for the serve subcommand. (9d9a50c)
- Documentation updated: Desktop README, docs, and AGENTS.md clarify the desktop is self-contained and never requires the browser dashboard. (f019a99)
Platform & Security Hardening
Docker: Cgroup Controller Fallback
- Graceful degradation on cgroup-limited hosts: Container startup now probes for cgroup v2 cpu/memory/pids controller delegation and omits
--pids-limit,--cpus, and--memoryflags when they're unavailable (e.g., unprivileged Proxmox LXCs, rootless setups). Previously these hosts would fail every container start with an OCI runtime error. (7cfa2fa)
Terminal: Host-Bound Docker Approval
- Docker containers with host bind-mounts now route through the normal approval flow instead of auto-approving all commands. Isolated Docker containers (no host paths) keep the fast path. (9860d93)
Credential Redaction
- Bare-token URL credentials redacted: Git remote URLs with embedded passwords (
https://PASSWORD@github.com) are now masked by the redaction engine. Previously onlyuser:pass@form was caught. (3483424)
Agent-Loop Hardening
- Anthropic interrupt guard: Return
Noneon interrupt instead of callingget_final_message()on a partially-drained stream (could hang or return incomplete tool_use blocks). (ec148f5) - Vision data-URL cap: 20 MB cap on base64 data-URLs before decoding to prevent OOM in shared gateway processes. Oversized payloads return
("", None). (ec148f5)
Gateway Exception Handling
- Error notifications logged: The last-resort exception handler in
_process_message_background()now logs withexc_info=Trueinstead of a barepass, making failed error-notification sends debuggable. (f1cbe43) - Sanitized error messages: Exception text from LLM providers (which can leak API URLs, file paths, credentials) is no longer sent to end users. A generic message is returned; full detail stays in logs. (27ddd8f)
File & Path Validation
- Skills path containment fixed: Replaced string prefix check with strict path containment. (313a8c6)
- Host/relative cwd sanitized: Before reaching a container sandbox. (8fe800e)
- Webhook arg validation:
pr_numberandrepoare validated before passing to subprocess. (27ddd8f)
Profile Alias Path Traversal Fix
- Custom alias names are now validated against a profile-id regex (forbids
/,.,..) to prevent path traversal and arbitrary file write/unlink in the wrapper directory. (11183e8)
Config & .env Parsing
exportprefix stripped: All three.envparsers now strip the bash-compatibleexportprefix, fixing silent auth failures for users who copy-paste from bash profiles. (5c1ac6c
LMStudio Base URL Normalization
- LMStudio base URLs are now normalized. (163562b)
Gateway & Integrations
Session Boundary Fixes
- /resume clears model overrides: Chat-keyed
_session_model_overridesand_pending_model_notesare now cleared on/resume, preventing a model switch from a previous session leaking into the resumed conversation. (61a4526) - Cached agent eviction on auto-reset: The agent cache is now cleared on daily/idle/suspended auto-reset, preventing stale
_previous_summaryfrom mixing into compaction summaries in fresh sessions. (b4300f2) - AST invariant test pins the eviction into the auto-reset cleanup block. (0b733a8)
Approval Mode Validation
- Unknown
approvals.modevalues now default tomanualwith a warning instead of silently behaving like manual with no signal. (dda3268)
Matrix & Mattermost Security
- Matrix invite auth check: Invites now check the inviter against the allow-list before auto-joining, preventing federated users from inviting the bot into arbitrary rooms. (d836b2b)
- Mattermost API path traversal guard:
_api_get/_api_post/_api_putreject any path containing.., preventing authenticated requests to arbitrary endpoints via WebSocket-event value interpolation. (d836b2b)
WeCom Callback Body Cap
- Raw request body size is now capped before pre-auth XML parsing on the internet-facing WeCom callback endpoint. (74541be)
Cron: False 'Gateway Not Running' on External Providers
cron statusno longer reports a false negative for external providers like Chronos, which deliberately don't run a 60s ticker loop or write a heartbeat file. The provider is resolved offline and reports managed-scheduler state. (0943e2a)
Agent & File Injection
.hermes.md Parent Walk Scoped to Git Repos
- Outside a git repo, only the current working directory is checked for
.hermes.md/HERMES.md, preventing a file planted at/tmp,/home, or/from being loaded into every agent session as a cross-user prompt-injection vector. (306b661) - Regression tests added for no-git-root cwd-only and git-root walk behavior. (14204b0)
UI / Desktop Polish
Shared Overlay Panel Primitive
- The Agents, Cron, and Profiles overlays now share a single
Panelprimitive (centered card, header, master/detail with built-in search, kebab row actions, "+" footer, empty state) instead of three ad-hoc layouts. (9912207) - Dead overlay code removed:
OverlayNewButton,OverlayCard, and unused search-input module are dropped. (317b948) - Theme-var form controls: Input border/background/inset are now per-mode CSS custom properties. (9912207)
Dashboard: Memory Provider API Key Catalog
- All six memory providers (Hindsight, Supermemory, Mem0, RetainDB, ByteRover, OpenViking) now have their API keys catalogued in
OPTIONAL_ENV_VARSand appear in the dashboard Keys page. A contract test asserts every provider's primary credential key is catalogued, tool-categorised, and password-masked. (dee41d0)
Dashboard Backup Upload/Download
- Dashboard backup download and upload is now supported. (476875a)
Gateway Status Popout & Command Center Polish
- Live gateway log tail while the popout is open (WS connection churn filtered), flattened status header, and system-panel/restart actions. (6776b2f)
- Command center: removed usage/system dividers, swapped session nav icon. (6776b2f)
Chore & Tooling
- Committed PR infographics removed: 35 PNGs (~54MB) accumulated under
infographic/are deleted and the path is now gitignored. (43eaf79) - Prettier + ESLint pass across repo. (9f02eea)
- Docker build fix:
apps/sharedincluded in dashboard Docker build context. (e9b95df) exportprefix stripping tests added for .env parsers. (490f215)- AUTHOR_MAP entries added for several salvage PRs. (163562b, 9cf9d3a)
Documentation
- Cron delivery targets documented: Per-platform explicit target syntax for Slack, Matrix, Feishu, WhatsApp, Signal, SMS, Email, and Weixin is now fully documented in the Delivery Model table (en + zh-Hans). (e1f4098)
- Desktop-backend relationship clarified in multiple docs pages. (f019a99)
This post covers highlights from 200 commit summaries of 1,143 total commits in the period. For a complete record, see the full commit log.