dsh-client-ui-rtl
Right-to-left text direction for the DeepSeek Harness Web client
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 27, 2026
- Updated
- Aug 27, 2026
Introduction
dsh-client-ui-rtl
Right-to-left text direction for the DeepSeek Harness Web client.
The client renders left-to-right by default. Arabic, Hebrew, Persian, Urdu and other right-to-left content therefore arrives correct as text but wrong on screen: bullets sit on the left, table columns run the wrong way, and any sentence mixing Latin and RTL words is reordered against its meaning.
This package marks right-to-left content as it renders, and leaves everything else alone.
Before and after
An Arabic answer mixing English technical terms:
| Before | After |
|---|---|
![]() | ![]() |
A short prompt opening with a Latin product name — the case dir="auto" gets
wrong:
| Before | After |
|---|---|
![]() | ![]() |
Install
dsh plugin --profile web add github:haythamat/dsh-client-ui-rtl
Restart dsh web afterwards. The package ships its own patch layer, so no
configuration file needs editing.
How direction is decided
Direction is decided by script dominance, not by the first strong character
in the block. dir="auto" reads only the first strong character, which fails on
technical writing in Arabic and Hebrew — a sentence opening with a product name
such as Git or GitHub is laid out left-to-right and every word after it is
misordered.
Instead, each element's text is weighed by words, not characters. Words
matter because right-to-left words are short while Latin technical terms are
long: اشرح لي ال Agentic AI is eight Arabic characters against nine Latin
ones, but three Arabic words against two Latin ones. When right-to-left words
are at least as common, the element is marked dir="rtl". Blocks with no
right-to-left words are never touched, so a bilingual session keeps its English
messages left-to-right.
Elements are judged on the text they hold directly, not on their descendants, so a wrapper containing many children is not flipped on account of its contents. Tables and lists are the exception: they are judged on their whole subtree, because column order and list markers only reorder when the container itself flips.
What is left alone
code, pre, kbd, samp, var, form controls, and embedded media are never
marked — their direction is meaningful as authored. An element carrying a dir
attribute this package did not set is also left as it is, which is the escape
hatch if the heuristic gets something wrong.
Streaming
A MutationObserver watches for added nodes and changed text, batched to one
pass per animation frame, so assistant messages are corrected as they stream
rather than only on load. Elements are reconciled rather than marked once: a
block whose balance shifts while it streams has its direction withdrawn or
applied to match.
Attribute mutations are deliberately not observed, since this package writes attributes and watching them would feed its own writes back in.
Model Experience
None, as the package contributes browser presentation only; nothing here reaches a model request.
KV Cache effect
None; this package neither assembles nor sends a provider request.
Known Limitations and Deferred Work
- Presentation only, not layout — the shell itself stays left-to-right. The sidebar remains on the left and controls keep their positions. Mirroring the application shell belongs in a separate package occupying the layout slots.
- The browser title is independent —
DSH_CLIENT_TITLEselects title text at build time rather than through a UI slot. - Dominance is a heuristic — a block that is evenly balanced between scripts resolves to right-to-left.
License
MIT



