DSH sidebar rendering order is determined by the browser-local sorting table and defaults to sorting by activity. This means that even if the host side changes session order, the change is usually not visible in the UI. The dsh-pin-session plugin uses a “host stores facts + client sorts” architecture to let users pin important conversations to the top of a sidebar group.
Core mechanism¶
The plugin does not depend on a complex runtime environment. The host side only stores the fact “which sessions are pinned” (using atomic JSON writes and HTTP endpoints inside the trust fence), while the client side performs sorting at the DOM layer.
Because sidebar session rows do not have a session id attribute, the plugin reads the React fiber (__reactFiber$...) and traverses upward to find memoizedProps.node.id to obtain the identifier precisely; if this cannot be retrieved, it falls back to reverse lookup by title (only when the title is unique).
- Zero runtime dependency: host side only uses
node:fs/node:path; client side only usesrequire("react"). - Failures do not affect DSH: if any step fails, only the plugin’s own effect is lost; the sidebar itself is not affected.
Installation & prerequisites¶
Before installing, ensure the following:
1. pnpm is on the PATH (the one bundled with DSH is fine).
2. DSH core version is 0.1.5-rc.1.
# 从 GitHub 安装
dsh plugin --profile web add github:BPTumbleweed/dsh-pin-session
# 或从 npm 安装
dsh plugin --profile web add dsh-pin-session
After installation, host-side changes require restarting the service, and client-side changes require a hard page refresh (Ctrl+Shift+R).
Configuration¶
Profile Patch overrides¶
You can use a profile patch to adjust the storage path, endpoint prefix, limit, and breaker threshold.
- id: dsh-pin-session
config:
storeRoot: /path/to/pin-data # 默认 $DSH_HOME/dsh-pin-session
routePrefix: /dsh-pin # 接口与面板前缀
maxPins: 100 # 置顶上限
breakerThreshold: 5 # 同一能力连续失败几次后熔断
allowUnfenced: false # 栅栏不可用时是否放行(默认 false = fail-closed)
Browser-side switches¶
Set the following key-value pairs in browser localStorage to enable or disable the feature without restarting:
| Key | Value | Purpose |
|---|---|---|
dsh-pin:disable |
"1" |
Disables the entire client-side effect (including buttons and badge) |
dsh-pin:prefix |
"/dsh-pin" |
Changes the endpoint prefix (used when the host side changes routePrefix) |
Usage¶
1. Command line (CLI)¶
CLI tools directly read and write the same JSON data file, suitable for scenarios without a browser (such as SSH or scripts).
dsh-pin list # 列出置顶会话
dsh-pin pin <sessionId> # 置顶会话(可选传入 title)
dsh-pin unpin <sessionId> # 取消置顶
dsh-pin toggle <sessionId> # 切换置顶状态
dsh-pin move <sessionId> <top|bottom> # 移动到顶部或底部
dsh-pin clear # 清空置顶列表
dsh-pin path # 查看数据文件路径
2. HTTP API¶
The endpoints default to going through the DSH trust fence and default to fail-closed when the trust fence is required.
| Method | Path | Description |
|---|---|---|
| GET | /dsh-pin/api/list |
Get the pinned set (the data source for the client-side sorting engine) |
| GET | /dsh-pin/api/status |
Get self-check status (capabilities, counts, and recent errors) |
| POST | /dsh-pin/api/pin |
Pin a session |
| POST | /dsh-pin/api/unpin |
Unpin a session |
| POST | /dsh-pin/api/toggle |
Toggle pin status |
| POST | /dsh-pin/api/reorder |
Reorder |
| GET | /dsh-pin/panel |
Admin page (purely server-side rendered) |
3. UI operations¶
- Session header: A 📌 button appears in the session header, and clicking it pins or unpins.
- Sidebar session rows: Hover the mouse over a sidebar session row, and a 📌 button appears inline; clicking it moves that row to the top of its group.
Notes¶
- Only effective in the browser: Pinning is client-side DOM sorting and does not change the host-side session order. If you switch browsers or clear local state, the pinned set still exists (server-side), but the effect needs to be reapplied.
- Only pins within the same workspace group: A pinned row is moved to the top of “its own group.”
- No intervention in search mode: The order of search results is determined by the query, and the plugin does not modify the DOM in this case.
- No DOM manipulation while renaming: When the input box inside a session row has focus, the plugin skips that sorting cycle (moving nodes would cause the input to lose focus). It will catch up automatically after focus leaves.
- Title may be missing: A session pinned via CLI without a
titlemay show only the sessionId in the list. - DSH version dependency: Requires DSH core version
0.1.5-rc.1.
License¶
MIT © 2026 Kan Zheng