deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
English | 中文
Which project, which branch, how much has moved — at a glance. This plugin puts the current conversation's project name and its git state in the conversation header of the DeepSeek Harness web GUI's Work window, just left of the Session log export button:
omdsh-plugins ⎇ main ↑1 +2 ~3 ?1 export
The project name is the title of the workspace the conversation lives in (the group heading you already read in the sidebar). Beside it: the checked-out branch, and whichever of ahead/behind, staged, modified, untracked, and conflicts are non-zero. A clean tree shows the branch alone; conflicts are the one count drawn in the alarm colour, because a row where every glyph shouts says nothing. The tooltip carries the full directory, every count in words, and why the figures are stale when a refresh failed.
A conversation that has not started yet has no header at all — the harness hides it — so the same readout holds that row's own corner from the frame's floating layer, on the same pixels, and hands them back the moment the header returns:
demo-project ⎇ main ~1 ?1 ✦ Files Terminal
Into the Unknown
📁 demo-project ⌄ ⚙ Standard mode ⌄
┌──────────────────────────────────────────────┐
│ Describe what you want to build │
| Surface | Where it comes from |
|---|---|
| The readout left of the Session log button in the conversation header | conversation.session.header.utilities, ui-conversation's trailing row — order: -1 keeps it left of the harness's default-order utilities |
| The same readout holding that row's corner on a new session | shell.overlay, ui-layout's frame-wide floating layer — the stand-in, for the conversations whose header the harness is not drawing |
GET /omdsh-status/status |
webServer, behind the same browser-trust fence as the /api gateway |
There is no settings namespace. Nothing here needs a person's decision — the project name is the workspace's own title, the git counts are the working directory's own state, and the poll cadence is fixed.
Each half reads from whoever already knows:
.git, so the host half
resolves the session's working directory and runs
git --no-optional-locks -C <dir> status --porcelain=v1 --branch, then
answers with the parsed counts as JSON. No path list, no diff, no branch
graph ever reaches the browser — only the handful of numbers it draws —
and the route sits behind the same trust check as /api.omdsh-sidepanel's switches hold its outer end and omdsh-sidechat's summon
icon tucks in beside them; this readout is the utility row's leftmost entry,
so its stand-in measures the occupant that has already tucked itself furthest
IN and goes inboard of that. The neighbour measures the opposite end, so the
dependency runs one way and the row settles in a single pass. Only boxes are
read — never another plugin's code, state, or identity — and an empty corner
is measured as empty: the readout takes the header's own padding.@omdsh-plugins/omdsh-base with @omdsh-plugins/omdsh-chatmode), a
conversation it classifies as a chat gets no readout and no poll: its
workspace is the managed one under the harness's own home, which is a
directory the harness keeps rather than one anybody chose. The rule is read
from sessionModes rather than re-derived, so the readout and the mode
switch cannot disagree.The poll is kept cheap: one directory's git answer is shared across every open page for two seconds, a visible page re-asks every four seconds, background tabs ask nothing, and cold sessions resolve their directory through the cached persistence listing.
sessionModes is
read on a restricted fiber and never injected, so its absence costs this
behaviour and nothing else.npx @omdsh-plugins/omdsh-plughub add omdsh-status
That is the plugin hub's
installer with argv where the button was. It resolves this plugin from the
collection's registry, installs it
from its GitHub repository, and writes the pnpm build-allowlist entry a bare
dsh plugin add github:… would leave to you — the entry carries the commit pnpm
resolved, so it can be copied out of a failure and never written down in
advance.
dsh plugin --profile web add @omdsh-plugins/omdsh-status is not that command yet:
this package is not on npm, and pnpm answers ERR_PNPM_FETCH_404. The same
install is also a button, on this plugin's card in Settings → Plugins → Plugin
hub, once the hub itself is in the profile.
Or from a checkout — the form an unpublished build needs:
pnpm install && pnpm run build
dsh plugin --profile web add "$PWD"
Remove it the same way:
dsh plugin --profile web remove @omdsh-plugins/omdsh-status
Nothing here is a precondition. Every service either half injects —
webServer, webRuntime, sessions on the host; slots, sessions,
workspaces, locale on the page — is a harness service, and both seats
register through slots.inject. The one companion service it reads,
sessionModes, is reached on a restricted fiber inside apply, so a profile
without a mode system boots normally and simply hides nothing. A profile with
only this plugin installed starts and works: without a git repository it shows
the project name alone, and without a conversation it shows nothing. Removing
it takes the readout, the route, and the poll with it — the harness itself is
untouched.
pnpm install
pnpm run build # tsdown bundles the host and browser halves
pnpm run typecheck
pnpm run test
pnpm run harness:local <path-to-harness-checkout> # while developing against a checkout
pnpm run harness:npm # back to the registry pin before committing
pnpm run check:harness-pin # fails while any harness dep is still linked
The pure logic (porcelain parsing, project derivation, the chat gate, polling
rules, route behaviour, and the corner arithmetic the stand-in places itself
by) tests under plain node; the browser-side slot registration cannot run
against a published harness pin because published packages ship no sources —
that half is exercised under harness:local.
tests/git.run.spec.ts is the one spec that spawns git, in a throwaway
repository it creates itself. It earns the milliseconds: a parser spec cannot
ask whether git accepts the command being run, and the released argv put
--no-optional-locks — an option of git, not of git status — after the
subcommand, so every read exited 129 and every repository read as "no git".
git status that outlives its timeout all
read as "not a git repository" — the tooltip does not distinguish them.CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。