dsh-sidebar-buttons
English | 简体中文
A DeepSeek Harness plugin.
Takes over the buttons at the bottom of the left sidebar: drag to reorder them,
put each one into one of three display states, and give them all the same height.
Compatibility
Tested on DSH 0.2.0-rc.2 (web profile); also runs on 0.1.5-rc.1 and
0.1.2-rc.1. Those are the releases dsh.engines.dsh in package.json declares,
so a host or plugin manager can read the same range without parsing this file.
No peerDependencies are declared on @deepseek-ai/* on purpose: a prerelease
range there would exclude newer DSH releases and make the host's compatibility
gate skip the plugin.
Everything happens in the browser. The plugin works through the documented list
slot sidebar.footer.action (plus the shell's own settings.launcher seat for
the Settings entry) and never touches the DSH core or another plugin's files, so
uninstalling it restores the original sidebar.
Install
-
Add the plugin — from npm:
dsh plugin --profile web add dsh-sidebar-buttons
or straight from GitHub:
dsh plugin --profile web add github:lywusichen/dsh-sidebar-buttons
-
Restart DSH.
-
Open Settings → Sidebar Buttons.
What it does
- Lists every button currently registered in the sidebar foot. Drag a row to
change the order; the sidebar updates as you drop it.
- Each button has three display states:
- Show — pinned in the sidebar, as usual.
- Fold into More — moved into a "More" button above Settings. The More
button only exists while at least one entry is folded, and folded buttons
stay fully usable from its menu.
- Hide — gone from both the sidebar and the More menu. Only the settings
page can bring it back.
- Buttons from different plugins come in different sizes. Pick one height for
all of them, keep each button's own size, or type a custom pixel value.
Screenshots
More button position
More menu
Settings nav position
Settings page
How it works
The sidebar foot is a list slot, so a plugin can register more than one entry
under the same id and the renderer sorts them by priority. This plugin
re-registers each existing entry with priority: -1, which puts its copy in
front of the original, and renders its own wrapper around the original
component. Order, visibility, and size then come from a shared store that every
wrapper reads. Nothing is unregistered, so turning the plugin off returns
control to the originals immediately.
One kind of button does not fit that model: the slot entry is only an anchor and
the plugin renders the real button elsewhere in the sidebar (for example
dsh-mneme's memory entry, which mounts itself above the workspace list). Those
buttons are controlled in place, without moving any node: the wrapper is
hidden while the state has no visible seat, and when the entry is folded into the
More menu the popup carries a proxy row whose click is forwarded to the real
button. Moving the node instead would break twice — the owning plugin re-inserts
its wrapper from its own observer, and a node moved out of React's tree stops
receiving the synthetic events that make the button work.
The shell's Settings seat (settings.launcher) is managed the same way. It is a
single slot that cannot be mirrored, so it is hidden or folded in place, and it is
pinned after every managed button so it stays at the very bottom of the sidebar.
Known limitations
- Anchor-style buttons are found through a
data-plugin-entry marker or a
built-in declaration table (the memory entry and the Settings seat are both
declared). With neither, the plugin cannot tell the button apart and leaves it
alone.
- The Settings seat offers only Show and Fold into More: hiding it would
leave no way back into the settings panel, where this plugin's own page lives.
It also does not take part in drag-reordering.
- Reordering and the More menu depend on
slots.entries and slots.subscribe,
which the plugin relies on to stay aligned with registrations made after it
loads. If a future DSH release changes the list-slot contract, this plugin
needs an update.
- The three states are stored per button id. Two plugins registering the same id
share one state.
Build
npm install # esbuild
npm run build # generates lib/client.js
Commit lib/client.js. Git-hosted installs consume the built artifact directly.
License
MIT