DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Thumb — DeepSeek Harness 插件(DSH Plugin)
← Plugins
T

dsh-thumb

Thumb

DeepSeek Harness 网页 GUI 的手机端外壳:侧边栏变为叠加式抽屉,点击会话后关闭抽屉,设置页面切换为全屏单列布局。不使用宿主类哈希。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:AliceLJY/dsh-thumb#6bf08239fd227ec177f7d2d6c2eaafbdcdfe9abd
README兼容性版本

兼容性与来源证明

Thumb 以 dsh-thumb 发布,当前版本为 0.1.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/8/25

版本

0.1.0stable
2026/8/25

相关插件

正在加载相关插件…

最新版
0.1.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 0
周下载
0
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录

相关插件

继续浏览 ui-customization 分类下经过校验的插件。

Web App@deepseek-ai/dsh-web-appdsh 浏览器界面捆绑包:位于 dsh-base 之上的 Web 补丁层,加上运行时粘合插件(提供前端 dist、Web 界面提示符、bash 运行时变量和 URL 行)Experimental Agent Team Web Profile@deepseek-ai/dsh-experimental-agent-team-web-profile用于 Agent Teams Remote 和 UI 插件的实验性 Web 配置层Remote Web Ui@linxin666/dsh-remote-web-ui通过扫码配对访问 dsh Web GUI,共享一个官方界面:设置按钮旁的二维码可将手机和 PC 配对到同一个 Web GUI(手机采用竖屏触控适配层,PC 使用完整桌面界面),通过一次性令牌和 rClient Ui Git Graph@linxin666/dsh-client-ui-git-graph外部 dsh Web GUI 插件:空会话 Git 分支选择器和 Git 图,包含实际的主机端 Git 操作与防护,作为 dsh 配置文件包

README

dsh-thumb

A phone shell for the DeepSeek Harness (dsh) web GUI. The sidebar stops squeezing the chat and becomes an overlay drawer, tapping a session closes it, the settings sheet goes full-screen single column, and the transcript is retuned for a phone reading distance. Desktop is untouched.

中文说明

Personal tool, published as-is. Written for one person's phone and one dsh version (0.1.0-rc.6). No maintenance and no issue response are promised. If a dsh upgrade breaks it, the four entries in LOCATORS at the top of src/client.js are where to look — that is a minutes-long edit.

Why

On a phone, dsh's first screen is fine — the sidebar auto-collapses to a 56px icon rail and the composer fits. Everything breaks only after the sidebar is expanded, which happens to be the one path you must take to switch sessions.

Measured on an iPhone 14 Pro viewport (393×660), dsh 0.1.0-rc.6, before this plugin:

SituationBeforeAfter
Collapsed railfineuntouched
Sidebar expandedtakes 71% of the screen and squeezes chat to 113pxoverlays; chat keeps its full 393px
After tapping a sessionstays open, so you read in the 113px slotcloses itself
Dismissing itonly via the collapse buttontap anywhere on the scrim
Settings sheet800px two-column layout crammed into 393px; every English word wraps; value pickers fall off-screenfull-screen single column, text wraps normally, pickers on-screen
Clipped elements in settings71
Transcript height (3-turn session)610px — sized for a desktop reading distance490px, a fifth shorter

This is not a bug upstream — it is a stated contract. From the column solver in @deepseek-ai/dsh-client-ui-layout:

The sidebar never concedes: its rendered width is always the drag preference (or the collapsed rail), and center absorbs any remaining deficit as the last resort.

With SIDEBAR_DEFAULT = 280, a 393px viewport gives exactly 393 − 280 = 113. The concession chain shrinks the details panel, then closes it, and then the center column eats whatever is left. Reasonable in a narrow desktop window with a few hundred pixels to spare; not on a phone.

Install / remove / switch off

# install
dsh plugin --profile web add github:AliceLJY/dsh-thumb
# confirm "dsh-thumb" is in dsh.profile.bundles in ~/.dsh/profiles/web/package.json, then restart the service

