前言¶
在 DeepSeek Harness(DSH)里让智能体改代码,常见做法是交给模型在 bash 里直接跑 git add、commit、push。会话一结束,工作区里往往还有未提交的改动,分支也可能一直没推上去;模型未必记得在回合结束前收尾,你也很难从一次对话里一眼看出「到底漏了什么」。
下面介绍社区插件 stansz/dsh-git(GitHub:stansz/dsh-git,目录页:skillhub.cn/plugins/stansz/dsh-git)。它把日常 git 操作收敛到同一个 git 工具与 /git 命令,用守卫拦截 shell 里容易绕开流程的原始 git 调用,并在回合边界自动提交、推送本会话记录过的路径,目标是让「没有东西被漏提交」不依赖模型记忆。插件由维护者 stansz 发布,分类为客户端;当前 GitHub 星标为 1。许可为 MIT,README 明确说明这是第三方 bundle,并非 DeepSeek 官方包。
三个包、两条安装线¶
生态里与 git 相关的能力拆成三个仓库,安装顺序有硬性要求:
| 包名 | 仓库 | 作用 |
|---|---|---|
dsh-git-core |
github.com/stansz/dsh-git-core | 共享库:统一执行 git、状态存储、记录会话改过的文件;不注册工具、命令或监听器 |
dsh-git(本文对象) |
github.com/stansz/dsh-git | git 工具、/git、bash/pwsh 守卫、回合边界自动 commit/push |
dsh-git-worktrees |
github.com/stansz/dsh-git-worktrees | 可选:按任务建 worktree、worktree 工具及受保护分支上的编辑守卫 |
必须先装 core。 dsh-git-core 是库而非插件,bundle patch 为空数组;装好后落在 profile 的 node_modules,由 dsh-git 通过 lib/core-loader.mjs 解析。README 说明:link: 安装不会提升依赖,裸 import 无法解析。
最少组合是 core + dsh-git,即可覆盖工具、守卫与自动同步。worktree 相关配置(如 worktreeRoot、autoWorktree、worktrees)属于可选包 dsh-git-worktrees,不在本 bundle 的配置行里。
核心功能¶
统一的 git 工具与 /git¶
插件向 DSH 注册一个 git 工具,模型看到的是十个动作的完整说明;人类可用 /git 打印同一套状态。动作概览如下(与 README 一致):
- clone:从 URL 克隆;
path为落地路径,branch可在克隆时检出分支。 - init:在
path创建空仓库,branch为初始分支名。 - status:单个仓库或目录下所有仓库的状态:分支、ahead/behind、变更路径、worktree;可选
pull: true查看打开的 Pull Request。只读。 - save:提交本会话在本仓库记录过的改动;不传
paths时只提交这些文件,其余脏文件会单独报告,避免扫进别的会话的改动;可用paths、message覆盖。 - publish:推送当前分支,首次推送会设 upstream;受保护分支默认拒绝,除非
allowProtected: true。forceWithLease: true用于 rebase 后替换本分支远端引用(远端已前进时 git 会拒绝)。 - sync:fetch 并拉入基线;无额外参数时在「本分支尚无自有提交」时 fast-forward,否则报告分叉;
rebase: true或merge: true处理并入,冲突会中止并列出路径。 - pr:为本分支打开 PR,或返回已打开的 PR;不会重复开第二个。
- merge:按编号合并 PR,或合并当前分支已打开的 PR;成功后会删仍指向合并提交的远端分支,并 fetch
origin(结果里含baseFetched),便于后续prune。 - finish:收尾单元工作:保存脏改动、publish、打开或复用 PR 并报告。
- prune:先 dry-run 再清理本工具留下的可删分支(无 worktree 且无自有提交的任务分支、已合并 PR 证明可删的分支等);
apply: true才真正删除。
Shell 守卫(仅智能体工具调用)¶
对 智能体 在 bash、pwsh 里执行的 git 命令,插件在 tools/pre-execute 阶段检查;你自己的终端不受影响。
- 日常流重定向:
git add、commit、push、pull、fetch、rebase会被拒绝,并提示改用save、publish、sync(rebase 场景用sync且rebase: true)。 - 拒绝丢工作:
reset --hard/--merge/--keep、clean、强推、branch -D、checkout -- <paths>、restore、stash drop、tag -f、改历史类命令,以及gc --prune=now、git prune等;git prune -n/--dry-run不删对象,会放行。 - 其余命令照常:
config、remote、tag、branch、checkout、merge、clone、worktree及只读操作等维护类命令不拦;fetch --dry-run、push --dry-run、clean -n等 dry run 会执行且不发送变更。
README 写明:检测是尽力而为,不是安全边界(只解析命令行 token,不做展开)。设置 guardMode: warn 时允许一切命令(含破坏性),且不报告;完整拒绝列表见仓库内 docs/guard.md。
回合边界自动同步¶
不依赖会话里具体用了哪条命令写文件。触发时机:
agent/turn-stopping,或带turn/end的session/event;- 若长时间无回合边界:每次工具调用会启动 settle 定时器,安静 4 秒后执行同步;持续连发工具调用时,至少每分钟仍会同步一次。
在每个本会话记录过改动的仓库里,只对「会话记录路径 ∩ 当前实际脏路径」做 commit,其余脏文件留在工作区并在报告中列出。提交说明形如 dsh: turn 3 — a.mjs, b.mjs 或 dsh: a.mjs(README 截断处仍可见该模式)。随后推送 deemed safe 的内容。README 强调:这类行为 deliberately 不是需要模型「记得去做」的可选项。
安装与启用¶
在 profile 目录(安装目标目录,不是全局 prefix)执行:
pnpm add github:stansz/dsh-git-core # 共享库,必须先装
pnpm add github:stansz/dsh-git
package.json 标明 Node >= 22,当前插件版本 0.2.0。README 称各项设置均有可用默认值,零配置挂载即可工作;覆盖方式见 README 的 Settings 与 Changing a setting 章节(本文未展开全部字段,以仓库文档为准)。需要按任务隔离工作区时,再按 docs/install.md 安装可选的 dsh-git-worktrees。
典型用法¶
日常让模型走工具而非 shell git:
- 用
git→status(必要时pull: true)看清分支、变更与 PR。 - 改完代码后
save提交本会话改动;需要上远端时用publish。 - 与基线对齐用
sync;要开或查 PR 用pr;一条链路收尾可用finish。 - 你在对话里输入
/git可与模型看到的状态对齐阅读。
若模型仍尝试 bash 里 git commit,守卫会拒绝并指向上述动作——这是设计行为,不是安装失败。
适用场景与注意¶
适合:在 DSH 里长期让智能体改同一批仓库、希望提交/推送节奏一致、且希望减少「会话结束留下脏树或未推送提交」的团队或个人。
注意:
- 插件以当前 dsh 进程的权限执行 git 与网络操作;安装前请阅读源码与 MIT 许可证,确认符合你的合规要求。
- 守卫不覆盖你在本机独立终端里的 git;也不要把它当成防恶意命令的沙箱。
- 社区目录 skillhub.cn 与 DeepSeek / 幻方无官方从属关系;DSH 生态是「一切皆插件」,本文介绍的是第三方 bundle。
- 可选 worktree 能力与本文主包配置分离,需要时再装
dsh-git-worktrees。
结尾¶
stansz/dsh-git 把 DSH 里的 git/GitHub 操作收成一条可预期的路径:git 工具负责 clone 到 prune 的十个动作,守卫把 shell 里的日常流引向同一套 API,自动同步在回合结束或短暂静默后补上 commit/push。若你正在 profile 里接智能体写代码,可先按 README 顺序安装 core 与本包,用 /git 和 status 验证状态是否符合预期。
- 目录页:https://www.skillhub.cn/plugins/stansz/dsh-git
- 源码与文档:https://github.com/stansz/dsh-git