DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-codex-pin

j

dsh-codex-pin

Manifest valid★ 1

Codex-Style DSH Web Plugin for Pinning and Archiving Conversations (Pinning = Marking, Not Sorting; Host-Persistent; Zero Order Changes)

UI (client)hasBundlePatch

dsh-codex-pin

Codex-style session pinning for the DeepSeek Harness Web sidebar — a pin is a flag, not a position.

Pinning a session lifts it into a single Pinned section above the whole workspace list. Toggling a pin never calls workspace.insertSessionBefore, never writes the workspace view store's order, and never switches the sidebar's sort mode: the durable session order in ~/.dsh/storages/workspace.json is not touched. That promise is guarded by a static check in this repo (npm test), not just by documentation.

The Pinned section above the workspace groups

Independent community plugin. Not an official DeepSeek product, and not affiliated with OpenAI — “Codex-style” describes the interaction model it copies, not any official connection.

What you get

  • A pinned flag. Hover a session row and click the pin (📌). The session moves into 已置顶 / Pinned at the top of the sidebar, newest pin first.
  • The pinned row leaves its group, so nothing is duplicated: click the row in the section to open the session, click the pin control there to unpin, and the row is back where the list order says it belongs.
  • Host-durable state. The ordered list lives in the host settings namespace codex-pin (~/.dsh/settings.yaml), so it survives restarts and is shared by every browser whose settings transport reaches the host.
  • Honest degradation. A browser that cannot reach the namespace keeps its own localStorage list and the section header says 仅本浏览器 / This browser only. That fallback is a fail-safe, not a one-way lock: a failed host write is retried once, and even after the page has fallen back every later pin keeps probing the host, so the note clears itself at the first write that lands.
  • No model-visible effects. No session events, no tokens, no telemetry and no external network calls — the browser half reaches only same-origin host surfaces: the settings namespace, the row menu's workspaces.openSession / forkSession / archiveSession, and the session's own rename.

How it differs from the other pinning plugins

dsh-codex-pindsh-pindsh-session-pin
Pin levelsone: a Pinned section above all workspacestwo: in-workspace + global traytwo: workspace + session
Durable session ordernever written — no ordering API is called at allin-workspace pins go through workspace.insertSessionBefore and switch the sort mode to manual; the global tray is display-levelpinned sessions move to the front of their account
Pin statehost settings namespace codex-pin.pinned, localStorage fallbackhost order anchors + local recordshost settings, per-browser durable
Extrasdeliberately noneanchor-exact restore, sort-mode restore8 colours, boards, tags, saved views, /goto
Footprintone bundle entry; no HTTP routesclient-onlyhost + browser

Pick this one if you want pinning to be a purely visual, always-reversible annotation. Pick the others if you want pins to also drive ordering, colours or boards.

