dsh-agentbox
Mobile and small-screen fixes for the DeepSeek Harness (DSH) web shell, packaged as a plugin rather than a patch — so it survives DSH updates.
Born from running DSH as an always-on agent box driven mostly from a phone. DSH's web shell is desktop-first: its entire stylesheet contains exactly one media query (prefers-reduced-motion) and no responsive breakpoints, so at phone widths it renders the desktop three-column layout unreflowed.
What it does
Everything ships behind a toggle and defaults to on.
| Toggle | Effect |
|---|---|
mobileCss |
≤640px only: reclaims the 56px rail, lets the open sidebar overlay the chat instead of squashing it, makes tapping a session auto-collapse the sidebar, and stops the transcript bleeding through the composer. |
usageDockCompact |
Keeps the usage indicator to one line. |
usageDockTerse |
Rewrites the dock to glyphs (↓319M ·↑937K ·⚡100%), dropping the noisy metrics. |
enterNewline |
On mobile, Enter breaks the line and the send button sends — the mobile convention. Stock DSH sends on Enter and only Shift+Enter breaks the line, which is two awkward taps on a phone keyboard. |
Plus small correctness fixes: the composer gets an opaque background so the transcript can't paint through the band around it, and the dock is set to wrap rather than clip.
Install
# into a profile — `dsh plugin` forwards to pnpm in the profile directory
dsh plugin --profile web add github:charysrinathsc/dsh-agentbox
# then sign the profile
dsh restart
The package carries a dsh.bundle.patch, so it is composed into the profile automatically. To disable a feature, override it in the profile's cordis.patch.yml:
- id: dsh-agentbox
config:
enterNewline: false
Requirements
- DSH with a web profile
- A browser at ≤640px for the mobile work; the rest applies at any width
Caveats, stated honestly
- The composer still sits behind the iOS keyboard. iOS Safari shrinks the visual viewport but not the layout viewport, so the composer's toolbar row ends up under the keyboard. A fix that resized the frame to
visualViewport.heightmade this worse and was reverted — seeINTERNALS.md. Treat this as an upstream issue. - Class names are hashed (
_3WPZCG_toggle,yhfFVG_card). They are matched by substring, which is inherently fragile.tools/health.mjschecks 25 load-bearing assumptions against a running instance and exits non-zero when DSH moves something. - Developed and verified against one DSH version. It is CSS and DOM-shape dependent; expect to re-check after DSH updates.
Development
INTERNALS.md is the engineering log: every measurement, dead end, and trap — including three self-inflicted regressions and what caught them. If you are changing this plugin, read it first; it will save you the same afternoons.
Two harnesses live in the sibling tools/ directory of the origin workspace:
health.mjs— do the selectors this plugin depends on still exist? (assumptions)regress.mjs— do the features still work? (behaviour, in WebKit, since Chromium and iOS Safari do not measure text identically)
Both exit non-zero on failure.
License
MIT
No comments yet. Be the first to write one.