DSH Plugins Marketplace

DSH Plugins

Plugins

/

Terminal & Clients

/

dsh-gitbar-lite

d

dsh-gitbar-lite

Manifest valid

A GitHub Desktop-style Git panel for DSH: changed files, tick-to-stage, Summary + Description, Commit and Commit and Push, discard-to-trash, and diff preview, in the built-in right sidebar.

UI (client)hasBundlePatch

dsh-gitbar-lite

给 DSH 用的 GitHub Desktop 风格 Git 面板——装在 DSH 自带的右侧栏里,和「文件 / 文档 / 聊天」并排。

变更文件列表、勾选提交、Summary + Description、Commit / Commit and Push、一个会随分支状态变化的 Push/Fetch 按钮、舍弃更改进插件自己的回收站、双击看 diff——都在这一栏里。

English: README.en.md

为什么是「右侧栏的一个 tab」

DSH 的右栏本来就是一个常驻的标签区。Git 面板放这里,意味着它和会话是同一份上下文:当前会话的工作区就是它看的仓库,切换会话就跟着切,不用再挑一次目录。

面板很窄(右栏最小 300px,窄视口下会自动全屏),所以它是按窄栏设计的:文件列表单列、路径按「文件名 + 目录」两级显示、提交框只留一个 Summary 输入框加一个可展开的小三角。

功能

功能说明
变更文件列表修改 / 新增 / 删除 / 重命名 / 未跟踪都能识别,每行带 +n −n 行数统计
勾选勾选就是真的 git add,取消就是 git restore --staged。终端里 git status 看到的就是同一件事
半暂存一个文件索引和工作区都有改动时,勾选框显示成「半选」,点一下把它整体重述为勾上或没勾
全选列表标题左边一个三态框:全选 / 取消全选,部分勾选时显示半选。冲突文件不参与,和自动勾选同一条规则
Summary / DescriptionSummary 常驻一行;最右边一个小三角展开 Description
Commit只提交勾上的(因为勾选写进了索引)
Commit and Push提交后立刻推送;推送失败不会说「提交失败」——提交已经发生了,面板会明说「已提交 xxx,但推送失败」
上下文按钮有本地未推送提交时是 Push,没有上游时是 Publish,否则是 Fetch
Push 前先 Fetch推送前会先 git fetch --prune,然后才推。已经落后就拒绝推并说明落后几个——git 的 push 从不合并,早晚都是被拒,先知道比推完再被拒有用。fetch 本身失败不阻断推送
自动 Fetch面板可见且仓库有远端时按 GitHub Desktop 的口径自己抓:默认 1 小时,每次到点重新判断,下一次从上一次完成后开始排,并加随机抖动防止多个面板同步。节奏是 autoFetchMs(0 关掉),并且用 FETCH_HEAD 的 mtime 判断"是不是刚抓过"——你在终端里抓也算
面板获得焦点每次重新看向面板都刷新一遍列表,并跑一遍脚本填 Summary:打开面板、切回这个标签、从对话点回面板、切回 DSH 窗口、浏览器标签回来,都算。手写的 Summary 不会被覆盖——只有空着的、或者还留着上次脚本填的那句话时才自动填
舍弃更改单个文件或「全部舍弃」;动手前先把这次改动的 diff 归档,确认框里可以勾「彻底删除」
回收站独立 tab。每次舍弃存一份 diff,并记下是对哪个提交(abc1234 初始提交)取的 diff
diff 预览双击文件,或点回收站里的一条,在右栏开一个 diff 标签页——永远只占一个,再点就复用
仓库绑定工作区本身是 Git 仓库就自动绑定并记住;不是就让你从工作区里扫出来的仓库里挑,或直接填路径

前置条件

需要什么说明
DSH >= 0.2.0-rc.2右侧栏 tab API 是这一版的行为
Node >= 22宿主半边用到 AbortSignal.any 与 node:test
本机有一个 git默认从 PATH 找;找不到时面板会明确说「本机找不到 git」,不会静默失败。装在别处可以用 gitPath 指定
凭据Push 用的是系统 git 的凭据(credential helper)。先在终端里成功 push 过一次,插件就跟着能推

插件不会自己存任何凭据。宿主半边不读 $DSH_HOME 里的密钥,也不写。

安装

dsh plugin --profile <你的 profile> add dsh-gitbar-lite

装完重启 DSH。然后在一个会话里打开右侧栏,引导页上会多一张 「Git 更改」 卡片,点它就进面板。

从本地克隆安装 / 卸载 / 装完打不开怎么办

本地目录安装(改代码时用这个):

dsh plugin --profile desktop add link:/绝对路径/dsh-gitbar-lite