Requirements

  • DeepSeek Harness with the web profile (the plugin is platform: web).
  • Verified against dsh web 0.1.5-rc.1, and re-verified against 0.1.6-alpha.2 (that host rewrote the sidebar, so the browser half now probes host capability shapes instead of one build's API); the declared peer range is >=0.1.2-rc.1 <0.2.0 and other builds in it are untested (see Compatibility).
  • Node >=22.19.0 (only for building from source).
  • dsh plugin add prints a peer-dependency warning on every known DSH build — the ecosystem's peer declarations are optional overlays, so the warning is expected and harmless.

Install

# straight from GitHub — the path that works today
dsh plugin --profile web add github:jackovibe/dsh-codex-pin

# pin a release instead of tracking main (any tag works)
dsh plugin --profile web add github:jackovibe/dsh-codex-pin#v0.2.7

# from the tarball attached to a release (Releases → Assets)
dsh plugin --profile web add ./dsh-codex-pin-0.2.7.tgz

# from a checkout
npm run build && npm pack && dsh plugin --profile web add ./dsh-codex-pin-0.2.7.tgz

# from npm (once published)
dsh plugin --profile web add dsh-codex-pin

The github: spec is what this plugin's own development profile uses, so it is exercised on every local run; the npm name is reserved for a later publish and does not resolve yet.

Then restart dsh web (the loader composes bundle layers at boot) and hard-refresh the browser (Ctrl+Shift+R). Open the sidebar: session rows now carry the pin control on hover.

How it mounts

The package ships a bundle patch (cordis.patch.yml) that inserts exactly one loader entry:

- insert:
    - id: codex-pin
      name: dsh-codex-pin

dsh plugin add reconciles dsh.profile.bundles by itself, so do not also add this insert to your profile's own cordis.patch.yml: two layers inserting the same loader id fail the boot. Check the composition before restarting:

dsh --profile web --dump-config | grep -c 'id: codex-pin'   # must print 1

Upgrade / uninstall

# upgrade: re-run the same spec (adds the newest commit on main, then restart)
dsh plugin --profile web add github:jackovibe/dsh-codex-pin
# or move to a specific release
dsh plugin --profile web add github:jackovibe/dsh-codex-pin#v0.2.7

dsh plugin --profile web remove dsh-codex-pin       # uninstall, then restart

Session ids stay in settings.yaml under codex-pin after uninstalling; delete that block to clean up.

Usage

ActionHow
Pin / unpin a sessionhover the row, click the pin control (📌 toggles)
Open a pinned sessionclick its row in the 已置顶 / Pinned section
Unpin from the sectionclick the filled pin on the section row
Rename / fork / archive / delete / copy title or idright-click any session row for the row menu
Pin / rename / archive the current sessionCtrl+Alt+P / Alt+Ctrl+R / Ctrl+Shift+A

Pinned and unpinned rows carry the same pair of controls — the pin (outlined when unpinned, filled when pinned) and archive — and the rows inside the Pinned section carry them too, so archiving stays available while a session is pinned. The menu's red Delete session entry calls the archive manager's workspaceRegistry.deleteSession behind a confirmation dialog; without that plugin the entry reports why instead of failing silently.

Menu copy and tooltips follow the GUI language: the plugin registers zh/en dictionaries through ctx.inject(['locale']), so a Chinese GUI shows 重命名 / 置顶聊天 / 归档会话 / 删除会话 and an English GUI shows Rename / Pin chat / Archive session / Delete session — switching the language re-labels a running page with no reload.

Ctrl+Shift+A asks for confirmation before archiving the current session (a single global keystroke should not archive silently); the row menu's archive entry is a deliberate click and archives directly. Right-clicking a session row opens this plugin's menu — a Codex-style overlay. It only intercepts rows it can act on; a row without a session identity keeps whatever context menu it had. The app's own surfaces (multi-select, search, the settings pages) are untouched.

Configuration

KeyDefaultMeaning
maxPins0Cap on pinned sessions; 0 = unlimited. Set it on the loader entry:
# profile cordis.patch.yml
- id: codex-pin
  config:
    maxPins: 5

When the cap is reached, the oldest pin is dropped as a new one is added, and a lowered cap prunes the view on the next read. Changing the cap re-composes the host plugin: an already-open page picks the new value up when the host pushes it (observed to take tens of seconds, and writes in that window can race the re-registration) — so refresh the page after changing the cap. The browser-local fallback has no policy to read, so the cap applies to the host-backed list.

Where state lives

WhatWhere
Pinned ids (newest first)~/.dsh/settings.yaml → codex-pin.pinned
Browser-local fallbacklocalStorage key dsh.codex-pin.pinned
Session orderuntouched — ~/.dsh/storages/workspace.json is never written by this plugin

Compatibility

DSH WebStatus
0.1.5-rc.1verified (2026-09-16) — see Verification
0.1.2-rc.1 … 0.1.5-rc.2inside the declared peer range, not tested by hand
any 0.2.xnot claimed; the peer range stops at <0.2.0

Tested alongside @michengai/dsh-archive-manager, which takes over the sidebar slot (sidebar.workspaces, priority −0.5): the Pinned section still rendered above the tree with zero page errors. Sidebar-rewriting plugins are the most likely source of breakage, because this plugin finds rows by React fiber props (see Limits).

Verification

Static checks need nothing but Node:

npm run check   # lib/client.js is byte-identical to src/client-src.js
npm test        # invariants: no order API, one loader entry, live e2e selectors

The e2e suites drive a running dsh web GUI with Playwright's Chromium. Point them at your instance with DSH_E2E_URL (a full URL including ?token=…) or let them read the URL the launcher logged into ~/.dsh/dsh-web.log; DSH_E2E_CHROMIUM overrides the executable path (any chromium-* build in the ms-playwright cache is found automatically). They need playwright-core from the dev dependencies:

node e2e/pin-e2e.mjs 3080              # pin -> tray -> open -> unpin -> persist
node e2e/pin-e2e.mjs 3080 --leave-pinned
node e2e/state-check.mjs 3080          # read-only: what the section shows now

Result of the run recorded in verification/ (redacted: tokens, session/workspace ids and titles are stripped before the records are written) against dsh web 0.1.5-rc.1 on 2026-09-16 (Windows, 5 session rows, 2 workspace groups, plugin installed from the packed tarball). The e2e run asserts every row of this table and exits non-zero when one breaks:

CheckResult
Client bundle in the boot graph…,dsh-codex-pin/client.js,…; served after client-HMR re-hash
Pin controls injected on session rows4 of 5 rows — the provisional New Session row carries no row actions
Pinned section above the workspace listaboveTree: true
Pinned session leaves its grouphiddenRows: 1, back to 0 after unpin
Section row opens the pinned sessionthe click goes through sessions.open (single-page app: there is no URL change to assert)
Unpin restores the rowtray gone, hiddenRows: 0
DOM order unchanged by pinningidentical title sequence before and after
Stored on the hostsettings.yaml → codex-pin.pinned, id read out of the row's React fiber props
Host order untouchedworkspace.json sessionIds arrays identical before/after
Rendered from the host, not the browserfresh headless context, no local state: 已置顶 · 1, noteShown: false
Tray controls presentmarkers tray, tray-head, tray-row, tray-pin, tray-archive, wrap tray-ctl
maxPins: 1two pins leave only the newest, on write and on read; see verification/maxpins-check.md
Console / page errorsnone

Development

lib/index.js        host half: registers the codex-pin settings namespace
src/client-src.js   browser half (the authored source)
lib/client.js       served bundle — built by `npm run build`, checked by `npm run check`
e2e/                Playwright suites against a running dsh web (dev dependency)
test/               dependency-free invariant tests (`npm test`)
verification/       redacted results of the runs quoted above
shots/              e2e screenshots (local only — not shipped, they show real titles)

lib/client.js is a copy of src/client-src.js (the loader wants a classic script registering window.__ModuleLoader__.load), so edit src/ and run npm run build; CI fails if the two drift apart.

Limits

  • Row controls are found through React fiber props and the row's own action button. A DSH UI rewrite — or another plugin replacing the sidebar slot — can strand the per-row controls; the Pinned section keeps working.
  • Pinned ids are never pruned automatically: a deleted session's id stays in the stored list but stops rendering.
  • Pinned rows are hidden with display: none, which also removes them from their group's “show more” count.
  • Pinning is per session; pinned workspaces (the other half of Codex's model) are not implemented.
  • The row menu is a plugin-rendered overlay, not DSH's native context menu.

License

MIT — see LICENSE. The DOM layer is adapted from dsh-pin (MIT) and the host-backed store pattern from dsh-session-pin (Apache-2.0); see NOTICE.md and THIRD_PARTY_LICENSES.md.

Versions

Latest versionPublishedSize
0.2.6——

Comments

Loading…

Similar plugins

dsh-codex-pins

by robbywang25

Codex-style pinned sessions for DeepSeek Harness — always visible above the sidebar list

Development & InfrastructureSessions & MessagesManifest valid

★ 1

MIT

JavaScript

Sep 6, 2026

dsh plugin --profile web add dsh-codex-pins

by NattoCB

Adds a Workspaces / Recent-sessions switcher above the sidebar list, with a pinned-sessions group, a per-row menu (pin/unpin, copy session id), title filtering, and browser-local pin storage with a on

UI & ExperienceSessions & MessagesManifest valid

★ 1

MIT

JavaScript

Sep 10, 2026

dsh plugin --profile web add dsh-plugin-sidebar-views

by BPTumbleweed

DSH「置顶对话」插件:会话头部与会话行内一键 📌,把重要对话钉在侧栏分组顶部;宿主端只存事实(原子写 JSON + 信任栅栏内的 HTTP 接口),排序由客户端在 DOM 层完成。零运行时依赖、能力探测与熔断、面向跨版本升级设计。

Terminal & ClientsDevelopment & InfrastructureManifest valid

★ 0

MIT

JavaScript

Sep 16, 2026

dsh plugin --profile web add dsh-pin-session

by ice-ai-lab

Codex-style sidebar skin for the DeepSeek Harness Web GUI: a Projects + Recents browser, a New chat row that starts a session without picking a project and allocates its own working directory, and a d

Manifest valid

★ 0

MIT

JavaScript

Sep 12, 2026

dsh plugin --profile web add dsh-plugin-codex-ui

Adds Pin/Unpin to the sidebar session-row menu and a collapsible Pinned Sessions group above the session list, with host-side persistence, hover quick-unpin, collapse memory, and live running-state do

UI & ExperienceManifest valid

★ 0

dsh plugin --profile web add dsh-plugin-pin-session

Splits the DeepSeek Harness sidebar into independently scrollable Pinned and Recents panes, and hides pinned sessions from Recents.

Sessions & MessagesManifest valid

★ 0

dsh plugin --profile web add dsh-codex-pins