# remove
dsh plugin --profile web remove dsh-thumb
# again, confirm it is gone from the bundles array, then restart

There is no npm package: dsh plugin add hands its arguments to pnpm, so a github: specifier installs the repository directly. Measured at 8.9s on a cold store, and dsh appends it to dsh.profile.bundles on its own.

Working on it locally instead? Point the same command at a path:

dsh plugin --profile web add link:/absolute/path/to/dsh-thumb

⚠️ Rolling back means undoing two things: package.json and the link in node_modules. Restore only the former and the next pnpm add sees the link still present, decides "Already up to date", and writes nothing while reporting success — it looks installed but isn't.

To switch off without restarting anything:

  • append ?thumb=0 to the URL, or
  • run localStorage.setItem('dsh-thumb','0') in the console and reload

How this differs from the similar plugins on GitHub

A dozen dsh mobile projects appeared around the same time, and the usual way to do this job is to hardcode dsh's class names in CSS (pI_x6G_sidebarCol, Md3f7G_scroll, and so on). Those are generated by CSS Modules at build time, so they all change on every dsh rebuild and the plugin dies silently — styles stop applying, the page still renders, nothing is logged. It just feels worse one day.

No host class name appears anywhere in this package. Instead the three columns are located once at runtime by their semantic suffix (sidebarCol — that half comes from the upstream source variable and survives hashing) and stamped with our own data-thumb attributes; every rule keys off those. If upstream renames something, one locator breaks in one place where you can find it, instead of styles failing quietly everywhere.

Behaviour goes through official interfaces too: closing the drawer calls ctx.layout.toggleSidebar() — the public ILayout method that ui-sidebar itself uses — rather than synthesising a click on some button.

Scope