卸载:

dsh plugin --profile <你的 profile> remove dsh-gitbar-lite

装完 DSH 起不来:先跑 node scripts/check-client-bundle.mjs .。DSH 把 exports["./client"] 当精确文件路径读,没有扩展名补全也没有目录回退;指向一个不存在的文件会直接 MissingClientBundleError 中止整个 Host 启动,而不是「这个插件不显示」。这个脚本就是复刻那条判定,让你不必靠重启去试。

使用

右栏引导页
┌──────────────────────────────────┐
│  ▸ Git 更改                      │  ← 引导卡片,点开面板
│    查看改动、勾选要提交的文件…    │
└──────────────────────────────────┘
        ↓ 点开
┌──────────────────────────────────┐
│ dsh-gitbar-lite  main   ↑1 ↓0    │  ← 仓库名 / 分支 / 领先落后
│              [Push] [↻] [🗄] [⑂]  │  ← 上下文按钮、刷新、回收站、换绑
│ 更改   5 个文件 · 已勾选 2  [全部舍弃] │
│ ☑ M  a.txt                  +3 −1 ↩│  ← 双击 = 看 diff;↩ = 舍弃这个文件
│ ▣ M  src/big.ts            +12 −4 ↩│  ← ▣ = 半暂存
│ ☐ ?  new note.md             +7   ↩│
│ ☐ D  docs/old.md             −31  ↩│
│ ☐ R  moved.txt                    ↩│
│ ┌────────────────────────────┐ ˅ │  ← ˅ 展开 Description
│ │ Summary(必填)             │   │
│ └────────────────────────────┘   │
│ [   Commit   ] [ Commit and Push ]│
└──────────────────────────────────┘
  • 勾选:点一下写进索引,再点一下撤出。半选状态点一下会整体勾上,再点整体撤出。

  • 双击文件行 → 右栏开 diff 标签页;再双击别的文件,复用同一个标签页。

  • 舍弃(行尾 ↩ 或「全部舍弃」)→ 弹确认框:

    舍弃「a.txt」的更改?
     · a.txt
     ☐ 彻底删除(不存入回收站)
       这次的 diff 会存进插件的回收站,之后还能回看是改了什么。
    [ 取消 ]  [ 舍弃 ]
    

    默认不勾「彻底删除」:这次改动的 diff 会存进回收站。勾上就什么都不留。这个勾选框会记住你上一次的选择。

  • 回收站(🗄):按时间列出记录,每条显示「多久之前 · 单个文件/全部更改 · 文件数 · +n −n · 基于 abc1234 初始提交」。 点一条看 diff,点 ↺ 把它恢复回工作区(恢复出来的文件回到列表时是勾上的),行尾的 🗑 删掉它, 右上「清空回收站」一次清掉(只清当前仓库,勾上「显示全部仓库」就清全部)。

  • 换绑(⑂):解除当前绑定。工作区是仓库会重新自动绑定;不是的话回到选择界面。

舍弃到底做了什么

顺序是固定的,不能换:

  1. 按当前改动生成 diff(已跟踪的文件走 git diff HEAD;未跟踪的新文件由插件自己合成一份 new-file diff, 因为 git diff HEAD 看不见它们,而舍弃未跟踪文件就是删掉它——不先合成,回收站里就只剩一条「删了一个文件」的空记录)。
  2. 存进回收站(除非勾了「彻底删除」)。
  3. 已跟踪的 git restore --source=HEAD --staged --worktree;未跟踪的直接删文件,并把因此变空的目录一起清掉。

冲突中的文件会被拒绝舍弃,只给一句提示。在合并中途 git restore 到 HEAD 有扰动合并状态的风险,不值得为省一句话去冒。

用脚本填 Summary

脚本就在面板里写:展开 Description 的小三角,下面有一个「填 Summary 的脚本」按钮,点开是一个编辑框——写进去、保存、运行并填入,全在这里,不用去翻配置文件。编辑框一开始是空的,什么都不会预先填进去(占位提示里给了一个例子);保存、运行、刷新都会给一条短暂提示,不用猜刚才那一下到底按到没有。每次重新看向面板都会自动跑一次(打开面板、切回这个标签、从对话点回面板、切回 DSH 窗口都算)——把侧边栏开着,去对话里让 agent 干活,回来,Summary 已经填好了;不过你自己手写过的 Summary 不会被冲掉,那时想更新就点星星按钮。配了脚本之后,Summary 框旁边还会多一个星星按钮,一点就填。

脚本以仓库根目录为工作目录运行,不喂任何 stdin。所以「取 CHANGELOG 最顶上的版本号」就是:

