New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

dsh-kanban

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dsh-kanban

Smoothly Kanban (思磨力看板): external DeepSeek Harness plugin — a cross-session, workspace-scoped kanban board for plans and todos, persisted to a git-trackable KANBAN.json. Model-facing tools (board_list/board_add/board_update/board_remove) plus a sidebar '思

latest
Source
npmnpm
Version
0.2.10
Version published
Weekly downloads
163
-41.79%
Maintainers
1
Weekly downloads
 
Created
Source

Smoothly Kanban

English | 简体中文

license MIT

Smoothly Kanban(思磨力看板)is an external DeepSeek Harness plugin: a cross-session, cross-branch, persistent plan / todo kanban board.

When you chat with an agent (in dsh, Codex, Claude Code, …) you produce lots of plans and todos — and the pain is that once you switch to another branch or open a new session, those plans and todos become invisible: they still live in the long conversation, but you can't find them or remember them.

dsh-kanban sinks plans and todos into a KANBAN.json file at the workspace root (git-trackable, human-editable, survives sessions) and gives you two ways to maintain it:

  • Model entry: 4 model-facing tools (board_list / board_add / board_update / board_remove) so the model records plan steps and todos while talking.
  • Web entry: a 「思磨力看板」 entry in the dsh Web GUI sidebar's global panels section that renders a three-column board page (To do / In progress / Done) in the centre column, with view, status move (incl. mark done), add, and delete.

The same KANBAN.json is shared by the model tools and the Web page, so what the model writes, the page shows; what you check off on the page, the model reads next time.

What it adds

Proactive model maintenance (host half, the core)

A system-prompt guidance section tells the model to actually use the board on its own — record plans/todos as they appear, move cards as work progresses, without waiting to be asked:

  • When the user states a multi-step plan or task list → the model board_adds one card per step;
  • As work progresses → the model board_updates cards to in_progress / done;
  • Switching branches or opening a new session → the model board_lists first to pick up the durable record;
  • Division of labor vs todo_write: todo_write is the transient in-turn task list; the board is the durable cross-session record — anything the user should still see after switching branches belongs on the board.

Verified with a real model (user only said "build a Markdown-to-HTML tool and make a plan", no mention of the board): the model proactively board_list'd, board_add'd all 7 plan steps, then board_update'd each to done as it went.

How it works & transparency

What makes the model "proactively" use the board? Two mechanisms, both in dsh's system prompt and visible to the user:

  • Board usage guidance (ctx.systemPrompt.section): a fixed guidance section telling the model what the board is, when to record, and how it differs from todo_write. Updated with plugin releases.
  • Session-start auto-injection (ctx.systemPrompt.context): on every prompt assembly, the plugin reads the current session's workspace KANBAN.json and injects an "open items" summary (todo + in_progress) into the model's context — so the model sees the board immediately, without having to remember to board_list. With no session / no cwd / an empty board it contributes nothing.

Trade-offs of the auto-injection (stated openly):

AspectNotes
✅ ProThe model always sees the current workspace's open items — no "remember to check"; cross-session continuity is guaranteed by the system, not the model's diligence
⚠️ Cost 1Every request carries the board summary, adding fixed token overhead (grows with the board)
⚠️ Cost 2Board changes alter the request prefix, which can affect KV-cache reuse. To limit this, only open items are injected (todo + in_progress) — done cards churn would worsen prefix instability
⚠️ Trade-off"System pushes" vs "model queries" — injection guarantees visibility at the price of per-request overhead

The full "make the model use it" mechanism:

  • Board usage guidance (ctx.systemPrompt.section): what the board is, when to record, how it differs from todo_write, and the card-completeness contract — every card needs a rationale (why at creation); a done card must carry all three what/why/rejected fields.
  • Session-start auto-injection (ctx.systemPrompt.context): open items are pushed into the model's context (see above); cards missing fields are flagged (缺:…) so the model fills them when it picks the work up.
  • Wrap-up discipline: the guidance requires that at the end of every work session the model moves completed cards to done, adds follow-ups as todos, updates summaries, and never leaves stale in_progress cards — the board stays an honest cross-session hand-off.
  • User-side visibility: the sidebar's global-panels 「思磨力看板」 entry carries an open-item count badge on its glyph (backed by the /kanban/counts route; the workspace follows the current session, then the most recent one, and the badge subscribes to workspace-list changes so it appears as soon as data is ready); the board panel auto-refreshes every 15s while shown, so model/other-session writes appear without a manual refresh.

