面向 DeepSeek Harness 的 对话 ↔ 工作树绑定…
31.5/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/29 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查有告警:npm 同名包「dsh-git-worktree」归属 wloops/dsh-git-worktree,装到的可能不是本插件。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add KHG420/git-worktree该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · browser
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 36 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
⚠︎ 实装验证未通过(dependency_conflict · 2026/10/30) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意npm 同名包「dsh-git-worktree」归属 wloops/dsh-git-worktree,装到的可能不是本插件
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-git-worktree @ 0.10.0
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/15 01:03:28
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件发起外部网络请求
查看扫描证据(共 10 处,展示前 10 条)
- 发起网络请求client.js:114
const res = await fetch(path, init); - 写入本地文件lib/tasks.js:171
mkdirSync(dir, { recursive: true }) - 写入本地文件lib/tasks.js:174
writeFileSync(tmp, `${JSON.stringify(record, null, 2)}\n`, 'utf8') - 写入本地文件lib/tasks.js:175
renameSync(tmp, target) - 读取本地文件lib/tasks.js:207
raw = readFileSync(path, 'utf8') - 读取本地文件lib/tasks.js:231
names = readdirSync(dir) - 读取本地文件lib/git.js:58
return statSync(cwd).isDirectory() ? null : 'not a directory' - 读取本地文件lib/git.js:235
existing = readFileSync(excludePath, 'utf8') - 写入本地文件lib/git.js:240
mkdirSync(infoDir, { recursive: true }) - 写入本地文件lib/git.js:242
appendFileSync(excludePath, `${separator}${rule}\n`, 'utf8')
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-agent@deepseek-ai/dsh-llm@deepseek-ai/dsh-subagent@deepseek-ai/dsh-tools@deepseek-ai/schemastery@deepseek-ai/cordis@deepseek-ai/dsh-host-webserver@deepseek-ai/dsh-subprocess给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 会话绑定独立工作树
- 并行操作互不干扰
- 侧边栏管理工作区树
DeepSeek Harness 插件:一键把每个会话绑定到独立的 git worktree + 分支,多个智能体并行操作同一仓库互不干扰——每个项目的 worktree 都在侧边栏工作区树里自动管理,背后有 9 个 git 工具支撑。
README
由 DeepSeek 最新模型翻译生成dsh-git-worktree
面向 DeepSeek Harness 的 对话 ↔ 工作树绑定 插件:让多个会话在同一项目上并行工作,每个会话绑定一个独立 git 工作树 + 分支,一键创建、互不干扰(绑定是“专属工作树”标记,不是独占锁;真正的保护是同机占用检查,见下文)。
DeepSeek Harness 插件:一键将每个对话绑定到其独立的 git 工作树 + 分支,使并行 agent 可以在同一个仓库上工作而互不干扰。绑定是“专属工作树”标记,不是独占锁;真正的保护是下文描述的同机占用检查。
- 绑定 / Binding — 会话在创建时即绑定到专属工作树:工作树 + 工作区 + 会话一次成型(绑定关系可推导、可展示、可清理;非独占,可共享)。
- Agent 工具 / Agent tools — 13 个工具:原有 9 个 Git 工具(git_session_binding、git_repo_status、git_worktree_、git_branch_),加上 4 个任务工具(git_task_start、git_task_status、git_task_cancel、git_task_integrate),每个会话都可以调用。
展开完整文档(README 剩余 1 节)
dsh-git-worktree
面向 DeepSeek Harness 的 对话 ↔ 工作树绑定 插件:让多个会话在同一项目上并行工作,每个会话绑定一个独立 git 工作树 + 分支,一键创建、互不干扰(绑定是“专属工作树”标记,不是独占锁;真正的保护是同机占用检查,见下文)。
DeepSeek Harness 插件:一键将每个对话绑定到其独立的 git 工作树 + 分支,使并行 agent 可以在同一个仓库上工作而互不干扰。绑定是“专属工作树”标记,不是独占锁;真正的保护是下文描述的同机占用检查。
- 绑定 / Binding — 会话在创建时即绑定到专属工作树:工作树 + 工作区 + 会话一次成型(绑定关系可推导、可展示、可清理;非独占,可共享)。
- Agent 工具 / Agent tools — 13 个工具:原有 9 个 Git 工具(git_session_binding、git_repo_status、git_worktree_、git_branch_),加上 4 个任务工具(git_task_start、git_task_status、git_task_cancel、git_task_integrate),每个会话都可以调用。13 个工具:原有的 9 个 Git 工具(git_session_binding、git_repo_status、git_worktree_、git_branch_)加上 4 个任务工具(git_task_start、git_task_status、git_task_cancel、git_task_integrate),每个对话都可以调用。
- 左侧工作区树 / The sidebar workspace tree — 唯一的管理界面:每个项目自动检测全部 git 工作树并注册为平铺的工作区行(主工作树 = 项目文件夹本身,标记 主工作树),工作树行上可新建会话(出生即绑定)或 删除工作树(含绑定会话提示/归档;运行中的会话会阻止删除)。唯一的管理界面:每个项目自动检测其所有 git 工作树,并将每个工作树注册为平铺的工作区行(主工作树就是项目文件夹,标记为 主工作树);工作树行可以启动一个对话(出生即绑定)或 删除工作树(带绑定对话警告/归档;运行中的对话会阻止删除)。
绑定是什么 / What a binding is
DSH 中,会话的工作目录(cwd)在创建时冻结,工作区归属要求“会话 cwd == 工作区路径”。因此绑定只能在创建会话的那一刻发生——把会话建在专属工作树里,绑定关系即成立:
DSH 会话的 cwd 在创建时冻结,工作区归属要求会话的规范 cwd 等于工作区路径。因此绑定发生在创建时:对话诞生在自己的工作树中:
~/projects/foo/ ← 主工作树 / primary worktree (main) ├── .dsh-wt/ │ ├── feature-a/ ← 会话 A 绑定 / conversation A is bound here (branch feature-a) │ └── bugfix-b/ ← 会话 B 绑定 / conversation B is bound here (branch bugfix-b)
└── (共享同一个 .git / one shared .git)
绑定关系无需额外存储,由 sessions.list(cwd)× git worktree list(路径→分支)× workspaces.list 推导而来——左侧树与 agent 工具看到的都是实时事实。
绑定是推导出来的,而不是存储的:sessions.list(cwd)× git worktree list(路径→分支)× workspaces.list——侧边栏树和 agent 工具显示的都是实时事实。
绑定不是独占锁 / A binding is not an exclusive lock
bound 只表示“本会话拥有一个专属(非主)工作树”,不表示独占:另一个会话完全可以共享同一个工作树,bound 也不会告诉你还有谁在写入。真正的并发保护是同机检查(same-host check),不是跨进程锁,也不是 shell 沙箱:
bound 只表示“本会话拥有一个专属(非主)工作树”,不表示独占:另一个会话完全可以共享同一个工作树,bound 也不会告诉你还有谁在写入。真正的并发保护是同机检查(same-host check),不是跨进程锁,也不是 shell 沙箱: bound 只意味着“此对话拥有自己专用的(非主)工作树”——它不是排他性。另一个对话可能共享同一工作树,而 bound 并不说明还有谁在写入。真正的保护是同主机检查,而不是跨进程锁,也不是 shell 沙箱:
- 查询绑定时:当宿主暴露原生 agents 注册表,且另一个 RUNNING 的原生 agent(包括子 subagent)按“最长匹配”规则解析到同一工作树时,git_session_binding 会以清晰的占用错误失败,而不是给出一个看起来安全的绑定;调用者自身被忽略,idle 的同伴不会被当作正在写入。
- 删除工作树时:git_worktree_remove 只要目标工作树里有 RUNNING 的 agent(包括调用者自己),即使带 force 也拒绝;force 只豁免 git 的脏工作树检查。本插件运行中的 git_task_ 任务也占用其工作树(含 preparing setup 阶段和尚未完成的释放),此时同样拒绝删除,且不依赖 agents 服务。
- UI 侧同样列出工作树上的全部会话(含 subagent),只要有 running 会话就停用删除并说明原因。
- 最小 profile:没有 agents 服务时检查自动跳过,工具照常可用——这是有意的能力降级,不要把它当作安全保障。
清理失败恢复 / Cleanup failure recovery
删除工作树是 git 优先、分阶段执行的:先真正删除 git 工作树,再(按选择)归档绑定会话,最后注销工作区文件夹。结论固定、重试安全:
- git 删除失败 → 不归档、不注销,确认框保留并报告原因,可直接重试。
- git 删除成功之后的归档或注销失败 → 明确报错,重试只执行未完成的步骤(绝不会再删一次 git 路径);待归档的会话 id 在删除后冻结,不因绑定重新解析(工作树已消失)而丢失。
- 不吞掉注销失败(旧版本会静默忽略)。
确认框用中文说明两种失败:Git 拒绝删除时会提示“目录仍然存在,请先保存/提交/stash 后重试”(不会自动 --force);Git 删除之后的清理失败会明确“目录已删除、清理未完成”。原始 git 报错保留在折叠的“技术详情”里。确认框用中文说明两种失败:Git 拒绝删除时会提示目录仍然存在,请先保存/提交/stash 后重试(绝不自动 --force);删除后的归档/注销失败会说明目录已不存在,但清理尚未完成。原始 git 错误仍可在折叠的“技术详情 (technical details)”下查看。
本地忽略规则 / Local exclusion rule
name 形式的默认工作树位于 /.dsh-wt/,嵌套在自己的仓库里;若不加处理,git add -A 会把它当作 gitlink/嵌入式仓库暂存。插件会在共享的 /info/exclude(不碰被跟踪的 .gitignore)里为配置的 name-based 父目录写入一条锚定规则(如 /.dsh-wt/):
基于 name 的工作树位于 /.dsh-wt/,嵌套在其自己的仓库内;如果不加处理,git add -A 会将其暂存为 gitlink/嵌入式仓库。插件会向共享的 /info/exclude(绝不是被跟踪的 .gitignore)中为配置的基于 name 的父目录写入一条锚定规则(例如 /.dsh-wt/):
- 保留已有字节、幂等(重复创建不重复写)、并发的同进程创建经写链串行化;含空格/元字符的目录名会正确转义。
- 只针对仓库内的 name-based 父目录;显式 path、仓库外的父目录、仓库根本身都不会被写入。
- 写入失败会报错(工作树已建,但明确告知未被保护),而不是静默返回“成功”。
- 保留已有字节,规则是幂等的,并发的同进程创建通过写入链串行化,包含空格/元字符的目录名会被转义。
- 只会触及仓库内基于 name 的父目录;显式 path、仓库外的父目录或仓库根目录绝不会被触及。
- 写入失败会被报告(工作树存在,但被明确标记为未受保护),而不是静默返回成功。
分支语义 / Branch semantics
name 形式且未给出显式 branch/newBranch/detach/commitIsh 时,插件显式 git worktree add -b 创建全新分支——绝不会静默复用一个已存在但未检出的分支。unique: true 时冲突会新建带后缀的工作树+分支(-2、-3…);unique: false 时直接报 git 的严格错误;force 也不绕过。显式 branch(复用已有分支)、newBranch(指定新分支名,冲突报错)、detach、commitIsh 语义保持不变;path 形式仍沿用 git 自身的推断。
当基于 name 的请求未显式指定 branch/newBranch/detach/commitIsh 时,会运行 git worktree add -b 来创建一个全新分支——它绝不会静默复用已存在但未检出的分支。使用 unique: true 时,冲突会变成新的带后缀工作树+分支(-2、-3……);使用 unique: false 时,git 的严格错误会直接暴露;force 不会绕过它。显式 branch(复用)、newBranch(指定名称,冲突则失败)、detach 和 commitIsh 保持其含义;显式 path 保持 git 自身的推断。
任务协作 / Task collaboration
主会话可以用 4 个任务工具把明确的独立任务派发到各自的工作树,并在验证后合并(原有 9 个 Git 工具保持兼容):
主会话可以将明确的独立任务分派到各自的工作树,并在验证后整合它们(原有的 9 个 Git 工具保持兼容):
1. git_task_start({ name, prompt, repo?, base? }) — 创建全新工作树 + 分支(//,重名自动后缀),写入本地任务记录后立即返回 preparing;随后在任务生命周期内顺序执行配置的 setupCommands,再以调用者 agent 为父创建一个原生子 agent,其 cwd 在创建时冻结为该工作树,继承调用者的模型与权限(只收窄、不扩大:approval 固定 never,sandbox 沿用父级 override)。子任务有深度上限(主 agent 深度 0 → 任务子 agent 深度 1),不能再次 git_task_start。多个 git_task_start 可并发。
2. git_task_status({ repo?, taskId? }) — 列出本仓库(记录写在共享 git common dir 下,linked worktree 同样可见)的任务:状态、工作树/分支、子会话 id、最终摘要、commit、错误。另一个仍存活的 DSH 进程拥有的活动任务按原样报告;只有能证明属主进程已消失时才标记 interrupted(用 kill(pid, 0) 存活探测,不发送任何信号)。
3. git_task_cancel({ taskId }) — 只停止本进程拥有的任务:中止 setup 或取消并排空子 agent,持久化 cancelled,保留工作树与分支。已结束任务幂等;属于其他存活进程的任务只报告限制,绝不向其发信号。插件/父级 teardown 会取消并释放自己启动的全部子 agent。
4. git_task_integrate({ repo?, taskId, verifyCommands? }) — 把已完成、已提交、干净的任务分支合并进目标工作树(repo,默认调用者工作树),只用真实 git,绝不 force/reset/clean、绝不 push/deploy。拒绝:活动任务、脏源/脏目标、源未提交、源==目标、目标或源内有其他 RUNNING 写入者(允许调用者自己所在的 target)。合并基于已记录并核对的 HEAD;冲突保留(不自动 abort/reset)并给出恢复说明。合并成功后顺序执行 verifyCommands(argv 数组、无 shell),全部通过才 verified;失败标记未验收,重试只重跑验证、不重复合并(即使目标 HEAD 已前进也不复用旧验证)。未提供命令则明确 verified=false(未独立验证)。源工作树/分支保留,由用户自行清理。
原生 spawn/fork 行为不变;任务入口是"独立写入"的推荐入口。The native spawn/fork behavior is unchanged; the task entry is the recommended isolated-writing path.
环境准备示例 / Setup example
setupCommands 为可选配置(默认 []),不经过 shell、不会自动复制 .env 或安装任何东西;每条命令在新任务工作树内按顺序执行,失败/超时/取消会得到有界诊断并在启动子 agent 之前停止(工作树保留供排查)。空数组以外、空 argv 数组、空字符串段或非数组形式都会在插件加载时报错。
setupCommands is optional (default []), never shell-interpolated, and never copies .env or installs anything implicitly. Commands run sequentially inside the new task worktree; a failure/timeout/cancel returns bounded diagnostics and stops before the child agent launches (the worktree is kept for inspection). An empty outer array is allowed, but empty argv arrays, empty-string segments, or a non-array shape fail plugin loading.
- id: git-worktree
name: dsh-git-worktree
config:
setupCommands:
- ["pnpm", "install", "--frozen-lockfile"]
- ["node", "scripts/check-env.mjs"]
继承与限制 / Inheritance and limits
- 任务子 agent 继承调用者的模型、权限与工具组合(通过 DSH 的 delegation 合成:captureDelegatedPolicyOverrides + applyChildComposition + resolveChildAgentOptions),但看不到调用者会话内容,必须在 prompt 中给出自包含的完整任务。Task children inherit the caller's model, permission scope, and tool composition via the DSH delegation helpers, but cannot see the caller's conversation — give every task a self-contained prompt.
- 它不是 OS 沙箱;工作树隔离只保证工作树层面互不干扰。It is not an OS sandbox; worktree isolation only separates the working trees.
- 同机占用检查(原生 agents 注册表)不是跨进程锁;另一 DSH 进程或手工 shell 的写入不在保护范围内。The same-host occupancy check (native agents registry) is not a cross-process lock; writes from another DSH process or a manual shell are outside its protection.
- git_task_integrate 的验证命令必须只做只读检查:若它修改了目标的已跟踪文件/索引或移动了 HEAD,结果为未验收,改动被保留(绝不 reset),需要人工清理后重试;重试只重跑验证、不重复合并。git_task_integrate verification commands must be read-only checks: if one modifies a tracked target file/index or moves HEAD, the result is unverified, the changes are preserved (never reset), and a cleanup + retry reruns verification without repeating the merge.
界面范围 / UI scope
本插件不替换原生 spawn/fork,也不新增独立面板;任务协作只以 agent 工具的形式提供,管理仍沿用既有左侧工作区树(见下文)。侧边栏不显示任务工作树以外的专用看板。
The plugin does not replace native spawn/fork and adds no separate dashboard; task collaboration is agent-tool-only and management stays on the existing sidebar workspace tree (below). No dedicated task board is added to the sidebar.
一键创建绑定会话 / One-click bound conversation
点击项目文件夹(仓库)行的 +,输入功能名,点 创建绑定会话:
1. git worktree add -b /.dsh-wt/(重名自动加后缀 -2、-3…)
2. workspaces.create({ path })(幂等注册工作区)
3. connectWorkspace → 会话直接诞生在该工作树(绑定成立)
4. 自动打开该会话
输入框有固定标签“工作树名称”和示例(如 login-page);名称会被规范化(空格等转为 -),有变化时先预览将创建的路径与分支,非法名称(如 ///、...、空白)会禁用创建并说明原因。仅创建工作树成功后不自动开会话,而是保留弹层显示真实路径/分支以及“打开绑定会话”“完成”;若工作树已创建但会话打开失败,重试只重开会话,绝不重复创建工作树。
On the sidebar tree, click the + on the project (repo) folder, type a feature name, hit 创建绑定会话 (Create bound conversation):
1. git worktree add -b /.dsh-wt/ (name collisions auto-suffix -2, -3, …)
2. workspaces.create({ path }) (idempotent workspace registration)
3. connectWorkspace → the session is born inside that worktree (the binding)
4. the new conversation opens automatically
The input carries a persistent "工作树名称" label and an example (login-page); the name is sanitized (spaces become -) and a preview shows the target path/branch when it changes, while invalid names (///, ..., blank) disable creation with a reason. A successful worktree only run keeps the popover open with the real path/branch plus "打开绑定会话 (open bound conversation)" / "完成 (done)" actions; if the worktree exists but opening the conversation fails, the retry only re-opens it — never a second worktree create.
已存在的工作树行上的 + 是「在该工作树新建会话」——会话出生即绑定(agent 先建好工作树、开发者一键确认的场景)。工作树行还有 删除工作树 按钮:确认框列出全部绑定会话(含 subagent;只要有 running 会话就停用删除并说明原因)、可一并归档(日志保留,侧边栏隐藏)、以 git 优先的顺序删除工作树并注销其文件夹;删除后的归档/注销失败会明确报错且只重试未完成步骤(见“清理失败恢复”)。确认框在没有绑定会话时不显示归档勾选框并说明分支仍保留,分支行只显示短 SHA(完整值在悬停提示中)。
工作树行的 + 会在该工作树中启动一个新对话——生而绑定(agent 准备 / 开发者确认流程)。该行还有 删除工作树 (Remove worktree):确认框会列出每一个已绑定对话(包括子代理;任何 running 的对话都会禁用删除并给出说明),可以归档它们(日志保留;侧边栏隐藏它们),以 git 优先的方式移除 git 工作树并注销其文件夹;移除后的归档/注销失败会被报告,且只有未完成的步骤会重试(见“清理失败恢复”)。在没有绑定对话时,归档复选框会被省略,面板会注明分支被保留;分支行显示短 SHA(悬停时显示完整值)。
安装 / Installation
在插件目录下执行 / from the plugin checkout
dsh plugin --profile web add /path/to/dsh-git-worktree
重启 dsh web — 工具与树界面同时生效 / restart dsh web — tools and the tree surface activate together
卸载 / Removal: dsh plugin --profile web remove dsh-git-worktree。
工具 / Tools
所有工具都接受 repo 参数(默认取会话工作区;相对路径会基于它解析)并返回 JSON。git 分支/工作树是共享可变状态,故都不声明并发安全。
All tools accept repo (default: the session workspace; a relative path resolves against it) and return JSON. None is concurrency-safe by design — branch/worktree state is shared mutable state.
| 工具 | 用途 |
| git_session_binding | 开场必查:本会话的绑定——仓库、所在工作树、检出分支、peer 工作树。bound 仅在拥有专属(非主)工作树时为 true,不代表独占;有 RUNNING 原生 agent(含子 subagent)解析到同一工作树时以占用错误失败(调用者自身忽略,idle 同伴不算写入)。无 agents 服务时跳过检查。 |
| git_repo_status | 分支、领先/落后、脏文件;查询本会话所在仓库时附带 binding 块(bound 同为非独占语义)。 |
| git_worktree_list | 列出所有工作树(含分支/HEAD),标记 主工作树 与 当前会话。 |
| git_worktree_add | 创建工作树。name → /.dsh-wt/(锚定主仓库根,从工作树内创建也不会嵌套);或显式 path。name 且无显式 branch/newBranch/detach/commitIsh 时 -b 创建全新分支(不复用已有分支);unique 冲突时新建 -2、-3… 工作树+分支;显式 newBranch 冲突报 git 原错。仓库内 name-based 父目录会写入本地 info/exclude,git add -A 不会把工作树当 gitlink 暂存。 |
| git_worktree_remove | 删除工作树(分支保留)。只接受已注册的工作树;主工作树会被拒绝;目标内有 RUNNING 原生 agent(含调用者)时即使 force 也拒绝;force 仍可删除含未提交改动的工作树。 |
| git_branch_list | 列出分支:短 sha、检出标记(调用者所在工作树的 HEAD)、上游;all 包含远程分支。 |
| git_branch_create | 创建分支;switch 立即检出;from 指定基于哪个提交/分支。 |
| git_branch_switch | 切换当前工作树的分支;create 表示不存在时先创建。 |
| git_branch_delete | 删除分支;force = -D。git 会拒绝删除在任何工作树中已检出的分支——这是保护机制,直接呈现而非绕过。 |
| git_task_start | 在全新工作树+分支中启动一个独立任务,并创建一个 cwd 冻结在该工作树的原生子 agent(继承调用者模型/权限,不扩大;有深度上限)。可配 setupCommands,失败则不启动 agent。立即返回 preparing。 |
| git_task_status | 列出/查询本仓库的任务记录(状态、工作树、分支、子会话 id、摘要、commit、错误);记录在共享 git common dir,linked worktree 可见;死属主活动记录标记 interrupted,存活外部属主不覆盖。 |
| git_task_cancel | 停止本进程拥有的任务(中止 setup 或排空子 agent),保留工作树与分支,持久化 cancelled;已结束幂等;外部存活任务只报告限制。 |
| git_task_integrate | 把已完成任务分支合并进目标工作树并运行 verifyCommands;拒绝活动/脏/未提交/source==target/运行中写入者;冲突保留待手动解决;验证失败不算验收,重试不重复合并;不 push/deploy。 |
| Tool | Purpose |
| git_session_binding | 首先调用:本次对话的绑定——仓库、其工作区所在的工作树、已检出的分支、对等工作树。仅当存在专用的(非主)工作树时,bound 才为 true——并非排他性;另一个正在运行的本地 agent(包括子 subagent)解析到同一工作树时会产生明确的占用错误(调用者自身被忽略;空闲对等方不计为写入者)。没有 agents 服务时跳过。 |
| git_repo_status | 分支、领先/落后、脏条目;在查询自身仓库时附带会话的 binding(bound 具有相同的非排他含义)。 |
| git_worktree_list | 每个工作树及其分支/HEAD,标记 primary 和 this session。 |
| git_worktree_add | 创建工作树。name → /.dsh-wt/(锚定到主仓库根目录,绝不嵌套在调用者的工作树内);或显式 path。没有显式 branch/newBranch/detach/commitIsh 的 name 会用 -b 创建一个全新分支(绝不静默复用);unique 冲突会变成新的 -2、-3、…… 工作树+分支;显式 newBranch 冲突会暴露 git 的错误。仓库内基于 name 的父目录会获得一条本地 info/exclude 规则,以便 git add -A 不会将其暂存为 gitlink。 |
| git_worktree_remove | 移除工作树(保留分支)。仅接受已注册的工作树;主工作树会被拒绝;目标中正在运行的本地 agent(包括调用者)会拒绝移除,即使使用 force 也是如此;force 仍会移除未提交的更改。 |
| git_branch_list | 分支及其短 sha、检出标记(调用者工作树的 HEAD)、上游;all 包括远程分支。 |
| git_branch_create | 创建分支;switch 将其检出;from 选择基础。 |
| git_branch_switch | 切换当前工作树的分支;create 会先创建它。 |
| git_branch_delete | 删除分支;force = -D。Git 会拒绝在任何地方已检出的分支——该保护会被呈现出来,而不是被绕过。 |
| git_task_start | 在一个全新的工作树+分支中启动独立任务,并启动一个 cwd 冻结在那里的本地子 agent(继承调用者的模型/权限,绝不扩大;有深度上限)。可选的 setupCommands 会先运行;失败绝不会启动 agent。会及时返回 preparing。 |
| git_task_status | 列出/查询此仓库的任务记录(状态、工作树、分支、子会话 id、摘要、提交、错误);记录位于共享的 git 公共目录中,并且从链接的工作树中可见。已死亡所有者的活动记录会被标记为 interrupted;活跃的外部所有者不会被覆盖。 |
| git_task_cancel | 停止此进程拥有的任务(中止 setup 或排空子进程),保留工作树/分支,持久化 cancelled;对已完成的任务幂等;外部活跃任务仅会被报告。 |
| git_task_integrate | 将一个已完成的任务分支合并到目标工作树并运行 verifyCommands;拒绝活动/脏/未提交/源==目标/正在写入的情况;冲突会保留以供手动解决;验证失败不算验收,重试绝不会重新合并;不推送/部署。 |
左侧工作区树:自动检测全部工作树 / 侧边栏树:每个工作树自动检测
当前 DSH(0.1.7-rc.2)的 ui-workspace 只声明 sidebar.workspaces.directoryFlow,不再有 sidebar.workspaces.create 链。因此浏览器端只注册一个 slot(sidebar.footer.action),并从该挂载点直接观察工作区树的 DOM,注入每行控件:
当前 DSH(0.1.7-rc.2)的 ui-workspace 只声明 sidebar.workspaces.directoryFlow,而不是 sidebar.workspaces.create 链。因此浏览器端只注册一个 slot(sidebar.footer.action),并将每行控件直接安装到被观察的树 DOM 中:
- sidebar.footer.action(渲染为空 / 不渲染任何内容,弹层打开时才渲染) — 一个无 UI 的同步挂载点。监听工作区列表,对每个工作区调用 /dsh-git-worktree/list:确保仓库根(主工作树)工作区存在并标记 (主工作树),确保每个工作树路径都注册为工作区;失效清扫——auto 注册的、工作树已从 git 消失且无会话的文件夹会被自动注销(跟随 git)。20 秒静默轮询覆盖 agent 工具/CLI 在工作树层面的改动。同时它观察侧边栏工作区树,按标签把行匹配到工作区并注入控件。一个无渲染的同步挂载点(弹层由它渲染)。监听工作区列表,对每个工作区查询 /dsh-git-worktree/list:确保仓库根(主工作树)工作区存在并标记为 (主工作树),确保每个工作树路径都注册为工作区;失效清扫——auto 注册的、工作树已从 git 消失且无会话的文件夹会被自动注销(树跟随 git)。20 秒静默轮询覆盖 agent 工具/CLI 在工作树层面所做的改动。同一个挂载点观察侧边栏树,按标签将行匹配到工作区,并注入控件。
- 行级控件(DOM 注入 / 逐行注入) —
- 主文件夹(仓库主工作树)+ → 「新增工作树」小窗:功能名 → 创建绑定会话 或 仅创建工作树;注入期间其原生「新建会话」+ 被隐藏,卸载时恢复。主工作树(仓库)文件夹 + → “添加工作树”弹层(创建绑定会话 / 仅创建工作树);注入期间其原生「新建会话」+ 被隐藏,卸载时恢复。
- 工作树文件夹 → 保留原生 +(在该工作树新建会话,出生即绑定)+ 删除工作树 按钮(确认框:绑定会话列表、可一并归档、删除 git 工作树并注销文件夹)。工作树文件夹 → 保留原生 +(在该工作树新建会话,出生即绑定)+ 删除工作树(Remove worktree) 按钮(确认:绑定会话、可选归档、删除工作树并注销文件夹)。
- 非仓库 / 仓库内的无关子目录 → 不注入任何控件,保持原生行为。非仓库和无关的嵌套文件夹 → 不注入任何控件,保持原生行为。
- 同名工作区 → 行上出现「选择工作区」按钮,列出每个候选的绝对路径,由用户显式选择,绝不猜测。重复标签 → 一个“选择工作区”控件列出每个候选的绝对路径,供用户显式选择——该插件绝不会静默地以猜测的仓库为目标。
浏览器端通过 ctx.webServer 以同源方式调用 /dsh-git-worktree 前缀下的宿主路由(list / status / branches / add / remove / bindings)。读路由(list / status)对不在任何 git 仓库内的路径返回 { notARepo: true }(200);bindings 对每个输入路径逐条标记 notARepo/工作树归属;写操作与 agent 工具仍保持严格报错。按 dsh-host-webserver 的文档约定,这些路由没有鉴权——请保持默认的 loopback 绑定。
浏览器通过 /dsh-git-worktree 下的宿主路由(list / status / branches / add / remove / bindings)进行通信,由 ctx.webServer 以同源方式提供服务。读取路由(status、list)对不在 git 仓库内的路径返回 { notARepo: true }(200);bindings 按行标记每个输入路径;变更操作和代理工具则保持严格失败。按照 dsh-host-webserver 的文档化姿态,这些路由没有认证——请将绑定主机保持在回环默认值上。
同步是合并式的:同一时刻至多一次扫描在途,扫描期间的变更折叠为一次收尾重扫;仅当检测到的工作树集合真正变化时才发布给行级 UI(避免无谓重渲染)。
Sync is coalesced: at most one scan in flight, later requests folded into a trailing re-run; the row-level UI is republished only when the detected worktree key sets actually move.
工作区树中的工作树 / Worktrees in the workspace tree
插件只注册到 sidebar.footer.action(自动同步 + DOM 行集成),让左侧工作区树成为完整的绑定管理界面。当前 ui-workspace 把每个工作区渲染为平铺的项目行(不再按路径嵌套),因此每条工作树是独立的一行,插件在该行上注入对应控件:
The plugin registers only into sidebar.footer.action (auto-sync + DOM row integration), making the sidebar tree the complete binding-management surface. Current ui-workspace renders each workspace as a flat project row (no path nesting), so every worktree is its own row and the plugin injects the matching controls on it:
- 树结构:自动同步保证每个工作树(包括从未打开过会话的)都注册为一个工作区行;主工作树的路径就是仓库根,因此项目文件夹即主工作树,标题标记为 (主工作树)。Tree shape: the auto-sync guarantees every worktree (even never-opened ones) is registered as a workspace row; the main worktree's path IS the repo root, so the project folder is the main worktree, titled (主工作树).
- 工树目录位置:无论工作树目录在仓库内(/.dsh-wt/)还是仓库外(显式 path),当前核心都将其渲染为独立的项目行;插件的能力(会话绑定、分支显示、删除工作树)不受位置影响。Placement: whether the worktree lives inside the repo (/.dsh-wt/) or outside it (explicit path), current core renders it as its own project row; every plugin capability (binding, branch display, remove-worktree) is unaffected by placement.
- 行匹配与同名工作区:行按标签匹配到工作区;标签重复时行上出现「选择工作区」,列出每个候选的绝对路径供显式选择,绝不静默作用于猜测的仓库。Row matching: rows match workspaces by label; on duplicate labels a "选择工作区" control lists each candidate's absolute path for an explicit choice — never a silent guess.
- 主文件夹 +(仓库):弹出「新增工作树」小窗,输入功能名 → 创建绑定会话(创建 .dsh-wt/ 工作树并立即创建/打开绑定会话,一键)或 仅创建工作树;非 git 目录不注入控件,保持默认「新建会话」。小窗是具名对话框(role="dialog"),输入框有固定标签与示例、非法名称即时禁用并报错、规范化有变化时预览目标路径/分支;忙碌中输入与按钮禁用且不可被 Esc/点击外部关闭,空闲时 Esc/取消/点击外部关闭并把焦点还给行控件;弹层会按视口钳制位置并在长内容时滚动。主文件夹 +(仓库):弹出「新增工作树」小窗,输入功能名 → 创建绑定会话(创建 .dsh-wt/ 工作树并立即创建/打开绑定会话,一键)或 仅创建工作树;非 git 目录不注入控件,保持默认「新建会话」。小窗是具名对话框(role="dialog"),输入框有固定标签与示例、非法名称即时禁用并报错、规范化有变化时预览目标路径/分支;忙碌中输入与按钮禁用且不可被 Esc/点击外部关闭,空闲时 Esc/取消/点击外部关闭并把焦点还给行控件;弹层会按视口钳制位置并在长内容时滚动。
- 工作树行 + / 删除工作树:保留核心默认 +(在该工作树新建会话,会话出生即绑定),并新增 删除工作树(仅已检测到的工作树):确认框列出绑定的会话,勾选“一并归档这些会话”后删除 git 工作树并注销其文件夹;工作树从 git 消失(agent/CLI 删除)后,无会话的文件夹由同步自动清理。工作树行 + / 删除工作树:保留核心默认 +(在该工作树新建会话,会话出生即绑定),并新增 删除工作树(仅已检测到的工作树):确认框列出绑定的会话,勾选“一并归档这些会话”后删除 git 工作树并注销其文件夹;工作树从 git 消失(agent/CLI 删除)后,无会话的文件夹由同步自动清理。
配置 / 配置
profile 行支持以下配置项(均可选) / profile 行支持以下配置项(均可选):
- id: git-worktree
name: dsh-git-worktree
config:
worktreesDir: .dsh-wt # 新工作树的默认父目录 / 新工作树的默认父目录 timeoutMs: 30000 # 每条 git 命令的超时时间 / 每条 git 命令的超时时间 stdoutMaxBytes: 1000000 # 捕获 stdout 的上限 / 捕获 stdout 的上限 stderrMaxBytes: 65536 # 保留 stderr 摘要的上限 / 保留 stderr 摘要的上限
setupCommands: [] # 可选:每个新任务工作树内顺序执行的 argv 命令(无 shell)/ 可选:每个新任务工作树内顺序执行的 argv 命令(无 shell)
架构 / 架构
dsh-git-worktree/
├── index.js # Cordis 插件 / Cordis 插件:name / inject / Config / apply ├── client.js # 浏览器端 / 浏览器端(手写 __ModuleLoader__ bundle) ├── lib/ │ ├── git.js # 基于 ctx.subprocess 的 git 执行(无 shell 层)、路径规范化 / 基于 ctx.subprocess 的 git 执行(无 shell 层)、路径规范化 │ ├── parse.js # worktree --porcelain / for-each-ref / status 的纯解析器 / worktree --porcelain / for-each-ref / status 的纯解析器 │ ├── operations.js # 工具与路由共用的核心操作(含绑定解析)/ 工具与路由共用的核心操作(含绑定解析) │ ├── tasks.js # 任务记录(原子 JSON)+ 原生子 agent 编排 + 集成/验证 / 任务记录(原子 JSON)+ 原生子 agent 编排 + 集成/验证 │ ├── tools.js # defineTool 封装(9 Git + 4 任务)/ defineTool 封装(9 Git + 4 任务) │ └── routes.js # /dsh-git-worktree REST 处理器(面向浏览器端)/ /dsh-git-worktree REST 处理器(面向浏览器端) ├── cordis.patch.yml # bundle patch:插入插件行 / bundle patch:插入插件行 └── test/ # 独立功能测试 + 客户端冒烟测试 / 独立功能测试 + 客户端冒烟测试开发过程中确认的关键事实 / Key facts discovered while building:
- 工具注册在 host 平面(该行位于 profile 组合中),因此所有 agent 都能看到(agent → preset → global)。工具注册在 host 平面(该行位于 profile 组合中),因此所有 agent 都能看到(agent → preset → global)。
- 浏览器端 bundle 无需前端重新构建:宿主直接服务 /plugins/dsh-git-worktree/client.js,启动图加载它即可。浏览器端 bundle 无需前端重新构建:宿主直接服务 /plugins/dsh-git-worktree/client.js,启动图加载它即可。
- 扩展客户端 RPC API(UNARY_VALUE_SCHEMAS)需要重新构建前端——这正是浏览器端改用普通 webServer 路由的原因。扩展客户端 RPC API(UNARY_VALUE_SCHEMAS)需要重新构建前端——这正是浏览器端改用普通 webServer 路由的原因。
- ctx.get('webServer') 在 apply 时是 undefined(异步初始化);应改用 ctx.inject(['webServer'], cb) 等待。无头(headless)profile 下工具仍可用,只是路由不会挂载。ctx.get('webServer') 在 apply 时是 undefined(异步初始化);应改用 ctx.inject(['webServer'], cb) 等待。无头(headless)profile 下工具仍可用,只是路由不会挂载。
- git 会用 realpath 规范化路径(例如 macOS 上 /var → /private/var);所有相等性判断都基于规范化形式。git 会用 realpath 规范化路径(例如 macOS 上 /var → /private/var);所有相等性判断都基于规范化形式。
- 会话 cwd 在创建时冻结(session.header.cwd 只读),工作区归属要求 cwd == 工作区路径——绑定只能发生在创建会话时,无法迁移已存在的会话。会话 cwd 在创建时冻结(session.header.cwd 只读),工作区归属要求 cwd == 工作区路径——绑定只能发生在创建会话时,无法迁移已存在的会话。
- git rev-parse --show-toplevel 在 linked worktree 内返回工作树根而非主仓库根;主工作树判定必须基于 --git-common-dir(主工作树路径 = common dir 的父目录)。主工作树路径是仓库根,因此 .dsh-wt/ 下的目录同时匹配主工作树和自身——取最长匹配。git rev-parse --show-toplevel 在 linked worktree 内返回工作树根而非主仓库根;主工作树判定必须基于 --git-common-dir(主工作树路径 = common dir 的父目录)。主工作树路径是仓库根,因此 .dsh-wt/* 下的目录同时匹配主工作树和自身——取最长匹配。
测试 / Tests sh
node test/run-all.js # 全部套件一次跑完(任一失败即非零退出)/ every suite, non-zero exit on failure
node test/unit-parse.js # 纯解析器:worktree/branch/status 输出(含 unborn、detached、prunable、ahead/behind、[gone])
node test/unit-git.js # git 运行器与路径助手:exit codes、abort、信号杀死、字节上限、cwd 分类
node test/test.js # 原功能测试:13 工具注册 + 路由处理器(bindings、unique 去重、绑定解析)
node test/tools-edge.js # 9 工具边界矩阵:遍历防护、detach/commitIsh/force、脏工作树、上游/远程、unborn 仓库、
外部路径工作树绑定、嵌套仓库、并发 unique 竞态、already-registered 去重、脏状态矩阵、 name-based 全新分支语义、info/exclude 本地忽略(空格/元字符/并发/既有字节)、同机占用守卫
node test/tasks.js # 4 任务工具:并行隔离启动/模型与策略继承、setup 成功/失败/超时/取消、权威完成判定、
cancel/teardown 释放、原子记录/重启调和/越权与损坏 id、顺序集成/冲突保留/验证重试
node test/routes-http.js # 真实 HTTP:方法校验(含 HEAD/OPTIONS)、坏 JSON/超大 body、空 repo 参数、+ 号编码、
严格 vs 宽容 notARepo、超时 abort;cwd 分支按实际值断言(独立 worktree 可移植)
node test/client-unit.js # 客户端纯函数:sanitizeName 边界(切片尾点、HEAD、代理对、check-ref-format 性质测试)、
sessionsSame、boundSessions 删除名单(同 cwd 全部会话/嵌套 cwd/别名/排除兄弟)、api() 错误映射
node test/client-smoke.js # 客户端 bundle 加载 + 当前服务接线(uiWorkspace.connectWorkspace/openSession)
node test/client-current.js # 当前 DSH 兼容回归:只请求存在的 slot、服务接线、行 DOM 集成生命周期、同名选择
node test/client-dom.js # jsdom 交互:自动同步(注册工作树/主工作树标记/失效清扫)、行级 DOM 注入
(repo + 新建工作树、工作树行 +/删除、非工作树回落、同名选择、卸载恢复)、
git 优先清理/失败重试/运行中会话停用;jsdom 全局先于 react-dom,意外 window/jsdom
错误由 test/jsdom-guard.js 记录并使套件非零退出(含隔离子进程自测)
node test/flows.js # 真实用户操作流:一键绑定会话、agent 准备/开发者打开、全生命周期、跨仓库、
unborn 仓库首绑、双工作树同名竞态
node test/schema-conformance.js # 工具输出 vs 声明 schema(harness 的 validateJsonSchemaValue 原样复放):
13 工具全部输出必须通过 additionalProperties:false 校验——防止遗漏 absolutePath / 可空 branch / 可空 worktree / 可空任务字段之类 schema 漂移在真实会话里炸掉
client-dom.js 与 client-current.js 需要 jsdom(插件本身不依赖它):从 DeepSeek Harness checkout 解析(DSH_HARNESS 指向其根目录,默认 /Users/aq/deepseek-harness),找不到时该套件自动跳过。KEEP_SCRATCH=1 可保留测试用临时仓库以便检查。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
KHG420/git-worktree
面向 DeepSeek Harness 的 对话 ↔ 工作树绑定…
相关插件 · 浏览器
智能体插件框架deepseek-ai/deepseek-harness
DeepSeek Harnessdsh是由 DeepSeek AI 开发的开源 agent harness智能体框架。
★ 270,422已汉化DSH
71.9
多设备 Agent 看板YaoApp/yao
✨ 所有 Agent 和工作区集中管理,覆盖你的每一台设备。任务看板追踪进度,桌面端、移动端、浏览器、API…
★ 8,147已汉化DSH
71.2
可扩展侧边栏工作台omdsh-dev/DSH-better-sidebar
DSH 的双工作台:原生右侧栏 + 自绘底部面板,并把 ctx.betterSidebar 服务开放给所有插件
★ 4,761已汉化DSH
71.1
浏览器自动化桥Tencent/BrowserSkill
你的 Agent。你的浏览器。连接,就能协作。
★ 9,967已汉化DSH
71
AI 小说创作工作台EthanYoQ/AI-Novel-Writer
AI 小说作家 / AI Novel Writer
★ 1,591已汉化DSH
70.7
智能体浏览器引擎platonai/Browser4
DeepSeek Harness 集成
★ 1,175已汉化DSH
70.4
这是你的仓库?认领条目