grep -m1 '^## ' CHANGELOG.md | sed 's/^## //'

输出即 Summary。要同时填 Description,就在输出里单独放一行 ---,该行之后的全部内容是 Description:

echo "1.4.2"
echo "---"
echo "Bumped the patch version."

关于 shell:Windows 上优先用 Git 自带的 sh(grep/sed/awk 都可用),并把它的 usr/bin 补回 PATH——否则那些工具会「command not found」。机器上没有 sh 才退回 cmd.exe,那时脚本要按 cmd 语法写。非 Windows 就是 sh。

脚本失败不弹错误横幅,退出码会以一条短暂提示显示;它的 stderr 原样保留,方便你自己判断。

脚本是按仓库存的(键是仓库路径,文件在 <DSH_HOME>/dsh-gitbar-lite/scripts.json):A 项目配的脚本不会跑到 B 项目里。一个从没配过脚本的仓库,编辑框是空的——不预先填任何脚本,占位提示只给个例子;清空保存之后它也真的空着。

配置

字段默认说明
gitPath""指定 git 可执行文件;空 = 从 PATH 找
stateDir""插件状态目录;空 = <DSH_HOME>/dsh-gitbar-lite
timeoutMs30000单条 git 命令超时。推到慢远端可以调大
maxDiffBytes524288一份归档 diff 的上限;超出按行截断并记下丢了多少行
maxFileBytes2097152比这大的未跟踪文件只列出来,不读内容、不归档、不出 diff
trashLimit200回收站保留多少条;超出丢弃最旧的连同它的 diff 文件
scanDepth3「不是仓库时」扫描工作区找仓库的目录深度
autoFetchMs300000面板自己多久 fetch 一次;0 = 关掉,只用手动按钮
summaryScript""填 Summary 的脚本。以仓库根为工作目录运行,输出即 Summary;单独一行 --- 之后算 Description

每个字段都是 volatile 的,所以在设置页改了立刻生效、不用重启。

状态存在哪:<DSH_HOME>/dsh-gitbar-lite/(没有 DSH_HOME 就回落 ~/.dsh)—— bindings.json(工作区 → 仓库)、prefs.json(那两个勾选偏好)、trash/index.json + trash/<id>.diff。 回收站只存那一个 diff,不额外留一份文件副本:恢复时用 git apply 把它重放回去, 那既是面板显示的记录,也是回放所需的全部内容;重放完再把这些路径 git add 进索引, 所以恢复出来的文件回到列表时是勾上的。都是先写临时文件再 rename,所以写到一半崩了也不会把文件截断。

工作原理

lib/shared.js          线协议字面量(浏览器半边手抄一份,自检脚本负责比对)
lib/index.js           插件入口:Config、apply、把路由挂到 connection.fetch
lib/host/git.js        git 执行层:走 ctx.subprocess,解析可执行文件、限流输出、清洗环境
lib/host/parse.js      porcelain v2 / numstat 解析(纯函数)
lib/host/diff.js       diff 合成、按行截断、按文件切分(纯函数)
lib/host/repo.js       仓库操作:status / stage / commit / push / fetch / fileDiff / discard
lib/host/store.js      绑定、偏好、回收站(原子写 + 按文件串行化)
lib/host/workspace.js  会话 → 工作区目录
lib/host/routes.js     单条 /api 路由 + action 分发 + 错误码映射
lib/client.js          浏览器半边:三个 tab 类型 + 面板/回收站/diff,手写、无构建

几个值得写下来的决定:

  • 一条 /api 路由 + action 字段,不是一条路由一个操作。connection.fetch 按精确 pathname 匹配, 而每次调用本来就要带 sessionId;分开写只会把十五个路径字面量摊到两种语言里。
  • 必须挂在 connection.fetch 上,绝不挂 webServer 的 exact 路由:web server 会先匹配 exact 路由, 而同路径的 exact 路由会遮蔽 /api 前缀路由——Host/Origin fence、浏览器 cookie 校验、operator 身份全在那条前缀路由上。 用 exact 就等于开了一个不需要鉴权的 git 接口。测试与自检脚本都专门盯这一条,并且反过来验证这条断言是有牙齿的。
  • diff tab 用 dsh-resource:// 固定地址,不是 page kind。重新打开同一个资源地址会让宿主聚焦已开的那个 tab, 并把新的 params 导航进去;page kind 只在当前 dock pane 内复用,被浮动出去就会多开一个。固定地址本身就是「永远只占一个」。
  • 不发 -m,用 -F - 把提交信息从 stdin 送进去:Summary 里有引号、有换行、以 - 开头,都只是文本,不是参数。
  • :(literal) pathspec:否则舍弃一个叫 docs 的文件会顺带动 docs/ 里的所有东西,a[1].txt 会被当成通配。
  • 不 import @deepseek-ai/dsh-client-ui-primitives:浏览器半边只 require('react')。 一个会抛错的 import 会把整个 slot entry 变成空白,而官方插件开发清单也要求客户端半边不导入 Harness Client 包。 需要的那几个控件手写,颜色全部走 --dsw-alias-* token;图标是逐 path 抄宿主 IconBranchOutlineRegular 等 artwork,所以它和旁边的宿主图标是一套东西。