The layout rules apply only when both conditions hold: viewport ≤1023px (matching upstream's SIDEBAR_AUTO_COLLAPSE = 1024, so there is only one breakpoint in play) and the sidebar has been manually expanded. The 56px rail is left entirely alone — it already works.

Is the drawer still worth it on a tablet?

An earlier version of this file guessed that it stops being worth it somewhere around tablet widths, and suggested dropping the breakpoint to 767px. Measured, that guess was wrong.

What matters is the state you are left in after tapping a session, since that is the path you have to take to switch sessions. Stock leaves the sidebar open, so the transcript stays at width − 280. The shell closes it, leaving the 56px rail and width − 56:

viewportstockwith the shellgain
393px113px337px+198%
480px200px424px+112%
604px324px548px+69%
768px488px712px+46%
900px620px844px+36%
1023px743px967px+30%

Regenerate that table with node test/measure-widths.mjs; the file also explains why it measures the width you are left with rather than the width the drawer covers, which is what the first attempt got wrong.

The gain shrinks with width, as expected — but it never inverts anywhere inside the supported range. Lowering the breakpoint would switch off something still worth 30–46% at the sizes it was supposed to help. The 1023px breakpoint stays.

The density rules are the one deliberate exception: they apply at ≤1023px with the drawer shut, because that is the state you read a transcript in. On the measured session that is 610px of column down to 490px — 60px of it from the gap between turns alone (16px → 10px), which costs nothing to interact with. Body text goes 16px/28px → 14px/21px and the action buttons 28px → 24px; the buttons were already under the 44px iOS touch target, so that last one is a trade, and --thumb-hit at the top of the stylesheet puts it back.

Desktop is verified unchanged: sidebar 280px, center 1160px, position: static, no scrim, settings still an 800px two-column sheet.

Known limitations

  • Hover tooltips can still overflow the right edge (the dark card when hovering a workspace row). Deliberately not fixed: its classes (_card / _copyable) are too generic to target safely, and doing it properly would mean scanning every position: fixed layer each frame and clamping them back into the viewport — an unclear blast radius for what is a cosmetic issue that blocks nothing. The right fix belongs upstream, in the tooltip's own touch handling.
  • Measured at 393, 480, 560, 604, 640, 700, 768, 900 and 1023px, plus desktop 1440×900 — see the table under Scope. Phone sizes are the ones used daily; the rest were measured once, not lived in.
  • The settings nav still stacks vertically instead of scrolling horizontally. The flex-direction: row rule lands on a wrapper that is not the one actually laying those items out, so it costs some vertical space at the top of the sheet. Left as is: the sheet went from unusable to usable, and chasing the exact nav container is polish, not repair.
  • The action rows under assistant replies keep their 28px while the ones under user messages shrink to 24px. They sit in a second flex wrapper and moved for none of height, align-self or min-height, and no rule naming those classes sets a height at all — so whatever sizes them needs a wider probe than a class-name scan. Left alone deliberately: it is 12px on a three-turn session, roughly 2% of the column.
  • A change to how upstream lays out its columns means updating this. The locators are the four entries in LOCATORS at the top of src/client.js — a minutes-long edit.

Verification

node test/smoke.mjs        # 21 assertions against a running dsh

The suite drives a real dsh instance at the phone viewport and again at 1440×900: locators stamped, the chat keeping full width behind the drawer, the four density numbers, containment, tablet width, the off switch, and a desktop regression pass that asserts body text is still 16px there. One assertion is end-to-end rather than a property check — it loads the same transcript twice, once with ?thumb=0, and requires the shell's version to be at least 15% shorter.

It has caught two real regressions so far, and both are worth knowing about.

The off switch, on the suite's first run. ?thumb=0 only ever disabled the React component, and until the density rules landed that was enough — every rule was gated on a drawer attribute only a live component sets. The density rules apply with the drawer shut, so the stylesheet became load-bearing on its own and the switch no longer reached it. ensureStyle and stampFrame now check it directly.

Containment, which the suite did not catch — it came back from a phone. The center pane mounts the trace view as well as the transcript, and the trace toolbar is made of text buttons. [class*="_actions"] > button sized every one of them to 24px square, collapsing Duration / Turns / Calls into an unreadable overlap. Every density rule now goes through FLOW, a scope that identifies the transcript column by the message items it holds rather than by a class name. The lesson was not the selector; it was that a suite which only ever opens one tab will keep passing while a neighbouring view is broken. Hence the containment assertion — and it was verified by reintroducing the bug and watching it fail, which it does, naming the three buttons.

Note for reproducing that one: the trace tab does not accept a Playwright click at phone width. Open it at desktop size and then shrink the viewport — same mounted view, narrow layout, no navigation in between.

Screenshots from the runs are not published — they show real workspace and session titles.

Three traps worth knowing before reproducing it:

  1. ESM ignores NODE_PATH — a globally installed playwright needs an absolute specifier, and it is CommonJS, so import the default.
  2. Chrome picks up the system proxy and ts.net addresses time out — use http://127.0.0.1:3080 with --no-proxy-server.
  3. waitUntil: 'networkidle' never fires — dsh holds a live connection open, so use domcontentloaded plus a fixed wait.

Development notes

Two traps, both of the "looks like it's somewhere else, is actually your own doing" kind:

Plugin never activates, whole page blank. dsh.client.inject in package.json and the inject exported from client.js look identical and mean different things: the first lists package names (module load order), the second lists cordis service names (['slots', 'layout']). Get the second wrong and the plugin stays pending, the shell reports web boot: 1 entry did not activate, and nothing renders at all. Copy what @deepseek-ai/dsh-client-ui-sidebar injects.

A drawer that can never be closed. The expanded check originally read the sidebar's rendered width (>56px means expanded) — and the drawer CSS is what pins that sidebar to 320px. The condition was contaminated by its own side effect, so it stayed true forever: collapse button, scrim and auto-close all appeared broken, and it looked like ctx.layout.toggleSidebar() was a no-op on narrow viewports (it was fine all along). It now reads the inline grid-template-columns that AppFrame writes on the frame — upstream's intent, which this plugin never touches. Rule: never derive a condition from a quantity you overwrite yourself.

License

MIT