- Sprint 12 and 13 headers: add missing (COMPLETED) labels
- Sprint 23 header: corrected from 'Profile/Workspace/Model Coherence' to
'Agentic Transparency + Context Visibility' (what it actually shipped)
- Sprint 24 Track C: removed stale self-referential cleanup items that are now done
- Sprint 26 added: full plan for pluggable UI themes (light/dark/solarized/monokai/nord)
including CSS variable architecture, flicker prevention, /theme slash command,
settings picker with live preview, and test spec
- ROADMAP.md: add v0.32/v0.33 to sprint history table, add Sprint 25/26 to feature checklist
- SPRINTS.md footer: add horizon sprint line
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
Three bugs found during review:
1. Class is SessionDB not HermesState -- would silently no-op on every install
2. SessionDB.__init__ takes Path not str -- would crash with AttributeError
3. _execute_write() takes a callable not SQL+params -- wrong signature.
Replaced with public set_session_title() API.
4. Each call opened a persistent SQLite connection and never closed it.
Added try/finally db.close() to prevent WAL leak under sustained load.
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
- routes.py /api/git-info: get_session raises KeyError on miss, does not
return None -- wrap in try/except KeyError to correctly return 404
(PR #82, api/routes.py line 222)
- style.css ctx-bar used undefined --teal CSS variable -- replaced with
--blue which is defined in :root and fits the existing color palette
(PR #83, static/style.css)
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
Matches the fix applied to api/config.py in PR #72. Both defaults
now consistently use ~/.hermes/webui for a clean generic install.
HERMES_WEBUI_STATE_DIR env var still overrides for anyone running
multiple instances.
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
The previous default pointed to 'webui-mvp' which is the internal
development repo name and meaningless to anyone deploying the public
repo. Changed to the generic '~/.hermes/webui' which is a sensible
default for any deployment.
The state dir remains fully overridable via HERMES_WEBUI_STATE_DIR
for anyone who wants to run multiple instances side by side.
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
Fix five stacking/overflow bugs in static/style.css (no JS changes):
1. Profile dropdown overlaps chat messages
.topbar lacked a stacking context -- added position:relative;z-index:10
so the dropdown (z-index:200 child) always paints above .messages (z-index:0)
2. Workspace dropdown clipped by sidebar overflow:hidden
.sidebar overflow:hidden was swallowing the upward-opening ws-dropdown.
Changed to overflow:visible -- scroll is already on .session-list, not .sidebar.
Added position:relative;z-index:10;overflow:visible to .sidebar-bottom.
3. Slash-command dropdown could render behind tool cards
.composer-wrap had position:relative but no z-index.
Added z-index:10 so cmd-dropdown always sits above .messages (z-index:0).
4. Skill picker dropdown clipped inside Settings modal
.settings-panel had overflow-y:auto which clipped the absolute-positioned
skill picker. Changed to overflow:visible + display:flex;flex-direction:column,
moved overflow-y:auto to .settings-body, raised skill-picker-dropdown to z-index:1100.
5. CLI session badge blocks action buttons on hover
Added .session-item.cli-session:hover::after { display:none } so the gold
'cli' label hides on hover, making archive/delete/pin fully reachable.
6. Workspace dropdown name+path crowded on same line
.ws-opt was a plain block with inline spans. Added flex-direction:column;gap:4px
and display:block to each child so name and path stack cleanly on separate lines.
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
* docs: add HERMES.md deep-dive, Why Hermes section in README, and screenshot layout
- HERMES.md: full why-Hermes document -- assistant vs. agent mental
model, three pillars (memory/scheduling/reach), four-category
taxonomy of AI tools, per-tool comparison sections with tables
(Claude Code, Codex CLI, OpenCode, Cursor/Copilot, Claude.ai),
compounding advantage, who it's for, what it's not, quick reference
- README: hero screenshot stays full-width; two new UI screenshots in
side-by-side HTML table with captions below
- README: new Why Hermes section with 6-bullet summary, comparison
table, and link to HERMES.md
- README: HERMES.md added to Docs section
- docs/images/: two UI screenshots (workspace browser, sessions view)
* docs: fact-check and update all comparisons; add Open Interpreter section
Researched current state of each tool before updating:
Claude Code:
- Scheduled jobs: now Partial (has /loop session-scoped, cloud-managed
/schedule via claude.ai/code, and desktop app automations); updated
table to reflect this with footnotes distinguishing self-hosted cron
- Persistent memory: Partial (CLAUDE.md, MEMORY.md, rolling auto-memory
but not full automatic cross-session recall)
- Provider-agnostic: No -- supports Bedrock/Vertex but Claude models only
- Web UI: Yes but Anthropic-hosted (not self-hosted)
Codex CLI:
- Persistent memory: Partial (session history + AGENTS.md since v0.100.0)
- Scheduled jobs: Partial (desktop app Automations only; CLI has no native
scheduling as of early 2026, open feature request)
- Provider-agnostic: Yes (10+ providers)
OpenCode:
- Web UI: now Yes (embedded in binary + official desktop app)
- Persistent memory: Partial (SQLite sessions + AGENTS.md, not semantic)
- Messaging: community Telegram bot only, not first-party
Open Interpreter: added as new comparison section
- Most common 'why not just use this' question; addressed head-on
- Session-scoped, no persistent memory by their own docs, no scheduler,
no messaging integration; powerful for one-shot tasks, not always-on
README Why Hermes table: updated to include Open Interpreter column,
fixed Claude Code self-hosted row (No -- scheduling runs on Anthropic
cloud), added footnotes for partial entries
* docs: add OpenClaw comparison; update category framework and quick reference table
OpenClaw (openclaw.ai, MIT, 347k stars) is the most direct Hermes
competitor -- both are open-source, self-hosted, always-on agents with
persistent memory, cron, and messaging integration. Added:
- Full OpenClaw section in HERMES.md with honest comparison: where it
wins (15+ messaging platforms incl. iMessage/WeChat, native Chrome CDP
browser control, voice wake words, ClawHub marketplace) and where
Hermes differs (self-improving skills system, Python/ML ecosystem,
web UI, multi-profile, sub-agent orchestration)
- Category 4 framework updated: now lists both Hermes and OpenClaw,
with the key architectural distinction called out
- Quick reference table expanded to include OpenClaw column (now 8 tools)
- New rows added: self-improving skills, browser/computer control,
Python/ML ecosystem
- README Why Hermes table updated: OpenClaw replaces OpenCode column,
self-improving skills row replaces generic skills row, callout line
at bottom addresses OpenClaw head-on
* docs: major accuracy pass -- OpenClaw deep-dive, Claude Code corrections, drop Open Interpreter
OpenClaw:
- Expanded comparison from a table to a full prose section with
'Where OpenClaw wins' / 'Where Hermes wins' structure
- Honest about OpenClaw strengths: 15+ messaging platforms, native
Chrome CDP browser control, voice wake words, 13k+ ClawHub skills
- Hermes advantages called out clearly: self-improving skills as a
first-class automatic loop (vs marketplace-install model), stability
(documented OpenClaw update regressions, Telegram breakage in early
2026, WhatsApp protocol instability), security (156 CVEs and 1,184
malicious skills found in ClawHub audit vs Hermes's no marketplace
attack surface), Python/ML ecosystem, full web UI vs dashboard-only,
and first-class multi-profile support
- Category 4 framework updated to name both Hermes and OpenClaw
- Table updated: added stability/security rows, corrected web UI row
(OpenClaw has a gateway dashboard but not a full chat UI)
Claude Code corrections (researched against official docs at code.claude.com):
- Skills/Hooks: changed from No to Yes -- has a full Hooks system (13
event types, 4 handler types) and a Plugin/Skills marketplace since
v2.0.12; unified with slash commands in v2.1.0
- Messaging: changed from No to Partial -- Channels feature (Telegram,
Discord, iMessage, Webhooks) in research preview since v2.1.80; deep
Slack integration that triggers cloud sessions and creates PRs
- Added Claude Cowork row: separate product with 38+ connectors
(Slack, Gmail, Teams, Notion, Jira, Salesforce, etc.)
- Scheduling footnote updated: cloud-managed has 1-hour minimum interval
- Provider-agnostic clarified: routes through Bedrock/Vertex but always
Claude models; cannot swap to GPT or Gemini
Open Interpreter removed:
- Less relevant comparison than OpenClaw for the 'always-on agent' frame
- Kept coverage focused on the tools people actually compare Hermes to
Quick reference table:
- Now 7 tools wide (added OpenClaw, kept Claude Code, Codex, OpenCode,
Cursor, Claude.ai, Hermes)
- New rows: self-improving skills, browser/computer control, stability
- Updated: Claude Code messaging to Partial, OpenClaw web UI to
'Dashboard only', skills rows differentiated by type
* docs: apply full editorial pass from hermes-edit-list.md
Writing patterns fixed:
- Em dashes reduced by ~80%; replaced with commas, periods, parens
- All 'Not X, it's Y' negative parallelism rewritten as positive
statements; 'What Hermes Is Not' section renamed 'Scope and Limits'
and reframed positively throughout
- 'It compounds.' standalone flourish removed
- 'meaningfully' removed everywhere (was appearing 3+ times)
- 'leverages' -> 'uses' in README
- 'remembers everything' softened to 'retains context across sessions'
- Bolded Hermes column in Quick Reference table un-bolded (only genuine
differentiator cells kept bold: self-improving skills, always-on,
orchestrates other agents)
- 'The honest summary' framing removed from OpenClaw section
- 'Hermes is different.' cliche transition cut from README
- Rule-of-three slogans trimmed (e.g. 'Same agent, same memory...')
- 'tired of re-explaining' -> 'don't want to re-explaining'
Duplicate content removed:
- 'day one / day one hundred' comparison kept only in Compounding
Advantage section; removed from Pillar 1
Factual accuracy fixes:
- Claude.ai comparison updated: memory now auto-generated from history
(not just user-curated); code execution and file read/write noted
as sandboxed (Artifacts), not flat No
- Category 2: Windsurf framed as 'earliest' on memory, Copilot
'catching up'; removed overconfident 'most mature' claim
- Category 4 qualifier: 'as of early 2026' added
- '1-hour minimum' for Claude Code cloud scheduling softened to
'minimum interval applies' (specific claim unverified)
- Claude Code scheduling table note: 'cloud or desktop-app only'
(was just 'cloud-managed or session-scoped')
- README claim 'No other open-source tool combines...' removed;
was false because OpenClaw does combine all three
- OpenClaw self-improving skills: 'No' -> 'Partial' with clarification
- README OpenClaw callout: 'relies on a marketplace' softened to
'skill system centers on a community marketplace'
- 'meaningfully more stable' -> 'more stable'; 'supply chain issues'
-> 'security incidents involving malicious skills'
- OpenClaw star count: '347k+' -> '~347k' (moving fast)
- Stability row added to OpenClaw table; bold removed from table
---------
Co-authored-by: Hermes <hermes@localhost>
Adds a server-side boolean setting (default: false) that controls whether
CLI sessions from state.db appear in the sidebar. Off by default so the
sidebar is clean until the user explicitly opts in.
- api/config.py: add show_cli_sessions to _SETTINGS_DEFAULTS and _SETTINGS_BOOL_KEYS
- api/routes.py: gate get_cli_sessions() call on the setting at request time
- static/index.html: checkbox in settings panel with description
- static/panels.js: load/save checkbox, refresh session list on save
- static/boot.js: load on startup alongside send_key and show_token_usage
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
The sessions table in the CLI state.db does not have a 'profile' column --
selecting s.profile caused an OperationalError which was silently caught by
'except Exception: return []', making get_cli_sessions() always return empty.
Fix: remove s.profile from the SELECT (it doesn't exist in the CLI schema)
and derive the profile from get_active_profile_name() instead, which is the
right value anyway since the CLI DB has no profile concept.
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
get_cli_sessions() and get_cli_session_messages() were using HERMES_HOME
(the profile the server was launched under) to find state.db. This meant
a server launched under the webui profile would read webui's state.db
(full of cron runs) instead of the user's actual CLI sessions.
Fix: use get_active_hermes_home() which tracks whichever profile the user
has selected in the UI. This means:
- default profile active -> reads ~/.hermes/state.db (interactive CLI)
- camanji profile active -> reads ~/.hermes/profiles/camanji/state.db
Falls back to HERMES_HOME env var if profiles module unavailable.
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
The backend CLI session bridge (PR #56) was complete but the frontend
never connected to it:
1. css class never applied -- el.className never included 'cli-session'
so the gold border and 'cli' badge CSS was dead code. Fixed: append
' cli-session' when s.is_cli_session is true.
2. import never triggered -- click handler always called loadSession()
directly, never POST /api/session/import_cli. Fixed: for CLI sessions,
call import_cli first (idempotent -- safe to call on every click),
then fall through to loadSession() which now finds the imported copy.
3. profile filter silently hid CLI sessions -- filter required
s.profile === S.activeProfile, but CLI sessions may have profile=null
if the SQLite DB has no profile column. Fixed: CLI sessions always
pass the filter (s.is_cli_session || s.profile === S.activeProfile).
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>