更多细节(线协议全表、状态文件格式、为什么这么排序、哪些没验证)在 docs/CONTRACT.md。

验证

npm test          # 单测 + 真 git 的 e2e + 产物自检
npm run test:e2e  # 只跑真 git 的 e2e(23 个小节,各自造自己的夹具,294 项断言)
npm run check     # 只用产物自检(不启 DSH 也能发现会让 DSH 起不来的问题)
npm run test:live # 探测一个正在运行的 DSH(不在 npm test 里,需要跑着应用)
套件覆盖什么
test/parse.test.mjsporcelain v2 与 numstat 解析,含重命名、暂存删除、冲突、非 ASCII 路径、带空格的路径
test/diff.test.mjsdiff 合成(含无尾换行、二进制、CRLF)、按行截断不切断多字节字符、按文件切分
test/store.test.mjs绑定键归一、绑定/偏好/回收站往返、坏文件容错、并发写不丢更新
test/index.test.mjsConfig 字段与默认值、路由载体与「只注册一次」、错误码映射
test/client.test.mjs按 manifest 的确切路径加载真实 bundle;三个 tab 类型的 id/kind/guide/keepMounted;每个 slot key 都是注册过的 id;字典与错误码齐全;无 hook 的三个组件按渲染树断言
test/seats.test.mjs把每个注册进来的 seat 都渲染一遍,含隐藏态和无 session 态。这是补盲区的:client.test.mjs 从不渲染三个 body,而 body 渲染期抛错就是整个面板变白(真实发生过——一个 const 被依赖数组提前引用,ReferenceError 打白了面板,而其余测试全绿)
test/e2e.mjs真实 git、真实 handler、真实路由层:勾选真的写索引(之后读 git status 回来比对)、提交、push 到本地裸远端、推送被拒、舍弃单文件/全部/重命名/暂存删除、冲突拒绝、回收站增删清空、按仓库过滤、扫描深度
test/check.mjsmanifest 指向的文件都存在且进得了 tarball、patch 层只有一行且没有密钥、两份线协议字面量一致、字典与 locale/*.json 一致、每个 t('字面量') 都能查到、README/workflow 的存在性与内容
scripts/check-client-bundle.mjs复刻 client-modules 的判定:exports["./client"] 指向的文件是否真的存在

没有真浏览器 harness,这是有意的:本插件不做任何 DOM 量测、不增强宿主 DOM、没有 portal 到 document.body 的东西, 而那套夹具的忠实性本身就是负担(同家族的插件曾因为夹具抄错一条 CSS 规则,把 bug 固化成绿色)。 test/client.test.mjs 里无 hook 的三个组件是按渲染树断言的,覆盖了勾选状态、确认框默认值、候选人列表这些真正的 UI 规则。 如果以后 UI 长出依赖 :hover 或需要量测的东西,这里就该重新考虑——那条判断写进了 docs/CONTRACT.md。

已知限制

  • 一个工作区绑一个仓库,一个仓库一次推一个远端(有 origin 就优先它)。不做子模块、worktree、分支切换、历史列表、stash。
  • Fetch 用的是 git fetch --prune,会删掉远端已经删除的分支对应的 remote-tracking ref(和 GitHub Desktop 一致)。
  • 提交会跑你自己的 commit hook。卡住的 hook 是你自己的 hook;timeoutMs 是唯一的兜底。
  • 回收站只存那一个 diff。恢复是把它 git apply 回去,所以能恢复出一模一样的字节(CRLF、无尾换行、 unicode、行尾空格都验过)。但它只能在「工作区还是舍弃后的样子」时重放:HEAD 变了,或那些文件又被改过, 按钮就变灰并说明原因——否则就是拿旧改动盖掉新改动。 恢复出来的文件回到列表时是勾上的:重放之后宿主会把这些路径 git add 进索引, 和「任何改动都默认勾选」是同一条规则,也和本插件「勾选就是真的索引」一致——终端里 git status 看到的就是这样。 恢复成功后这条记录会被移除:它是舍弃的逆操作,放回去之后档案就没有用处了, 而且再重放一次会把同一个改动应用两遍。
  • 二进制文件不归档内容,只记一句 Binary files … differ。这很诚实,但那不是备份。
  • 超过 maxFileBytes 的未跟踪文件被舍弃时,归档里只有一段说明。确认框目前不会特别提示这一点。
  • 「舍弃未跟踪文件」是直接删除(不进系统回收站)——这是说好的设计:插件自己的回收站承接它,不勾「彻底删除」时能看到内容。

发布(维护者)

版本号就是发布按钮:

  1. 改 package.json 的 version。
  2. 推到 main。

.github/workflows/publish.yml 会跑 npm test,然后 npm view <name>@<version>——该版本已经在线就静默跳过(绿色的 no-op,并提示你 bump)。所以漏改版本号不会静默重发,也不会变成一次红色失败。

认证是 npm 的 Trusted Publishing(OIDC):没有任何 token secret,id-token: write 就是全部凭据。

一次性配置:在 npmjs.com 上绑定 Trusted Publisher

包的页面 → Settings → Trusted Publisher,填:

字段值
PublisherGitHub Actions
RepositoryCkarefulon/dsh-gitbar-lite
Workflow filenamepublish.yml
Environment(留空)

首次发布必须手工 npm publish——Trusted Publisher 只能绑到一个已经存在于 registry 上的包名。

工作流刻意不用 actions/setup-node 的 registry-url:它会往 ~/.npmrc 写 _authToken=${NODE_AUTH_TOKEN},而这个字面占位符会被当成凭据发出去。registry 由 publishConfig 提供。

另外它会先把 npm 升到 ^11.5.1:Trusted Publishing 是 npm CLI 的能力,Node 22 自带的 npm 10 不支持 OIDC 交换, 在 npm 10 上会以 ENEEDAUTH 失败——那看起来像缺 token,其实是 npm 太旧。

许可

MIT,见 LICENSE。

「GitHub Desktop」是 GitHub, Inc. 的产品名称;本插件不是 GitHub 的产品,也与 GitHub 无关,只是借用了那种布局。

Comments

Loading…

From the same category

dsh-TUI

by ccch1mneyyy

DSH 官方公众号收录的 TUI 补位插件:Claude Code 风,鲸鱼顶栏/实时状态/流式思考/双击 Esc 回滚/上下文进度+TPS。npm 一键装。 DSH official WeChat featured TUI plugin — Claude Code style: whale bar, live status, streaming thoughts, double-Esc rol

Terminal & ClientsManifest valid

★ 4.8k

↓ 7.2k/wk

MIT

TypeScript

Oct 19, 2026

dsh plugin --profile terminal add @deepseek-harness-tui/dsh-tui

by strukto-ai

The World's First Virtual Terminal for AI Agents

Terminal & ClientsManifest valid

★ 3.7k

↓ 227/wk

Apache-2.0

TypeScript

Oct 19, 2026

dsh plugin --profile agent add @struktoai/mirage-dsh

by bowenliang123

The best DeepSeek Harness plugin for context insight and management, with context dashboard / browser / sidebar and context command, for context statistics, composition, breakdown, evolution details,

Tools & CapabilitiesUI & ExperienceTerminal & ClientsManifest valid

★ 2.3k

↓ 39.4k/wk

Apache-2.0

TypeScript

Oct 19, 2026

dsh plugin --profile web add dsh-context

by huiliyi37

官方 DeepSeek Harness 的交互式终端 UI 插件:自研 ANSI 极简交互渲染、流式 Markdown/工具卡、16+ 主题、slash 命令与选择器、输入历史与本地偏好持久化、LSP 诊断、memory记忆,很丝滑的开发体验。

Terminal & ClientsManifest valid

★ 287

↓ 319/wk

Apache-2.0

TypeScript

Sep 30, 2026

dsh plugin --profile terminal add @huiliyi37/dsh-tianshu-tui

by Hilbert-beinghappy

面向 DeepSeek Harness 的 Claude Code 风格终端界面,支持 Windows、macOS 与 Linux,兼容透明终端、VS Code 主题和自定义配色。

Terminal & ClientsManifest valid

★ 196

↓ 108/wk

MIT

TypeScript

Oct 13, 2026

dsh plugin --profile web add seektty

by c3cvld7aag

富江DSH完美破甲|富江破甲 DSH 本地插件,内置提示词规则,支持 Windows 一键安装、环境自动准备与一键卸载,全中文使用说明。

Terminal & ClientsManifest valid

★ 145

JavaScript

Oct 3, 2026

dsh plugin --profile web add fujiang-armor