Data-safety commitment: the plugin only writes board/note files (plus, on a shell with no skill registry, the ~/.agents/skills/kanban-use/SKILL.md copy described below); there is no startup, scheduled, or install-time cleanup. Cards are removed only by an explicit board_remove / the Web delete button (which requires a confirmation Modal — no accidental one-click loss); excess done cards (beyond 100, oldest first) are archived (moved to .agents/notes/archive.json), never deleted. All board data lives inside your workspace directory (git-trackable, hand-editable).

Model tools

ToolPurpose
board_listRead the current workspace board (all cards with status, tags, timestamps). Call it before any update to get real ids.
board_addAdd a card (title + rationale/why expected on every card — a title-only card is incomplete and flagged 缺; rejected/gave-up when a decision was made; summary/what filled at completion; optional description, status, tags).
board_updateUpdate a card by id (status / title / summary / rationale / rejected / description / tags).
board_removeRemove a card by id.
note_addWrite an Agent Note (full replication of the DSH repo discipline) to .agents/notes/implemented/<class>/<date>-<topic>.md.
note_listList existing Agent Notes in the current workspace.

The board is scoped to the current session's working directory (cwd): every session under the same project directory shares one KANBAN.json — that's what makes it survive across sessions and branches.

Editable Agent Note spec (reuse, not re-invention; synced via overrides)

note_add's output format, classes, and "non-trivial change" definition are replicated from the deepseek-harness repo (no re-inventing the wheel):

ItemUpstream source
Note classesscripts/agent-note-tree.ts → AGENT_NOTE_CLASSES
Note formatscripts/verify-agent-note-format.ts
Non-trivial definition.agents/notes/README.md → "When to write one" (root AGENTS.md only points at it)
  • Plugin ships defaults (updated per release): src/note-spec.ts fixes the default classes, format template, and definition — works out of the box;
  • User overrides: the Web board page's Agent Note spec section has three inputs to paste newer upstream content over the defaults; overrides are stored at the workspace's .agents/notes/overrides.json;
  • Source hints: each input states which dsh source file to copy from;
  • Update warning: when the plugin ships a newer spec version than a workspace with custom overrides, the page warns that updating the plugin resets overrides to the new defaults (custom content is lost). "Save overrides" acknowledges the current version; "Reset to defaults" clears them.

Why not import dsh directly: verify-agent-note-format.ts is a dsh repo internal script — not published, not installable, unreachable from an external plugin. The spec is fixed as constants and synced via "input-box overrides + plugin releases".

Sync mechanism (dev-time check + releases)

  • Source anchor: src/note-spec.ts states it is replicated from deepseek-harness (upstream commit ddefc45fbc7f8e46dd73185e68295696d1297887);
  • Dev-time check: pnpm check:spec (scripts/check-note-spec.mjs) reads the local dsh checkout's spec constants (classes from agent-note-tree.ts, format from verify-agent-note-format.ts, note-scope rule from .agents/notes/README.md + the AGENTS.md pointer to it) and diffs them against the plugin defaults — when upstream changes, one run reports the difference and tells you to update src/note-spec.ts and bump NOTE_SPEC_VERSION;
  • Release sync: the author updates the defaults and ships a new version; dsh plugin update dsh-kanban delivers the new defaults (if the user had custom overrides, the update warning explains they get reset).

check:spec needs the local dsh source path — it is a dev-time tool (not shipped, not part of the user-facing test chain).

/kanban command

/kanban shows the current workspace board; /kanban done <card-id> marks a card done quickly.

Web board page (client half)

