* fix(start): use server-entry wrapper for production
* fix(swarm): reconcile oneshot checkpoints and ignore phantom blockers
* fix(profiles): sync editable descriptions from profile config
* fix: show cron jobs across Hermes profiles
* fix(capabilities): clarify dashboard-backed API detection
* feat: make Conductor use native Swarm fallback
Treat Workspace-native Swarm as the official Conductor fallback when the dashboard mission API is unavailable. Preserve dashboard-first dispatch, native status/cancel handling, provider-neutral setup docs, and regression coverage for gateway capability detection, swarm health, roster/profile handling, and native Conductor responses.
* fix(usage-meter): reposition menu trigger for better alignment
- Adjusted the position of the menu trigger in the usage meter component to enhance layout consistency and user experience.
fix(chat-panel): adjust position of chat panel toggle button
- Updated the positioning of the chat panel toggle button to improve visibility and accessibility by changing its bottom and right offsets.
* fix(stt): wire Groq/OpenAI voice transcription into chat
* Fix Workspace Kanban loopback dashboard link
* fix(update): do not open historical release notes on startup
* fix(chat): clear stale thinking runs reliably
* fix(dashboard): trust sessions endpoint for status
* fix(settings): address review — local default, OAuth lifecycle, validation
* fix(dashboard): always scrape live session token from HTML
* fix(chat): avoid portable history replay on bound sessions
* fix(settings): remove dead smart routing controls
* fix(tasks-api): guard against HTML catch-all in probeBackend
The /api/hermes-tasks route was renamed to /api/claude-tasks in commit
efcb7d14, but the probe logic still listed the old route as a candidate.
When probed, the SPA catch-all returned a 200 HTML response instead of
a 404, so probeBackend() treated it as a valid (empty) backend and then
failed when the actual task fetch threw.
Fixes:
- probeBackend() now checks Content-Type: application/json and returns
-1 for non-JSON responses, so future route renames degrade gracefully.
- resolveBackend() now only selects hermes if hermesCount > 0, defaulting
to claude-tasks (the active backend post rename) when hermes is absent.
* fix(terminal): default cwd to ~ and fallback if path missing
PTY helper chdir fails when ~/.hermes is absent (common in Docker).
Default shell cwd to home; server falls back to HOME if cwd does not exist.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(settings): satisfy lint on custom providers UI
* fix(docker): add -m flag to useradd so workspace home dir is created
Without -m, the system account has no /home/workspace directory.
The auth middleware tries to write the session store at
/home/workspace/.hermes/workspace-sessions.json; mkdirSync fails with
EACCES because /home/ is root-owned (755), causing the 'Failed to
persist session store' warning and a 500 on every authenticated route.
Adding -m causes useradd to create and chown /home/workspace correctly
so the session store can be written on first login.
* fix(tasks): preserve real session links and restore task launch flow
* fix(launchd): install macOS plist from server-entry template
* fix(docker): expose dashboard API and persist workspace volumes
* fix(jobs): serialize deliver targets for cron API
* Make Hermes Workspace installable as PWA
* chore(deps): pin direct tanstack versions
* feat: align semantic Hermes swarm agents
Add semantic swarm roster metadata, profile/tool/skill docs, shared semantic worker ID validation, focused roster regression coverage, and one-shot checkpoint capture for dispatch smoke tests.
* fix(conductor): pass through sessionKeyPrefix from portable spawn result
sessionKeyPrefix was hardcoded to null in conductor-spawn.ts, breaking
async session resolution when the dashboard backend returns a prefix.
Now mirrors the sessionKey pattern and passes through the value from
the spawn result.
Co-authored-by: Hermes Agent
* feat(swarm): bridge workspace kanban to native Hermes
* fix(chat): keep portable main pinned without breaking resolved sessions
* Add Windows startup script for Hermes Workspace
Document PowerShell usage for launching and restarting gateway + workspace via WSL tmux.
Co-Authored-By: Oz <oz-agent@warp.dev>
* fix(config): name Hermes Agent in restart notice
* fix(swarm): reconcile aggregate semantic worker exports
---------
Co-authored-by: Aurora release bot <release@outsourc-e.com>
Co-authored-by: motoki takahashi <motokitakahashi@motokinoMac-mini.local>
Co-authored-by: Vicky Wonder <vicky@openclaw.ai>
Co-authored-by: Vitaliy Isikov <visikov+supagoku@gmail.com>
Co-authored-by: Hermes Agent <hermes-agent@local>
Co-authored-by: Nikolay Mohr <nikomohr96@gmail.com>
Co-authored-by: Niko Mohr <niko@friendsfromcollege.de>
Co-authored-by: wtchronos <262830926+wtchronos@users.noreply.github.com>
Co-authored-by: Dak0verflow <dakotaferris@gmail.com>
Co-authored-by: norema <mamadou.marone.19@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: daoyuan <ludaoyuan1989@gmail.com>
Co-authored-by: firemountain <firemountain@gmail.com>
Co-authored-by: RAZSOC Local <razsoc@local>
Co-authored-by: Waylon Kenning <waylonkenning@Waylons-MacBook-Pro.local>
Co-authored-by: Kublai <kublai@kublai.local>
Co-authored-by: justa <justa@local>
Co-authored-by: Oz <oz-agent@warp.dev>
Allow operators to hide the HermesWorld sidebar link by setting
VITE_HERMESWORLD_ENABLED=0 in .env. Default is enabled (1).
Closes the gap for users who don't want gamification/playground links
in their workspace sidebar.
Adds capability detection for the upstream Hermes Agent kanban plugin
mounted at /api/plugins/kanban/. Lays the groundwork for the v2.3.0
work where the workspace's /swarm kanban surface syncs with the
dashboard's SQLite-backed kanban DB.
Changes:
* gateway-capabilities.ts: new probeKanban() probes
/api/plugins/kanban/board on the dashboard URL with a short timeout.
GatewayCapabilities now carries a 'kanban' boolean. Probed once per
PROBE_TTL_MS alongside conductor.
* connection-status.ts: surfaces caps.kanban so client-side feature
gates can react.
* use-feature-capability.ts + feature-gates.ts: 'kanban' is now a
recognized FeatureKey / EnhancedFeature so useFeatureCapability('kanban')
works.
* .env.example: documents HERMES_DASHBOARD_URL (default 127.0.0.1:9119
on current Hermes Agent v0.13+; the legacy 9120 is gone).
Tested locally with hermes-agent main pulled into
/Users/aurora/hermes-dashboard-fresh/repo. Workspace gateway-status
now reports kanban: true when the plugin is mounted, false otherwise.
The 2026-05-01 codename rename swept most of the repo from 'Claude' to
'Hermes' but left a few env vars and README copy that still referenced
the old name. Users on fresh installs were configuring HERMES_PASSWORD
based on the docs but the auth middleware only read CLAUDE_PASSWORD,
silently bypassing the guard.
Changes:
- src/server/auth-middleware.ts: read HERMES_PASSWORD first, fall back
to CLAUDE_PASSWORD for back-compat with pre-rename setups.
- server-entry.js: same fallback for HERMES_PASSWORD +
HERMES_ALLOW_INSECURE_REMOTE. Error messages updated to point at the
new names.
- README.md:
- Drop the misleading 'v2 zero-fork = full feature parity' framing;
call out that Conductor specifically requires an upstream dashboard
plugin not yet shipped (per #262), with a link.
- Theme list updated to current names (Hermes / Nous / Bronze /
Slate / Mono \u2014 the v2.1 rename) instead of the old 'Official /
Classic' labels.
- Replace CLAUDE_PASSWORD / CLAUDE_ALLOW_INSECURE_REMOTE references
with HERMES_* primary names + back-compat note.
- Add HERMES_API_TOKEN to the security env-var list (previously
undocumented despite being honored by the gateway-capabilities probe).
- Inline note on the avatar PNG asset name being retained for cache
stability \u2014 the 'claude-avatar' filename is intentional.
- .env.example: HERMES_PASSWORD + HERMES_ALLOW_INSECURE_REMOTE primary
names with legacy notes.
- docker-compose.yml: HERMES_PASSWORD: ${HERMES_PASSWORD:-${CLAUDE_PASSWORD:-}}
so existing compose files that set CLAUDE_PASSWORD keep working while
new files use HERMES_PASSWORD.
Build + auth-middleware tests pass.
No public-facing breaking change: every previous CLAUDE_* env var still
resolves correctly through the back-compat fallbacks.
Co-authored-by: Aurora release bot <release@outsourc-e.com>
Hardcoded 2/3-min no-activity timeouts are now driven by
STREAM_ACCEPTED_TIMEOUT_MS and STREAM_HANDOFF_TIMEOUT_MS env vars
(defaults: 120s accepted, 300s handoff). New /api/stream-config route
reads these at runtime; chat-screen fetches them once on mount and
passes to useStreamingMessage. Together with the 30s heartbeat added
in the previous commit, long agent runs on slow models no longer stall.
Worked with Interstellar Code
(cherry picked from commit 96f0c64b2222b42b112b83a878dbe12cf29c46a7)
NODE_ENV=production enables the Secure flag on session cookies. Browsers
silently drop Secure cookies over plain HTTP, causing login to fail with
no visible error when HOST=0.0.0.0 is used on a LAN without HTTPS.
- Add startup warning in server-entry.js when non-loopback host +
production + COOKIE_SECURE not explicitly disabled
- Document COOKIE_SECURE=0 in .env.example alongside the existing =1 case
- Add COOKIE_SECURE entry to README env-vars table
Closes#149
Worked with Interstellar Code
(cherry picked from commit d88d899481871f2d9ac5d01f5c318f668d1e6873)
Addresses the 5 security findings from @kiosvantra's audit (thank you!).
## #121 — Path traversal via naive startsWith()
src/routes/api/files.ts: ensureWorkspacePath now uses path.relative()
to enforce the workspace boundary. The previous string-prefix check
accepted sibling paths (e.g. /root/.hermes2 when root is /root/.hermes).
Added regression tests in src/routes/api/-files.test.ts.
## #122 — Deployment defaults expose control plane
server-entry.js: default HOST to 127.0.0.1. If HOST is non-loopback
and HERMES_PASSWORD is unset, the server refuses to start with a
clear banner explaining the fix. An explicit
HERMES_ALLOW_INSECURE_REMOTE=1 escape hatch is available for operators
who understand the risk.
docker-compose.yml: gateway defaults to 127.0.0.1 (no host binding),
workspace publishes on 127.0.0.1:3000 and passes HERMES_PASSWORD /
COOKIE_SECURE / TRUST_PROXY through.
## #123 — Session cookie missing Secure
src/server/auth-middleware.ts: createSessionCookie() now appends
Secure by default in production (and when COOKIE_SECURE=1 overrides).
Docs clarify when dev-HTTP exemption is safe.
## #124 — Dashboard token scraped from HTML
src/server/gateway-capabilities.ts: fetchDashboardToken() now prefers
an explicit HERMES_DASHBOARD_TOKEN (or HERMES_API_TOKEN) env bearer.
The HTML-scrape path remains as a logged fallback for existing
deployments, with a deprecation warning pointing at #124. This removes
the brittle trust boundary in production.
## #125 — x-forwarded-for trusted unconditionally
src/server/auth-middleware.ts + src/server/rate-limit.ts: both IP
resolvers now ignore forwarded headers unless TRUST_PROXY=1 is set.
Without that opt-in, clients cannot spoof local classification or
rotate rate-limit keys via x-forwarded-for. Added regression tests.
## Env + docs
.env.example: new Security section documenting HOST, HERMES_PASSWORD,
COOKIE_SECURE, TRUST_PROXY, HERMES_DASHBOARD_TOKEN, and the bypass.
README.md: Security section updated to reflect the new posture and
credit the audit.
## Verification
- tsc --noEmit: clean
- vitest: 43/43 pass (added 16 new tests across files, auth-middleware,
rate-limit)
- Fail-closed guard verified manually:
HOST=0.0.0.0 \u2192 exit 1 with banner
HOST=0.0.0.0 HERMES_PASSWORD=x \u2192 starts
HOST=0.0.0.0 HERMES_ALLOW_INSECURE_REMOTE=1 \u2192 starts with warn
HOST=127.0.0.1 \u2192 starts
Closes#121, #122, #123, #124, #125
Co-authored-by: Eric <eric@outsourc-e.com>
User on Discord reported our docs saying ANTHROPIC_API_KEY is required.
It's not — hermes-agent supports Anthropic, OpenAI, OpenRouter (incl. free
models), Google, local Ollama/LM Studio, etc. Users only need the key for
the provider they actually picked in `hermes setup`.
Also replaced the 'pip install hermes-agent' references that snuck in — the
package isn't on PyPI, it installs from source via Nous's official script.
Changes:
- .env.example: list all common provider keys, all commented out, users
uncomment whichever they use
- docker-compose.yml: pass through ANTHROPIC / OPENAI / OPENROUTER / GOOGLE /
GROQ / MISTRAL keys (all optional, whichever is set wins)
- README.md: remove 'ANTHROPIC_API_KEY required' claim, replace pip install
references with the Nous installer path, generalize Docker troubleshooting
to match any provider
- FEATURES-INVENTORY.md: list all supported provider env vars
Closes#77 — nekopep reported workspace couldn't authenticate to a gateway
exposed on 0.0.0.0 with API_SERVER_KEY set. Workspace already supports
HERMES_API_TOKEN (added previously) but it wasn't documented.
- Document HERMES_API_TOKEN in .env.example with the matching API_SERVER_KEY
relationship and usage notes.
- Wire through API_SERVER_KEY / API_SERVER_HOST / API_SERVER_ENABLED in
docker-compose.yml so both services pick up the secret from a single
.env value.
- HERMES_API_TOKEN on the workspace side now defaults to the same
API_SERVER_KEY so Docker Compose works out of the box.
When the Hermes gateway is running but the HTTP API server is not
enabled, the onboarding screen shows generic advice that doesn't
address the actual problem. Users can have a fully functional gateway
(serving Telegram, Discord, etc.) while the workspace can't connect.
Changes:
- Onboarding connection error now shows step-by-step instructions:
1. Add API_SERVER_ENABLED=true to ~/.hermes/.env
2. Restart the gateway
- Updated .env.example to document the requirement
- Added Ollama/LiteLLM/vLLM as explicit alternative backend options
Fixes#26
- Replace hardcoded command with platform-detected steps (macOS/Linux/Windows)
- Auto-start button tries to detect and launch hermes-agent automatically
- Manual setup section shows numbered steps with copy buttons
- Falls back to manual guide when auto-start fails
- Add HERMES_API_URL env var hint for custom setups
- Add .env.example with all configurable env vars
- Auto-refreshes when connection is detected
- Auto-detect WebAPI on port 8642/8643 (no HERMES_API_URL required)
- Connection error shows specific WebAPI install instructions
- CI: --no-frozen-lockfile to match Docker setup
- .env.example documents all config options
- Startup log shows configured API URL
New CLAWSUITE_PASSWORD env var — when set, requires password to access.
- Timing-safe password comparison
- httpOnly cookie sessions (30-day expiry)
- Clean login screen matching ClawSuite design
- Auth middleware on all API routes (send, stream, config-patch)
- /api/auth-check for client-side auth state
- Backwards compatible: no password = no auth (localhost default)
Adds CLAWSUITE_ALLOWED_HOSTS env var (comma-separated hostnames).
When set, server binds to 0.0.0.0 and allows those hosts.
Requested by @tharshan_09 for Tailnet access.
- Full security audit with findings, risk summary, code-level evidence
- SECURITY.md with reporting policy, architecture, scope docs
- Fixed .env.example branding (WebClaw → OpenClaw Studio)
- Phased ticket roadmap (P0-P3) with acceptance criteria
- Scan results: no secrets in current tree or git history