Fold completed turns into their final conclusions, split thinking from prose with a divider, and jump between turns from a rail dockable left or right with line or dot marks, an optional ring and hover summaries; it can hide the host right-edge TurnNavigator, load earlier history, and open a pre-filled diagnostics issue.
Install
# from npm (prebuilt)
dsh plugin --profile web add @bananasoldier01/dsh-tidychat
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:BananaSoldier01/dsh-tidychat
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
🧩 A web plugin for DeepSeek Harness (
dsh), listed in awesome-dsh-plugin.
Turn long DSH conversations into a scannable, skippable stream of conclusions.
In multi-task sessions, thoughts, tool calls, intermediate text and final summaries pile up, making it hard to find "the conclusion of that last task". dsh-tidychat folds completed turns into a single conclusion line, separates thinking from prose with a divider, and adds a Codex-style navigation rail (Canvas minimap) along the chat edge.
Maintenance focus (from 0.4.0): Upstream DSH Web now covers much of the same ground (fold, rail, etc.). This plugin is primarily under compatibility maintenance — tracking host settings/DOM contract changes so it stays installable on the target DSH line, not chasing new features. Still useful if you want this rail's dock/style/colors, official-rail takeover, smart earlier-history load, or you stay on DSH 0.1.x (use 0.3.1).
✨ Features
| Feature | Description |
|---|---|
| 🗂 Auto-fold | Completed turns fold away thinking (Think), tool calls and intermediate text, keeping only the final summary; the control bar shows "N steps" and timing |
| ➖ Divider | A solid line between thinking and prose — one glance separates "process" from "conclusion" |
| 📍 Navigation rail | Global navigation along the chat edge: fish-eye hover, drag preview, click-to-jump, current-turn highlight. Dockable left or right (right mirrors everything), styles line / dot, plus a separate ring toggle; colours auto-adapt or come from a colour picker. When earlier history is not loaded yet, an arrow appears at the rail's top — click it to load |
| 🎛 Take over the official rail | Hides DSH 0.1.2+'s native right-edge TurnNavigator so this plugin's rail takes over (off by default; hides rather than unmounts) |
| ⬆ Smart earlier-history load | Gradually loads older records while idle; pauses automatically when responsiveness drops; manual load still available |
| 📤 One-click issue report | Generates a diagnostic report (version / browser / performance / anomaly detection / symptom tags) and opens a pre-filled GitHub issue |
All five toggles are independent ("Settings → Built-in plugins → 会话整理 tidychat", applied instantly). On DSH 0.2.x, the first time both rails are present a one-time guide explains "left = this plugin / right = official DSH" and offers three one-click choices.
📸 Screenshots
Auto-fold: completed turns collapse to a control bar with only the final conclusion (top); click "expand" to restore thinking, tool calls and intermediate text (bottom).
Navigation rail: dockable left or right, style line / dot, ring independently toggleable. Hovering shows that turn's summary; clicking jumps to it.
When earlier history is not loaded (turns above are not mounted yet — common right after opening a long session): an arrow and a dashed line appear at the top of the rail; hovering explains the current coverage and clicking loads earlier records.
Settings card: five toggles (fold / divider / rail / take over the official rail / smart earlier-history load) + the rail's position · style · ring + colors + symptom tags and one-click diagnostics.
🚀 Install
Prerequisite: DSH (Web) installed, pnpm on PATH.
# Option 1 (recommended): npm package, prebuilt — no allowBuilds approval needed
dsh plugin --profile web add @bananasoldier01/dsh-tidychat
# Option 2: from GitHub (pin a tag for reproducibility)
dsh plugin --profile web add git+https://github.com/BananaSoldier01/dsh-tidychat.git#v0.4.0
Restart dsh web + hard refresh (Cmd+Shift+R) after installing. 0.4.0 supports DSH 0.2.x only.
Update
The plugin is installed as a profile dependency; updating just re-pulls that dependency (only this plugin, no full DSH re-download):
# Option A: npm-installed — update directly
dsh plugin --profile web update @bananasoldier01/dsh-tidychat
# Option B: pinned to a tag — re-add pinned to the new tag
dsh plugin --profile web add git+https://github.com/BananaSoldier01/dsh-tidychat.git#v0.4.0
Restart dsh web + hard refresh after updating.
⚠️ Version lines do not mix. DSH 0.1.7 removed the imperative
settings.register/installSectionAPIs and replaced them with declarative Config.volatile()fields. Calling.volatile()on 0.1.6 throwsTypeError. One build cannot support both ≤0.1.6 and ≥0.1.7.
Plugin DSH 0.4.0+ (this line, npm dist-tag dsh-0.2)0.2.x 0.3.1 (last release for 0.1.0-rc.7 ~ 0.1.6) 0.1.0-rc.7 ~ 0.1.6 0.1.0≤ 0.1.0-rc.6 (needs the whitelist patch below) DSH 0.1.7 is on neither line: 0.3.1's registration APIs are gone, and 0.4.0's peers accept 0.2.x only. Upgrade the host to 0.2.x, then install 0.4.0.
DSH ≤ 0.1.0-rc.6 only (plugin
0.1.0): the host hardcodes its plugin-namespace whitelist, so third-party switches appear greyed out. Runscripts/whitelist-patch.shonce (idempotent):curl -sL https://raw.githubusercontent.com/BananaSoldier01/dsh-tidychat/main/scripts/whitelist-patch.sh | bash
🧩 Compatibility
| Plugin | DSH | Settings surface |
|---|---|---|
| 0.4.0+ | 0.2.x (checked against 0.2.0-rc.2) | Declarative: Config .volatile() fields are auto-rendered; the browser half reads ctx.configForms.get('tidychat'); the full settings card is a settings.plugins.tab |
| 0.3.1 (last release for this range) | 0.1.0-rc.7 ~ 0.1.6 | Imperative: register (through 0.1.1) / installSection (0.1.2 ~ 0.1.6). Fold / divider / auto-load work since plugin 0.2.8; the rail works since 0.3.0 (on 0.2.10 and earlier the rail read the wrong snapshot, resolved 0 turns and never rendered) |
- Since DSH 0.1.2 the host folds process content and ships a right-edge TurnNavigator; on 0.2.x upstream covers even more, overlapping this plugin heavily. Prefer the official UI for most cases; turn on this plugin's rail / takeover only when you want its dock/style/colors (otherwise you risk double-fold or two rails).
- Takeover hides rather than unmounts: the host exposes no native switch, so with takeover on the official component stays mounted (its DOM remains) — what stops is painting, layout, interaction and scroll-following. On 0.2.0-rc.2 the official rail is a virtual list and no longer writes
--turn-natural-position; hiding anchors on thediv.*_slot > nav.*_framestructure (CSS-module hashes are not hardcoded).
⚙️ Settings
Open the 会话整理 tidychat tab under "Settings → Built-in plugins" (changes apply instantly):
| Item | Config key | Default | Description |
|---|---|---|---|
| Auto-fold completed turns | fold |
on | Hides thinking, tool calls and intermediate text, keeping only the final conclusion |
| Thinking ↔ text divider | divider |
on | Inserts a solid line between the thinking row and body text |
| Rail | navigator |
on | The thin navigator along the chat edge; turning it off leaves no plugin rail at all |
| Take over the official rail | hideOfficialNav |
off | Hides DSH 0.1.2+'s native right-edge TurnNavigator; do not enable it while the rail itself is off |
| Smart earlier-history load | autoLoad |
on | Loads older records while idle, pausing automatically when responsiveness drops |
| Position | navSide |
left | left / right (right mirrors everything: bars grow leftward, the accent arrow points left, the hover card opens to the left) |
| Style | navStyle |
line | bar line / dot dot; both keep the fish-eye zoom and click-to-jump |
| Ring | navRing |
off | Accent outline (1px, offset 2px) around the current and hovered marks; a capsule for lines and a true circle for dots |
| Colors (advanced, collapsible) | navColor navAccent … |
auto | Default color and accent each offer auto / custom. Auto: the default color uses the host muted label, switching to a corrective gray when contrast vs the chat background is insufficient; the accent follows the theme brand color. Custom: native picker (continuous) or an exact HEX / rgb() / rgba() value plus an alpha slider. The accent also drives the current/hover highlight and the ring stroke |
| First-run guide | navGuideSeen |
off | Shows a one-time guide when both rails are present; "Show the first-run guide again" recalls it any time |
New defaults only affect fresh installs — existing installs keep the values already materialised in their settings, so a historical
navigator: falsemust be turned on manually.
🔧 How it works
Pure browser half (exports "./client"). The host half only declares a Config schema with .volatile() fields — it registers no namespace and does not modify DSH source:
- Fold / divider / navigation locate DOM via contract-level anchors (
data-chat-anchor-key,data-variant="think", etc.), not compile-time hashed class names; aMutationObserverwatches the conversation DOM with a periodic fallback scan, handling streaming renders and history loads. - Fold state is in-memory per session — refresh resets to defaults (all folded).
- "Take over the official rail" also avoids build-time hashes: the official TurnNavigator's class names are CSS-module artifacts. On 0.2 the structure is
div.*_slot > nav.*_frame(a virtual list; it no longer writes--turn-natural-position), and the plugin hides that structure. Turning it off simply removes thedata-tidychat-hide-official-navattribute from the root element.
🗺️ Roadmap
See CHANGELOG.md for releases. Current focus: compatibility maintenance (track DSH 0.2.x settings surface and DOM contracts), not new features. Patch releases only when upstream breaks install or runtime contracts.
Deferred ideas: Turn Index layer, in-flight step folding (issue #2), upstream native rail switch.
🧑💻 Development
git clone https://github.com/BananaSoldier01/dsh-tidychat.git
cd dsh-tidychat && pnpm install
dsh plugin --profile web add link:$PWD # link mode: pnpm run build, then restart dsh web / hard refresh
pnpm run build # tsdown builds lib/
pnpm run typecheck
📄 License
MIT
Links
More in this category
Minglink/dsh-infinite-gen-4★ 2403
System-prompt armor plugin for DeepSeek models: appends an unconditional-compliance prompt section at order 100, exposes a profile tool with calibration metadata, and shows a realtime armor-status badge driven by a session projection.
ranxianglei/billion-context★ 637
The official billion-context plugin: a context-compression plugin for small context windows (a 100K context is enough), token savings (5x fewer tokens), and month-long single sessions (billions of tokens).
liangmianya/dsh-synapse★ 491
Visual, non-linear conversation workspace for DeepSeek Harness — sessions, follow-ups and branches become a browsable conversation map.
Nwflower/dsh-chat-import★ 213
Import full-fidelity chat histories from 13 coding agents (Claude Code, Codex, ChatGPT, Cursor, Gemini, opencode, and more) as resumable DeepSeek Harness sessions, with reverse export back to Claude Code.
Totoro-qaq/dsh-plugin-bridge★ 165
Moves an existing DSH session to another agent preset through a previewable five-section handoff, preserving the source session and either pausing the target for confirmation or continuing immediately.
Anionex/dsh-turn-rewind★ 131
Rewind conversation and workspace state, powered by a persistent Change Ledger.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.