# dsh-chat-ux English | [中文](./README.md) A chat-area UX plugin for the [DeepSeek Harness (dsh)](https://github.com/deepseek-ai/deepseek-harness) web GUI. With it installed, reasoning rows fold themselves away when thinking ends, process groups open and close on their own, and the composer and readouts take on this plugin's own look—and none of it ever yanks a reader who scrolled away. ## What it does - **Self-folding reasoning rows**: a reasoning row expands while thinking and folds when it ends; once you touch it yourself, it stops moving. - **Self-folding process groups**: a process group expands when a tool call starts and folds when that stretch ends, with a roller-blind transition in both directions. A row whose body holds several cards (`run_code`'s program plus its output) rolls as one blind, not card by card. Both share one "Automatic folding" switch on the Plugins page. A height-capped process group in standard / compact scrolls vertically only — that rule is always on and is not behind any switch. - **File change rows**: write / edit calls inside `run_code` show their diff lines right in the chat area For direct calls, the path, input size and `+n -m` appear while the arguments are still streaming, both counts growing as the content arrives (each starts counting as soon as its own field arrives, and neither waits for the path — a write puts `file_path` last); the digits at the end of the row pop on a beat so each reel turn plays out in full (same for a write and an edit), and switch to live following once the call settles (on by default; turn it off on the Plugins page). - **Caret motion**: the input caret slides, 80 ms, whether you type, arrow around, or click. It covers the main composer, the answer box of a question card, and the inline editor for queued messages (the one you use for follow-ups to a running subagent). - **Chat bubble motion** (on by default): the composer lifts off when you submit—its toolbar shrinks into the corners and fades, the card narrows into the bubble while the text re-wraps to fit—and lands in the transcript; the run is a fixed 300 ms. It runs entirely on the compositor, so it keeps its frame rate even while dsh's main thread is busy with the send. - **Work details default to Standard**: on the web client, dsh's "Work details" setting is filled in as **Standard** (dsh's own web default is Detailed). Once you pick a mode yourself under Settings → **General**, your choice wins and the plugin leaves it alone. - **Cache-hit rate**: the pill under the composer keeps one decimal, and its colour walks a six-stop ramp from 90% to 99% — red below 90, deep green at 99 and above; the label beside the reading takes the same colour (the token total and the separator dot in Detailed mode do not). When the reading changes, the digits that changed pop to their new values — each one drops back in from just below while the old digit fades out the other way (500 ms, lower digits starting later); a switch on the Plugins page turns it off. - **Context occupancy as a pie**: the ring becomes a solid 16px pie on a 20%–40% ramp (green below 20, red at 40 and above), with the reading in the same colour. The occupied slice is cut along a fold line pivoted at the centre and slides out along the bisector, and the gap between the two pieces is a constant 1.2px wide; turn the whole pie off on the Plugins page and dsh's own ring comes back. The percentage beside it pops too. - **Composer glass** (on by default): the input card keeps its own blue gradient — the same two-ends-tinted, middle-clear shape DSH uses on its sidebar, with the end tints kept faint enough to be only just visible — lets just under a tenth of it through, and adds a light blur plus a top highlight, an inner rim and a bottom inner shadow. The send button (stop while it runs) and the add button on the left wear the same material — a blue slice of that glass for the send circle, a neutral one for the add circle. The stats row below and the cards above are untouched, and the fade band above it still fades to the canvas colour. A switch on the Plugins page turns it off. - **Trajectory tab without the composer**: on the Trajectory tab dsh floats the composer over the ledger; the plugin takes the whole composer seat out so the ledger runs to the bottom, and it comes back the moment you switch back to Chat. ## Install In the dsh web GUI, open **Plugins** → **Add plugin** and enter the package name: ``` @alm-allen/dsh-chat-ux ``` Or from the command line (this forwards to pnpm inside the profile directory): ```sh dsh plugin --profile web add @alm-allen/dsh-chat-ux ``` Restart dsh and reload the page. To remove it, use the plugin page or: ```sh dsh plugin --profile web remove @alm-allen/dsh-chat-ux ``` ### Install from the GitHub repository You can also install straight from the repository — the build output is committed, so no build approval is required: ```sh dsh plugin --profile web add github:Alm-Allen/dsh-chat-ux ``` Pin it to a commit so later pushes cannot change what you installed: ```sh dsh plugin --profile web add github:Alm-Allen/dsh-chat-ux# ``` ## Configuration Every switch lives on the plugin's own row on the **Plugins** page: | Option | Default | Meaning | | --- | --- | --- | | Automatic folding | on | When off, reasoning rows and process groups stop opening and closing on their own; clicking still works. | | Caret motion | always | Three steps: off / on move / always. | | Chat bubble motion | on | When off, the send has no flight and the message simply appears. | | Cache-hit reels | on | When off, a changed rate swaps instantly. | | Context pie | on | When off, dsh's own ring comes back. | | Composer glass | on | When off, the composer, the send button and the add button all go back to dsh's own look, and nothing behind it is blurred. | | Live change counts | on | The `+n -m` at the end of a directly-called write / edit row grows while the content streams (each count starts as soon as its own field arrives), and a changed digit pops in place — on a beat while streaming, so each reel turn plays out in full. | "Work details" is not on the plugin card: it lives in dsh's own Settings → **General**, and the plugin only fills in Standard while you have not chosen a mode yourself. ## Compatibility - Developed and verified on dsh `0.2.1-alpha.2` (web) and `0.2.1-alpha.1` (desktop); **`0.2.0-rc.2` and older keep working** (the adaptation rounds in 2026-10 had silently broken three things on older releases — the cache-hit pill, the context pie, and the file-mutation row's preparing stage; all are now fixed). - On `0.2.0-rc.2` what you see matches the newer releases: the **cache-hit pill** is still drawn by the plugin (one decimal + the 90%–99% colour ramp). Only the takeover differs — that dsh has a single `stats` pill in the dock and id-based shadowing does not apply there, so the plugin hides dsh's own pill through the DOM instead (a plain `display: none`), which means you never get two readings side by side. - Older `0.1.x` was never checked release by release: the `data-composer-*` family only exists from dsh `0.2`, so the row under the composer may be shaped quite differently, and the plugin leaves it alone when it cannot recognise it. - Node `^22.19.0 || >=24.0.0`. ## About this repository This repository carries the plugin's source and release notes. Build scripts and internal design docs are not part of it, so a fresh clone cannot run `npm run build`; install the package from npm instead. Every release is recorded in [CHANGELOG.md](./CHANGELOG.md) — the tag-triggered workflow takes the release notes out of it. ## License [MIT](./LICENSE)