dsh-chat-locator
Turn-rail settings for DSH Web: tick thickness, rail side, and a curved length gradient anchored on the hovered tick — plus a plain-text hover preview whose line count, font size, and width you control.
[](LICENSE)

[](https://nodejs.org)
[](https://github.com/hawkongz/dsh-chat-locator)
Language: English | 简体中文
---
## 📋 Table of Contents
- [Features](#-features)
- [Quick Start](#-quick-start)
- [Installation](#-installation)
- [Usage](#-usage)
- [How It Works](#-how-it-works)
- [Topics](#-topics)
- [Contributing](#-contributing)
- [License](#-license)
---
DSH Web draws a turn rail down the edge of every conversation: one tick per turn, so you can see where you are in a long session and jump between turns. It is a good rail with three opinions baked into it. Ticks are always 2px. The rail always sits on the right. And pointing at a tick tells you nothing about what that turn contains, so finding a specific turn in a long conversation means hovering ticks one at a time.
None of that is configurable. The rail is rendered directly by `ChatView` inside `@deepseek-ai/dsh-client-ui-chat`; the Slot system gives it no seat, and no setting for thickness or side is exposed anywhere.
`dsh-chat-locator` is a persistent DSH plugin that turns those fixed opinions into settings. It does not replace the rail — it claims the rail's styles at runtime, so the built-in jump-to-turn, unloaded-turn paging, and active-turn following all keep working exactly as before.
## ✨ Features
- **Tick thickness (横线粗细):** 1–8px instead of a fixed 2px. Only the line width changes; the 10px tick spacing stays put.
- **Rail side (轨道位置):** Left or right. The hover preview automatically opens on the opposite side, so it never covers the text you are reading.
- **Hover preview (悬停预览):** A plain-text card showing that turn's prompt and response. Thinking content can never appear in it, whitespace is collapsed so it cannot contain a blank line, and long text is truncated with an ellipsis.
- **Preview line count (预览正文行数):** 1–6 lines. The card really grows — only the overflow is clipped.
- **Preview font size and width (预览字号 / 预览框宽度):** 10–18px and 200–420px. Font size and line height scale as a pair, so enlarging the text never crowds or clips it.
- **A curved length gradient:** With the preview on, the tick under the pointer grows to 32px and its neighbours taper back along a curve — `21 / 14 / 12` — so the rail reads as a hook pointing at where you are, not as a straight diagonal.
- **Restore defaults (恢复默认):** All seven settings back to factory values in one click, via per-field `unset` rather than rewriting the defaults.
- **A dedicated settings page:** Settings → 对话定位条, with a live sample rail and sample preview card that redraw as you change each value.
- **Zero dependencies, no build step.** Both halves are plain ESM loaded directly by Node and the browser.
## 🚀 Quick Start
> **What you need:** a working DSH installation (the `dsh` command) with a profile, plus Node.js 20 or newer. The plugin itself has no dependencies to install.
**Step 1 — Open a terminal**
- macOS / Linux: open Terminal.
- Windows: press `Win + R`, type `powershell`, and press Enter.
**Step 2 — Install the bundle into your profile**
`dsh plugin` forwards its arguments to pnpm inside the profile directory, so this registers the bundle as a dependency and DSH picks up its patch automatically. Replace `web` with your own profile name if it differs.
```bash
dsh plugin --profile web add github:hawkongz/dsh-chat-locator
```
That is the whole install. It fetches the four files a DSH plugin bundle needs — `package.json` (which declares the bundle and the browser half), `index.js` (the host half), `client.js` (the browser half), and `cordis.patch.yml` (the patch that adds the plugin row) — and there is nothing to compile and no dependency to install.
**Step 3 — Restart the host**
```bash
dsh web
```
The host process caches imported modules, so a newly added bundle is not mounted until the host restarts once.
**Step 4 — Done.** With DSH Web open at `http://127.0.0.1:3080`, you are finished if:
- **Settings → 对话定位条** appears in the settings sidebar, and
- in the browser console, this returns `railFound: true` on a conversation with at least two turns:
```js
__dshChatLocator.state()
```
Open a conversation and slide the pointer up and down the rail: the tick under the pointer grows and its neighbours taper.
> To update: run `dsh plugin --profile web update dsh-chat-locator`, then restart the host. To uninstall: `dsh plugin --profile web remove dsh-chat-locator`, then restart the host.
>
> **Installing offline, or want a local copy you can edit?** Download the four files instead and install the folder — see [Install without git](#install-without-git).
## 📦 Installation
### Requirements
| Requirement | Version | Notes |
| :--- | :--- | :--- |
| DSH | 11.x | Provides the `dsh` command and the profile you install into. |
| Node.js | 20 or newer | Used by the host half and the test suite. |
| A browser with `:has()` support | Chromium 105+ | Without it the length gradient does not apply; everything else still works. |
### Install methods
| Method | Best for |
| :--- | :--- |
| `dsh plugin --profile web add github:hawkongz/dsh-chat-locator` | Most users. One command, and it is what the Quick Start uses. |
| From a git clone | Pinning a revision, or working on the plugin itself. |
| From four downloaded files | No git available, or an offline machine. |
### Install from a git clone
Use this if you would rather update with `git pull` than by re-downloading files.
```bash
git clone https://github.com/hawkongz/dsh-chat-locator.git
cd dsh-chat-locator
dsh plugin --profile web add "$(pwd)"
dsh web
```
### Install without git
A bundle is four files. Download them into a folder, install the folder, and restart the host — nothing else is needed.
macOS / Linux:
```bash
mkdir -p ~/.dsh/plugin-src/dsh-chat-locator
cd ~/.dsh/plugin-src/dsh-chat-locator
curl -fsSLO https://raw.githubusercontent.com/hawkongz/dsh-chat-locator/main/package.json
curl -fsSLO https://raw.githubusercontent.com/hawkongz/dsh-chat-locator/main/index.js
curl -fsSLO https://raw.githubusercontent.com/hawkongz/dsh-chat-locator/main/client.js
curl -fsSLO https://raw.githubusercontent.com/hawkongz/dsh-chat-locator/main/cordis.patch.yml
dsh plugin --profile web add ~/.dsh/plugin-src/dsh-chat-locator
```
Windows (PowerShell):
```powershell
$dir = "$env:USERPROFILE\.dsh\plugin-src\dsh-chat-locator"
$base = "https://raw.githubusercontent.com/hawkongz/dsh-chat-locator/main"
New-Item -ItemType Directory -Force -Path $dir | Out-Null
foreach ($file in "package.json", "index.js", "client.js", "cordis.patch.yml") {
Invoke-WebRequest -Uri "$base/$file" -OutFile "$dir\$file"
}
dsh plugin --profile web add "$dir"
```
Then restart the host:
```bash
dsh web
```
### Notes on installation
- **DSH registers the bundle for you.** A package that declares `dsh.bundle.patch` is added to your profile's `dsh.profile.bundles` list automatically, so `dsh plugin add` is the only step.
- **There is no build step.** pnpm may print a note about blocked build scripts for git-hosted packages; this plugin has no `prepare` script and no dependencies, so there is nothing to allow.
- **Restart the host after installing or removing.** See [How It Works](#-how-it-works) for why.
- **Installation is per profile.** `--profile web` is the profile this plugin was developed against; substitute your own.
## 📖 Usage
Everything lives on one settings page: **Settings → 对话定位条**. The table below lists each control with its default and range.
| Setting | Default | Range | What it does |
| :--- | :--- | :--- | :--- |
| Show the locator rail