Skip to content

dsh-rtl-fix

Verified

dsh-rtl-fix Β· v1.0.2 Β· MIT Β· Web UI

Proper RTL rendering for DeepSeek Harness web chat: any line containing RTL scripts renders fully RTL (right-aligned, correct bidi word order) even when it embeds English words, plus RTL-aware composer input.

Install

dsh plugin add dsh-rtl-fix

Confirm the layer applied with dsh --profile default --dump-config β€” see the install guide.

Source

Creators

Readme

dsh-rtl-fix

npm version npm downloads License: MIT

Proper RTL rendering for DeepSeek Harness (dsh) web chat.

Arabic, Hebrew (and any other RTL script) chat lines render fully RTL β€” right-aligned, correct bidi word order, list markers on the right β€” even when the line embeds English words, e.g.:

ShiftController::show() β€” أآفΨͺ Ψ­Ψ³Ψ§Ψ¨ ΨΉΨ―Ψ― Ψ­Ω‚ΩŠΩ‚ΩŠ

  • βœ… Any line containing at least one RTL letter is treated as a full RTL line
  • βœ… English/paths inside an RTL line keep their correct internal order
  • βœ… Ordered/unordered list markers (1. / β€’) render on the right
  • βœ… Code blocks (pre / code) stay LTR β€” JSON, paths and code never flip
  • βœ… The composer input and its mirror follow the draft as you type
  • βœ… Streaming-safe: directions re-apply automatically on every re-render
  • βœ… No configuration needed β€” works out of the box

Install

In a DeepSeek Harness web or desktop profile. From npm:

dsh plugin --profile desktop add [email protected]

Or for the web profile:

dsh plugin --profile web add [email protected]

Or directly from GitHub (no npm involved):

dsh plugin --profile desktop add github:ahmedtohamy1/dsh-rtl-fix#main

Either can also be run through npx:

npx -y @deepseek-ai/dsh plugin --profile desktop add [email protected]        # npm
npx -y @deepseek-ai/dsh plugin --profile desktop add github:ahmedtohamy1/dsh-rtl-fix#main   # GitHub

Then restart dsh and refresh the browser. That's it β€” RTL lines in the chat now render correctly.

Troubleshooting β€” ERR_PNPM_IGNORED_BUILDS: If dsh plugin add fails with [ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: @google/genai, protobufjs, those are host dependencies of dsh itself (not this plugin) that pnpm 11 requires you to approve once per profile. Open pnpm-workspace.yaml in your web profile β€” %USERPROFILE%\.dsh\profiles\web\pnpm-workspace.yaml on Windows, ~/.dsh/profiles/web/pnpm-workspace.yaml on macOS/Linux β€” and set:

allowBuilds:
  '@google/genai': true
  protobufjs: true

then re-run the same dsh plugin --profile web add ... command. One-time only β€” future installs won't ask again. Alternatively run pnpm approve-builds inside that profile directory.

Verify

  • Open a chat containing Arabic text. Lines with mixed English should be right-aligned and read right-to-left; numbered/bulleted lists put their markers on the right.
  • Console handle for manual checks:
__dshRtlFix.scanAll()   // re-apply directions now, returns a report object

Uninstall

dsh plugin --profile web remove dsh-rtl-fix

How it works

A tiny client-only plugin (one loader row + a browser bundle; the host half only carries the small diagnostics route below). It watches the conversation DOM and, for every block-level text element (paragraphs, list items, ol/ul, table cells, leaf text containers) inside the chat scroll scope, sets dir="rtl" whenever the element's text contains any RTL character β€” overriding the browser's dir="auto" first-strong-character heuristic, which is exactly what made lines starting with an English word render LTR.

dir is enough: the chat styles never pin text-align, so the CSS initial text-align: start follows the direction β€” RTL lines right-align automatically. A MutationObserver plus a periodic sweep re-apply the fix after any re-render (streaming, session switches, etc.).

What stays LTR

  • Markdown/code blocks (pre, code, kbd, samp, var)
  • Pure-LTR lines (direction is set to ltr explicitly if a parent forced RTL)
  • Non-conversation UI (sidebar, settings, titles) β€” untouched by design

Diagnostics

The host half exposes a tiny loopback endpoint the client pings on startup and whenever it changes directions, appended to:

<DSH_HOME>/plugins/dsh-rtl-fix/pings.log

pings.log is runtime data, never tracked in the repository. Useful when reporting issues β€” delete it any time; it regenerates.


Development

dsh-rtl-fix/
β”œβ”€β”€ package.json          # dsh bundle + web client metadata (name: dsh-rtl-fix)
β”œβ”€β”€ cordis.patch.yml       # inserts the loader row (id: rtl-fix β†’ package dsh-rtl-fix)
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ index.js           # host half: ping/telemetry route (no core logic)
β”‚   └── client.js          # the RTL scanner (module-loader entry, all logic here)
β”œβ”€β”€ LICENSE                # MIT
└── README.md

Local iteration while developing:

# point the profile at your checkout with an existing real path
dsh plugin --profile web add link:C:\path\to\dsh-rtl-fix

Client changes are served from disk per request β€” a browser hard refresh (Ctrl+F5) applies them without a host restart. Host-side changes (like the ping route) need a dsh restart.

The scanner at a glance

  • Scope: elements under [data-conversation-scroll] (the chat column)
  • Target selectors: p, li, blockquote, h1..h6, dt, dd, td, th, ol, ul + leaf text containers
  • Rule: any RTL character in the element's textContent β†’ dir="rtl"
  • Exclusion: anything inside pre, code, kbd, samp, var

If a future dsh release changes the markdown DOM, adjust these in lib/client.js β€” the debug handle __dshRtlFix.scanAll() returns { scope, flow, arabicFlow, changed, composer, err, … } to help you see what the scan is matching. The chat scan deliberately skips the composer subtree ([data-composer-card] / [data-composer-seat] / Lexical editor nodes); the composer is driven separately by syncComposer(), which supports both the legacy textarea + backdrop/mirror composer (≀ 0.1.1) and the Lexical div[contenteditable][data-composer-input] composer (β‰₯ 0.1.5).


Requirements

  • DeepSeek Harness 0.1.x (web or desktop profile) β€” dsh must expose the standard client-plugin surface (dsh.client bundles + loader rows)
  • A Chromium/Firefox/WebKit browser β€” the fix is pure DOM/CSS, no dependencies, no network calls, no API keys
  • Verified on dsh 0.1.1-rc.2 (Windows Β· Chrome/Edge) and macOS, and on dsh 0.1.5-rc.2 (DSH Desktop Β· desktop profile) β€” if something doesn't look right on your combo, open an issue and attach the output of __dshRtlFix.scanAll()

License

MIT β€” see LICENSE.