The three-column board page (To do / In progress / Done)

  • A 「思磨力看板」 entry in the sidebar's global panels section (sidebar.panellist) with an open-item count badge on the glyph (number when there are todo/in_progress cards, "99+" cap);
  • The board is the main slot's occupant for that panel id: selecting the entry renders it in the centre column (the Conversation steps aside, exactly like the built-in Plugins page), and 「返回会话」/“Back to conversation” returns;
  • A three-column board: To do / In progress / Done, each column with a card count;
  • Workspace switcher: switch between any registered workspace at the top (each workspace owns its KANBAN.json); defaults to the current session's workspace;
  • Per card: a status dropdown (including "done"), and delete with a confirmation Modal (no accidental one-click loss); cards show the what/why/rejected fields the model filled, and model-created cards carry an "Open source session" button (jump to the handling session);
  • Two-line clamped previews: each of the three what/why/rejected fields on a card shows at most two lines, with an ellipsis (...) for the rest — cards stay compact and scannable;
  • Detail dialog: clicking the card's title + what/why/rejected region (including the description) opens a detail Modal where the full content is laid out in labeled sections (icon + label + newline-preserving body), plus status, tags, source session and created/updated times — a comfortable reading view;
  • An add form at the bottom: title + the three what/why/rejected inputs laid out in one row of three columns;
  • Silent auto-refresh: while open, the page polls every 15s and diffs by a content signature — when nothing changed it leaves the card DOM completely untouched, so it never interrupts reading or drops the scroll position; the header shows "auto-refreshed at HH:mm:ss" so the poll's liveness is visible; a failed poll keeps the current view (no error flash);
  • The page reads/writes the same KANBAN.json through the host-registered /kanban/api and /kanban/counts webServer routes (GET read, POST add/update/remove) — independent of built-in dsh RPC, so official upgrades don't touch it.

Data file

<workspace root>/KANBAN.json
{
  "version": 1,
  "cards": [
    { "id": "card-xxxx", "title": "implement kanban tools", "description": "…", "status": "todo", "tags": ["dsh"], "createdAt": 1234567890, "updatedAt": 1234567890 }
  ]
}

The file shape is validated: a missing file reads as an empty board; a structurally broken file fails loud instead of being silently repaired (so a hand edit gone wrong never loses data quietly).

Install

Prereq: a DeepSeek Harness with the dsh CLI, plus pnpm. This is an installable bundle — loaded by dsh, not imported as a library.

From a local dev checkout

dsh plugin --profile web add /home/karoc/dsh-kanban

From npm (after publishing)

dsh plugin --profile web add dsh-kanban

From git

dsh plugin --profile web add github:karoc/dsh-kanban#<sha>

Git installs run the package prepare script to build the bundle; pnpm ≥ 10 asks you to allowlist the build once in the profile's pnpm-workspace.yaml (allowBuilds), then re-run add.

You must restart dsh web after installing for both the host tools and the Web page to load.

Update / remove

dsh plugin --profile web update dsh-kanban
dsh plugin --profile web remove dsh-kanban   # removes dependency + bundle layer; entry disappears after restart

Usage

  • Install, restart dsh web; the sidebar's global panels section shows the 「思磨力看板」 entry.
  • Ask the model to record plan steps with board_add (e.g. "put xxx on the board"); it writes the current workspace's KANBAN.json.
  • Open 「思磨力看板」 anytime for the three-column view; mark done / move / add / delete directly on the page.
  • After switching branches or opening new sessions the board is still there — it's just a file in the workspace.

Card completeness & the kanban-use skill

Cards are the board's cross-session memory: the next session reads them without asking you. The plugin therefore enforces a completeness contract on every surface the model sees (same rule everywhere, missingCardFields in board-core.ts):

  • Every card needs rationale (为什么) — why it exists and why now. A title-only card is incomplete and is flagged:
    • in tool outputs (⚠️缺:… after the card line, plus a summary line when any card is incomplete),
    • in the session-start snapshot ((缺:…) on open items, so a resuming session can fill them),
    • on the Web board page (a warning line under the card fields — missing: … in the English UI, 缺字段:… in Chinese — humans see it too).
  • A done card must be self-explanatory: summary (做了什么) + rationale + rejected (放弃了什么) all present, so the completed work is an honest hand-off.

