Skip to content

Sessions UX: /save writes to CWD, browse/picker limits hide sessions, ollama-cloud stale model cache #16294

@teknium1

Description

@teknium1

A user (@John44893657552 on X) reported several session-related problems. Triaged against current main — some are real bugs, some are misunderstandings of how the system works. Tracking all of them here so nothing falls through.

Claims — triaged

Real bugs

1. /save writes to the current working directory, not ~/.hermes/sessions/.
cli.py save_conversation() writes hermes_conversation_<timestamp>.json to whatever directory hermes was launched from. The file is never indexed in the state DB and never surfaces in hermes sessions browse, so from the user's perspective the session "didn't save." This matches the "i saved sessions and they dont save" complaint.

2. hermes sessions browse has a default limit of 50 rows; TUI picker is 20.
hermes_cli/main.py passes limit=50 to list_sessions_rich(). tui_gateway/server.py's session.list handler defaults to limit=20 AND additionally filters sessions by a hardcoded allow-list of sources (cli, tui, telegram, discord, slack, whatsapp, wecom, weixin, feishu, signal, mattermost, matrix, qq). Any session with a different source value (for example acp, webhook, cron, custom values from older versions, or platforms not in the list) is silently dropped. This is "lots are missing from browse but they exist in .hermes/sessions."

Worth noting: ~/.hermes/sessions/session_*.json are transcript logs. The picker reads from the SQLite state.db, so any session present on disk without a matching DB row is invisible too.

3. hermes sessions browse and then resume does not restore context — only when the source is /save.
SQLite-indexed sessions loaded via --resume or sessions browse do restore full conversation history from the DB (cli.py around line 3292–3318 loads messages and feeds them into the next run_conversation() call; verified against current main). But a file produced by /save is not a resumable session — it lives in CWD, is not in the DB, and has no resume path. Root cause is (1); symptom is what the user described.

4. Ollama Cloud does not re-fetch models after the API key is entered in setup.
fetch_ollama_cloud_models() has a 1-hour disk cache. When a user adds OLLAMA_API_KEY during hermes tools / hermes setup, nothing calls force_refresh=True, so the pre-key cache (models.dev only, no live /v1/models probe) keeps serving until TTL expires. New models like deepseek v4 flash / kimi k2.6 are not visible until you either wait an hour or force a refresh.

Partially real (UX gaps, not broken)

5. "No way to switch sessions from within hermes --tui."
/resume inside the TUI opens a session picker overlay (ui-tui/src/app/slash/commands/core.ts). It exists, it's just not obvious from /help or the composer UI, and the picker hits the 20-row + source-allow-list filter from (2).

6. "Quitting doesn't auto-save or ask for a title."
Every message is already persisted to SQLite as it happens; normal exit calls end_session(..., "cli_close"). Titles are auto-generated in a background thread by agent/title_generator.maybe_auto_title after the first successful turn. The data is safe. What the user is missing is a visible confirmation on exit: "saved as '<title>' — resume with hermes --resume <id>". That's a legitimate, small UX ask.

Not real / misunderstood

7. "Only one session per tab."
Correct and intentional. One HermesCLI instance per process. Not a bug — the user is asking for a feature (tabs/splits inside the TUI).

8. "/agents in the TUI — what is it?"
It's the subagent-tree viewer for delegate_task spawns (ui-tui/src/components/agentsOverlay.tsx). Not a session switcher. Tooltip / help text could be clearer.

9. "I forked a session and it disappeared."
/branch was live-tested against SessionDB.list_sessions_rich() in an isolated HERMES_HOME. Both the parent (end_reason='branched') and the branch child (parent_session_id=<parent>, started_at >= parent.ended_at) are visible. The branch visibility logic in hermes_state.py is correct. The user's "disappeared" is almost certainly (2) — the branch is past position 50 in the picker, or its parent's source was filtered out.

10. web_extract vs browser_navigate.
Two independent tools with no fallback chain between them. web_extract uses Firecrawl / Tavily / Exa / Parallel (the paid search/scrape APIs). browser_navigate uses the browser automation stack (Browserbase / Playwright / Camofox). The user's mental model ("web_extract is a paid layer over browser") is wrong, but the hermes tools menu and docs genuinely don't explain the split — "Web Search & Extract" defaults to paid Firecrawl Cloud and only mentions DuckDuckGo (a skill, not a tool) as the free option. This is a docs / menu-clarity issue, not a code bug.

Fix plan

Small PR covering the real-bug and partially-real items that have clear code fixes:

  • /save → write under ~/.hermes/sessions/saved/ and print the absolute path.
  • hermes sessions browse → raise default limit from 50 to 500.
  • TUI session.list → raise default limit from 20 to 200; drop the hardcoded source allow-list so new platforms, acp, webhook, and custom sources appear.
  • hermes tools ollama-cloud post-setup → force_refresh=True on the model cache after the key is saved.
  • CLI exit → print "saved as '<title>' — resume with hermes --resume <id>" on normal exit.

Items 5, 7, 8, 10 are product / docs discussions, deferred.

Reporter: https://x.com/John44893657552

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/cliCLI entry point, hermes_cli/, setup wizardcomp/tuiTerminal UI (ui-tui/ + tui_gateway/)provider/ollamaOllama / local modelstype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions