# NousResearch/hermes-agent · Dashboard embedded chat wheel scrolling and scrollback handling

## Open now

- 0 issues, 1 PR open on GitHub.
- PR #29975: fix: improve dashboard terminal clipboard and wheel handling

Most members concern mouse wheel scrolling and transcript scrollback in the dashboard's embedded chat (/chat), including one issue report and several pull requests with similar titles. Some also mention related areas such as chat resume stability and terminal clipboard handling, but the shared theme is scroll behavior.

## TL;DR

- 5 member(s): 0 open issue(s), 1 closed issue(s), 1 open PR(s), 1 merged PR(s), 2 PR(s) closed without merging.
- A fix was merged to main in PR #28584. Verify it addresses your case.
- **Recommended:** read PR #28584 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `resolved` · deciding PR(s): `pr-28584`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.40`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #19084: dashboard /chat: wheel scrolling does not reliably scroll transcript history in embedded chat

## Prior & competing PRs

- **#19088: fix(dashboard): stabilize embedded chat resume and scrollback**. closed without merge · fix tier `suggested`
  - maintainer direction: category `uncategorized`; implication `needs_llm`
  - _suggested-tier fix detail withheld; re-request with `?tier=all` to include it._
- **#28584: fix(dashboard): use browser scrollback for chat wheel (#28029)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `hermes_cli/web_server.py`, `tests/hermes_cli/test_web_server.py`, `web/src/pages/ChatPage.tsx`
  - fix hunks:
  - `hermes_cli/web_server.py`

    ```diff
    @@ -3350,6 +3350,7 @@ def _resolve_chat_argv(
         # build unchanged for native CLI usage; only disable mouse tracking for
         # the dashboard PTY path.
         env.setdefault("HERMES_TUI_DISABLE_MOUSE", "1")
    +    env.setdefault("HERMES_TUI_INLINE", "1")
     
         if resume:
             latest_resume, _latest_path = _session_latest_descendant(resume)
    ```
  - `tests/hermes_cli/test_web_server.py`

    ```diff
    @@ -2092,6 +2092,21 @@ def _url(self, token: str | None = None, **params: str) -> str:
             q = {"token": tok, **params}
             return f"/api/pty?{urlencode(q)}"
     
    +    def test_resolve_chat_argv_uses_dashboard_scroll_env(self, monkeypatch):
    +        """Dashboard chat runs the TUI in browser-scrollback mode."""
    +        import hermes_cli.main as main_mod
    +
    +        monkeypatch.setattr(
    +            main_mod,
    +            "_make_tui_argv",
    +            lambda project_root, tui_dev=False: (["node", "dist/entry.js"], "/tmp/ui-tui"),
    +        )
    +
    +        _argv, _cwd, env = self.ws_module._resolve_chat_argv()
    +
    +        assert env["HERMES_TUI_INLINE"] == "1"
    +        assert env["HERMES_TUI_DISABLE_MOUSE"] == "1"
    +
         def test_rejects_when_embedded_chat_disabled(self, monkeypatch):
             monkeypatch.setattr(self.ws_module, "_DASHBOARD_EMBEDDED_CHAT_ENABLED", False)
             from starlette.websockets import WebSocketDisconnect
    ```
  - `web/src/pages/ChatPage.tsx`

    ```diff
    @@ -298,10 +298,9 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) {
           // is false; enabling it gives users a single-action selection
           // path on top of the modifier-based bypass above.
           rightClickSelectsWord: true,
    -      // Single-scroll-system experiment:
    -      // let the inner Hermes TUI own transcript history/scroll behavior.
    -      // The outer browser xterm should act as a display/input bridge only.
    -      scrollback: 0,
    +      // Browser-embedded chat runs the TUI in inline mode. Keep transcript
    +      // history in xterm.js so the browser wheel can scroll it directly.
    +      scrollback: 5000,
           theme: TERMINAL_THEME,
         });
         termRef.current = term;
    ```

    ```diff
    @@ -345,7 +344,7 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) {
               // original keydown event's activation. Log to aid debugging.
               console.warn("[dashboard clipboard] OSC 52 write failed:", err.message);
             });
    -      } catch (e) {
    +      } catch {
             console.warn("[dashboard clipboard] malformed OSC 52 payload");
           }
           return true;
    ```

    ```diff
    @@ -404,34 +403,16 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) {
         fitRef.current = fit;
         term.loadAddon(fit);
     
    -    // Single-scroll-system experiment:
    -    // keep browser xterm as a display/input bridge only, and let the inner
    -    // Hermes TUI own transcript scrolling.
    -    //
    -    // In practice, the most reliable path here is NOT terminal mouse-wheel
    -    // protocol emulation — that can vary by terminal mode and parser path.
    -    // The inner TUI already handles keyboard-driven transcript scrolling
    -    // correctly (`Shift+Up` / `Shift+Down`, `PageUp` / `PageDown`), so we
    -    // translate browser wheel gestures into those known-good key sequences.
    +    // Dashboard chat should scroll the browser-side transcript, not send
    +    // mouse-wheel protocol bytes through the PTY.
         term.attachCustomWheelEventHandler((ev) => {
    -      if (wsRef.current?.readyState !== WebSocket.OPEN) {
    -        return false;
    -      }
    -
           const delta = ev.deltaY;
           if (!delta) {
             return false;
           }
     
    -      // Shift+Up / Shift+Down: the TUI maps these to line-by-line
    -      // transcript scrolling, which feels much closer to wheel behavior
    -      // than PageUp/PageDown's half-page jumps.
           const step = Math.max(1, Math.round(Math.abs(delta) / 50));
    -      const seq = delta > 0 ? "\x1b[1;2B" : "\x1b[1;2A";
    -
    -      for (let i = 0; i < step; i++) {
    -        wsRef.current.send(seq);
    -      }
    +      term.scrollLines(delta > 0 ? step : -step);
     
           ev.preventDefault();
           ev.stopPropagation();
    ```
- **#28029: fix(dashboard): use browser scrollback for chat wheel**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `afffb8d9a56b850f98ba5d696de030c5c46b8030`, `#28584`
- **#29975: fix: improve dashboard terminal clipboard and wheel handling**. open
  - maintainer direction: category `uncategorized`; implication `needs_llm`; refs `#24860`, `#30007`, `#30008`, `#19084`, `#29989`
  - files: `ui-tui/src/__tests__/clarifyPasteResult.test.ts`, `ui-tui/src/components/prompts.tsx`, `web/src/pages/ChatPage.tsx`

## Fix status

- Merged to main in PR #28584 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-05-19`.
- Subsystem: `dashboard`
