Bug Description
I added a task and created a new board and saw the original task disappear in the WebUI
Steps to Reproduce
- I created a kanban board from cli:
hermes kanban init
- I viewed the WebUI:
hermes dashboard
- I created a basic:
hermes kanban create "THING"
- I confirmed it in the WebUI
- I used the WebUI to create a new board (checkbox to switch was checked)
- The new board rendered in the UI, the tab bar for the original board showed (1) item, but the UI displayed no tasks at all.
- I re-created the task:
hermes kanban create "THING" and it now showed up on the second board in the UI, the dashboard was stopped/restarted and the original/default board shoed 0 tasks
- I then ran
hermes kanban list and saw both tasks on both boards and realized this was a WebUI issue
Expected Behavior
UI should display tasks for selected board, not just the active board
Actual Behavior
switching boards prevents all tasks from rendering in the WebUI
Affected Component
Tools (terminal, file ops, web, code execution, etc.), Other
Messaging Platform (if gateway-related)
No response
Debug Report
Report https://paste.rs/ahTfg
agent.log https://paste.rs/MJPsV
Operating System
MacOS 26.3.1
Python Version
3.11.15
Hermes Version
v0.12.0 (2026.4.30)
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
The docs expose the smoking gun in the WebSocket endpoint signature. From the REST surface table:
- REST endpoints:
GET /board, GET /tasks/:id, etc. — all accept ?board=<slug>
- WebSocket:
WS /events?since=<event_id> — no board= parameter shown
The dashboard card render isn't driven purely by the initial REST response. Per the docs, "the board reflects changes the instant any profile acts" and "reloads are debounced so a burst of events triggers a single refetch." Cards are rendered/refreshed via WebSocket-triggered refetches, not purely from the initial load.
So after your CLI boards switch:
| Surface |
Board resolution |
Result |
| REST /board?board=default |
localStorage → default |
Returns 1 task → count badge shows 1 |
| WebSocket /events?since=0 |
No board= param → falls back to server current file → new board |
Connects to wrong board, no events fire for default's task → card refetch never triggers |
The count and the cards are reading from different board scopes within the same page load. The initial REST response populates the count, but card column rendering depends on the WebSocket event stream to hydrate or confirm state — and that stream is silently connected to the wrong board.
The fix is that the WebSocket endpoint needs to accept and respect ?board=<slug>, sourced from the same localStorage value the REST calls use. As the docs note, "switching in the UI opens a fresh WS against the new board" — that mechanism exists for UI-initiated switches, but it's never triggered when the board changes externally via CLI.
Proposed Fix (optional)
Two parts: the WebSocket endpoint needs a board parameter, and the dashboard needs to detect external board changes.
Part 1 — Thread board through the WebSocket connection
The WS endpoint should accept ?board=<slug> and use it for scoping, the same way the REST endpoints do:
# plugins/kanban/dashboard/plugin_api.py
@router.websocket("/events")
async def events_ws(
websocket: WebSocket,
since: int = 0,
board: str | None = None, # add this
token: str | None = None,
):
await websocket.accept()
resolved_board = board or _resolve_current_board() # same helper REST calls use
db = kanban_db.connect(board=resolved_board)
...
And on the frontend, pass the board slug from localStorage when opening the connection:
// plugins/kanban/dashboard/src/kanban.tsx (or wherever the WS is opened)
const board = localStorage.getItem('hermes-kanban-board') ?? 'default';
const ws = new WebSocket(
`/api/plugins/kanban/events?since=${lastEventId}&token=${token}&board=${board}`
);
This makes the WS and REST calls consistent: both read board from localStorage, both scope to the same DB.
Part 2 — Detect external board changes and reconnect
Even with Part 1, if the CLI switches the board while the dashboard is open, the WS stays connected to the old board. The dashboard needs to poll GET /api/plugins/kanban/config (or a new GET /boards/current endpoint) on a slow interval and reconnect the WS if the server-side current board diverges from localStorage:
useEffect(() => {
const interval = setInterval(async () => {
const { current_board } = await fetchJSON('/api/plugins/kanban/config');
const localBoard = localStorage.getItem('hermes-kanban-board') ?? 'default';
if (current_board !== localBoard) {
// Surface a non-destructive banner: "Board switched to X in CLI — switch here?"
// Don't auto-switch; respect the intentional localStorage/current-file split
}
}, 30_000);
return () => clearInterval(interval);
}, []);
The auto-switch is intentionally avoided — the docs call the localStorage/current decoupling a feature ("so it persists across reloads without shifting the CLI's current pointer out from under a terminal you left open"). The right UX is a dismissible banner that lets the user decide, not a silent takeover.
What this doesn't need: changes to kanban_db, the REST handlers, or the board resolution order. The bug is entirely in the WS connection setup; the underlying data is correct throughout.
Are you willing to submit a PR for this?
Bug Description
I added a task and created a new board and saw the original task disappear in the WebUI
Steps to Reproduce
hermes kanban inithermes dashboardhermes kanban create "THING"hermes kanban create "THING"and it now showed up on the second board in the UI, the dashboard was stopped/restarted and the original/default board shoed 0 taskshermes kanban listand saw both tasks on both boards and realized this was a WebUI issueExpected Behavior
UI should display tasks for selected board, not just the active board
Actual Behavior
switching boards prevents all tasks from rendering in the WebUI
Affected Component
Tools (terminal, file ops, web, code execution, etc.), Other
Messaging Platform (if gateway-related)
No response
Debug Report
Operating System
MacOS 26.3.1
Python Version
3.11.15
Hermes Version
v0.12.0 (2026.4.30)
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
The docs expose the smoking gun in the WebSocket endpoint signature. From the REST surface table:
GET /board,GET /tasks/:id, etc. — all accept?board=<slug>WS /events?since=<event_id>— noboard=parameter shownThe dashboard card render isn't driven purely by the initial REST response. Per the docs, "the board reflects changes the instant any profile acts" and "reloads are debounced so a burst of events triggers a single refetch." Cards are rendered/refreshed via WebSocket-triggered refetches, not purely from the initial load.
So after your CLI
boards switch:The count and the cards are reading from different board scopes within the same page load. The initial REST response populates the count, but card column rendering depends on the WebSocket event stream to hydrate or confirm state — and that stream is silently connected to the wrong board.
The fix is that the WebSocket endpoint needs to accept and respect
?board=<slug>, sourced from the same localStorage value the REST calls use. As the docs note, "switching in the UI opens a fresh WS against the new board" — that mechanism exists for UI-initiated switches, but it's never triggered when the board changes externally via CLI.Proposed Fix (optional)
Two parts: the WebSocket endpoint needs a
boardparameter, and the dashboard needs to detect external board changes.Part 1 — Thread
boardthrough the WebSocket connectionThe WS endpoint should accept
?board=<slug>and use it for scoping, the same way the REST endpoints do:And on the frontend, pass the board slug from localStorage when opening the connection:
This makes the WS and REST calls consistent: both read board from localStorage, both scope to the same DB.
Part 2 — Detect external board changes and reconnect
Even with Part 1, if the CLI switches the board while the dashboard is open, the WS stays connected to the old board. The dashboard needs to poll
GET /api/plugins/kanban/config(or a newGET /boards/currentendpoint) on a slow interval and reconnect the WS if the server-side current board diverges from localStorage:The auto-switch is intentionally avoided — the docs call the localStorage/
currentdecoupling a feature ("so it persists across reloads without shifting the CLI's current pointer out from under a terminal you left open"). The right UX is a dismissible banner that lets the user decide, not a silent takeover.What this doesn't need: changes to
kanban_db, the REST handlers, or the board resolution order. The bug is entirely in the WS connection setup; the underlying data is correct throughout.Are you willing to submit a PR for this?