> **A slim minimap rail on the LEFT edge of the DeepSeek Harness Web GUI chat pane: every message you sent becomes a tick — hover for a preview, click to jump, drag to scan long sessions.**
[](LICENSE)
---
## 1. The problem it solves
In a long session, going back to "what did I say earlier?" means endless wheel scrolling. The assistant's replies are long and dense, and your own messages get buried in between.
This plugin adds a thin navigation rail on the **left edge** of the chat pane (like the VS Code minimap):
```
chat scroll pane (overflow-y: auto, long sessions are paged)
│ each turn = one tick (including not-yet-loaded history, from the official turnOutline projection)
│ ticks of in-viewport turns = bold highlight
│
▼ hover a tick → preview card (index / total + prompt excerpt + time line)
▼ click a tick → smooth-scroll to that turn (official loadThrough(seq) pages it in first)
▼ click/drag the rail → proportional jump
```
**Read-only**: the client only reads the conversation DOM already rendered in the browser (chat rows carry stable `data-chat-flow-kind` / `data-chat-flow-key` / `data-chat-turn` anchors) and scrolls the existing chat scroll container. The full list comes from the official **`turnOutline` session projection** (whole-log turn outline: turn number, `turn/start` seq, bounded prompt/response previews), and paging uses the official **`sessions.binding(id).session.loadThrough(seq)`** ("page backwards until the window covers seq").
> Since 0.5.0 the **host half is a no-op**: no route, no session-log parsing. That also drops the dependency on the on-disk log layout, which changed in 0.1.7 (`session.v3/v4.jsonl.zstd`, new container format).
> Compatibility: requires **DSH ≥ 0.1.7** (`turnOutline` is provided by `@deepseek-ai/dsh-session-turn-outline`, registered by the `dsh-web-app` composition). On older versions the rail degrades to loaded turns only.
## 2. Features
- ✅ A **compact, vertically centered** rail on the chat pane's left edge (not full height) — zero layout interference.
- ✅ **One tick per turn** (i.e. per message you sent), evenly spaced on the rail (oldest at top, newest at bottom) — never scattered by message sizes.
- ✅ **Immune to history paging**: ticks cover ALL turns (including history not yet rendered via "load older") — sourced from the official `turnOutline` projection, so the full ladder shows as soon as the session opens, **without scrolling up yourself**.
- ✅ **Exact jumps**: an unloaded turn is fetched with the official `loadThrough(seq)` in one call ("page backwards until the window covers that turn's `turn/start` seq") — no blind page-by-page probing, and no drift.
- ✅ **Ticks of the turns inside the viewport are auto-bolded**, following the scroll in real time.
- ✅ **Fisheye magnification while sweeping the rail**: the tick under the pointer grows longest, its neighbors grow by a cosine distance falloff (CSS-transitioned) — spot the target at a glance.
- ✅ **Hovering a tick** pops a preview card: `My message · 3 / 12` plus the prompt excerpt and a dedicated time line (taken from the rendered turn).
- ✅ **Clicking a tick** smooth-scrolls to that turn (parked ~18% below the pane top).
- ✅ **Clicking or dragging the rail background** jumps proportionally, like a scrollbar.
- ✅ Follows streaming output, history loading, session switches and window resizes automatically (MutationObserver + scroll/resize + polling fallback).
- ✅ Hides itself when the content doesn't overflow, when there are no turns, or on the new-session hero screen — zero layout interference.
- ✅ Bilingual (zh/en) UI strings following the GUI language.
- ✅ Keyboard accessible: ticks are native `