The kanban-use skill (skills/kanban-use/SKILL.md) is the deep manual for this discipline — field semantics, good/bad card examples, the create → advance → close flow, a close checklist, and templates. The system-prompt guidance points the model at it. Delivery has two paths, and neither asks the user for an extra step. Preferred (DSH ≥ 0.1.6, i.e. ctx.skills exists): the host half registers the packaged skills/kanban-use/SKILL.md straight into the shell's skill registry (ctx.skills.register, source: 'runtime'), so the skill version IS the plugin version — there is no stale copy, and a frontmatter DSH cannot parse cannot silently hide it; by DSH's precedence (project > runtime > user) a copy in ~/.agents/skills cannot shadow it, while a project-level .agents/skills (or .dsh/skills) copy still wins — the documented way to customize. Fallback (an older shell, or a profile without the skill service): copy install — the skill ships inside the npm package (the tarball includes skills/kanban-use/SKILL.md and scripts/install-skill.mjs) and the host half checks ~/.agents/skills/kanban-use/SKILL.md on every dsh web start. A skill-version fingerprint in the skill's frontmatter (bumped on content changes) drives that copy policy: missing → copies the shipped file in; identical → no-op; same or newer version but different content → your local copy is kept (that is your own edit of the current version) with a hint; older version (or a copy with no fingerprint) → synced over (that is stale package content from a previous install, the upgrade path). So dsh plugin add/update dsh-kanban + the required restart is all it takes, on any machine. The manual commands still exist for repo checkouts and forced syncs:

pnpm install:skill            # symlinks skills/kanban-use → ~/.agents/skills/kanban-use
node scripts/install-skill.mjs --copy   # materialize/overwrite a copy (works inside the installed package too)

The skill is maintained in this repository alongside the plugin — the release/dev gates (pnpm check:cards → scripts/check-card-discipline.mjs) assert that the skill's field semantics and tool names stay consistent with the plugin's schema, and scripts/audit-cards.mjs <workspace> [--fail] reports incomplete cards in any workspace's KANBAN.json.

Directory layout

cordis.patch.yml        # bundle layer: mounts this package (host tools + client half)
package.json            # dsh.bundle (patch) + dsh.client (web) + exports["./client"]
tsdown.config.ts        # self-contained build: node half + module-table client bundle
src/board-core.ts       # KANBAN.json domain: read/write, validation, card CRUD,
                        #   missingCardFields completeness rule (shared)
src/index.ts            # host half: 4 model tools + /kanban/api webServer route
src/client/index.ts     # client apply: global panel (sidebar glyph + 'main' occupant)
src/client/BoardPage.tsx       # three-column board component (+ missing-field hints)
src/client/KanbanSurface.tsx   # panel glyph + the 'main' panel wrapper
src/client/workspace-pick.ts   # current-session + most-recently-active workspace derivations (pure, unit-tested)
src/client/board-counts.ts     # /kanban/counts poll behind the glyph badge
src/client/locales.ts          # zh/en copy
src/client/styles.ts           # --dsw-alias-* design-token styles
src/skill-register.ts          # host half: kanban-use served through ctx.skills (DSH ≥ 0.1.6)
src/skill-sync.ts              # host half: copy fallback for shells without the skill service
skills/kanban-use/SKILL.md     # the kanban-use skill (ships in the npm tarball)
scripts/check-card-discipline.mjs # dev gate: guidance/schema/skill agree on completeness
scripts/check-tokens.mjs         # dev gate: every --dsw-alias-* token exists in the installed DSH theme
scripts/check-client-wiring.mjs  # dev gate: panel id/key wiring survived the edit
scripts/audit-cards.mjs          # KANBAN.json completeness audit ([workspace] [--fail])
scripts/install-skill.mjs        # symlink/copy the skill into ~/.agents/skills (shipped too)
scripts/verify-skill-sync.mjs    # copy-fallback three-state verification (part of pnpm test)
scripts/verify-skill-runtime.mjs # runtime skill registration vs a real registry (part of pnpm test)
docs/screenshots/board-page.png  # Web board page screenshot (README figure)

Why an external plugin

dsh's official updates only touch the bundled in-repo packages. An external bundle is installed into the user profile via dsh plugin and is never touched by official upgrades (same pattern as dsh-model-reasoning). The plugin only uses dsh's externally stable capability surface: tool registration (ctx.tools), webServer route registration, system-prompt guidance (ctx.systemPrompt.section / .context), the command registry (ctx.commands), the skill registry (ctx.skills), and the Web global-panel slots (sidebar.panellist + main).

Known limitations (v1)

  • dsh only: aggregating Codex / Claude Code todos is future work (the KANBAN.json file is plain, so any tool can read it later).
  • No auto-extraction: model-driven writes plus manual page maintenance keep the data clean and controllable.
  • One board per workspace: a flat card list; plans are expressed via tags or card groups (no multi-board / nested columns).
  • JSON first: machine-friendly and diff-friendly; a KANBAN.md render view can come later.

Development

pnpm install   # build deps (tsdown, react)
pnpm bundle    # emits lib/index.js + lib/client.js
  • src/client/ is the browser plugin; the client bundle keeps @deepseek-ai/* + react external (resolved from the loader module table at runtime) and inlines everything else.
  • UI uses --dsw-alias-* design tokens, namespaced with the kb- prefix; pnpm check:tokens fails on any token the installed DSH theme does not define (an unknown custom property renders as nothing, silently).
  • The board is a DSH global panel: sidebar.panellist draws the sidebar row, the keyed main slot hosts the page. pnpm check:wiring pins that wiring; the live-GUI scripts verify it in a browser.

Verification

pnpm test       # tsc --noEmit typecheck + 20 KANBAN.json domain unit tests
                #   + 13 workspace-pick/current-session derivation tests
                #   + token-drift gate (with negative control) + panel-wiring gate
                #   + host tool smoke + skill runtime registration vs a real registry
pnpm typecheck  # typecheck only (tsc --noEmit)
pnpm verify     # 4 board tools registered + board_add persisted end-to-end
pnpm accept     # GUI acceptance against a running dsh web (http://127.0.0.1:3080):
                #   sidebar global-panel row → board rendered in the centre column
                #   (opaque, row marked selected) → add / move / delete
node scripts/capture-board-page.mjs  # refresh the README figure from the live GUI
                #   (captures the board panel only — never the session sidebar)

Since DSH 0.1.2-alpha.2 the Web GUI protects its index with a browser-session cookie ("dsh web authentication required"); the live-GUI scripts authenticate themselves through the /?token= handshake. Point them at the token dsh web printed on launch via DSH_WEB_TOKEN, or pass the full launch URL (including ?token=...) as DSH_GUI_URL; on instances where auth is off they run unchanged.

Since DSH 0.1.3-alpha.1 the composer input is a contenteditable div (0.1.2 used <textarea>); the live-GUI scripts match both (textarea, [contenteditable="true"]), so the same scripts run against either version.

External plugins get no compile-time typechecking by default (tsdown only transpiles); tsc --noEmit in pnpm test catches "used-but-not-imported" mistakes that would otherwise crash at runtime (a missing IconCheckOutline16 import once took down the whole board page).

Since DSH 0.1.6-alpha.2 the client SessionListState no longer carries current; the board derives the current session from main-view retention (retainedBy.mainView), the same predicate the shell's own sidebar, session binding, and Settings use — and still reads current when an older shell provides it.

Since DSH 0.1.7-alpha.1 icons carry their stroke weight in the name (*Regular = 1 px, *Medium = 1.3 px) and the size-suffixed names are gone; the board imports the *Regular variants, with every rendered size unchanged (the artwork defaults still carry the old sizes). The client half therefore requires DSH ≥ 0.1.7 since 0.2.9 — 0.2.8 is the release for 0.1.2–0.1.6. That floor is also declared, since 0.2.10, as an optional @deepseek-ai/dsh-client-ui-slots peer dependency, range >=0.1.7-rc.1 (the prerelease floor is load-bearing: a plain >=0.1.7 does not match a 0.1.7-rc.N runtime). The peer gate itself shipped with DSH 0.1.7-rc.1: from there on the loader evaluates every @deepseek-ai/dsh* peer against the running runtime and skips an incompatible bundle with the exact dsh plugin allow-version remedy (dsh plugin add refuses it outright) — so a future plugin floor is enforced up front instead of failing later at render time. Runtimes older than the gate — everything up to and including 0.1.7-alpha.2, hence all of 0.1.2–0.1.6 — do not evaluate peers at all: there the plugin still loads and the client half is what breaks on render, which is why 0.2.8 remains the release for those.

scripts/verify-model-board.mjs additionally verifies a real model call: it sends the GUI agent an instruction to use board_add/board_list, then confirms the card lands in KANBAN.json at the session cwd and is visible on the board page (the model-writes ↔ Web-sees round trip).

License

MIT

Keywords

deepseek-harness

FAQs

Package last updated on 26 Sep 2026

Related posts