🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

Git 可视化工作面板 Dayi-Z/dsh-git-manager

DeepSeek Harnessv2.0.0
Dayi-Z48 天前有提交已提供中文文档扫描:含敏感能力

连接 GitHub 的可视化 Git 面板。

29.7/100
综合分
0
GitHub 星标
259
npm 周下载
—/5
用户评分

数据截至 2026/9/20 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-git-manager
npm 源 · dsh-git-manager 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · market
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
数据截至 2026/10/23·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 48 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-git-manager @ 2.0.0
✓Node 引擎要求 ^22.19 || >=24 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/9/21 23:54:19

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 90 处,展示前 66 条)
  • 执行外部命令固定命令
    lib/index.js:31
    const child = spawn("powershell", [
  • 写入本地文件
    lib/index.js:70
    mkdirSync(STORAGE_DIR$1, { recursive: true });
  • 写入本地文件
    lib/index.js:83
    writeFileSync(tmp, cipher, "utf8");
  • 写入本地文件
    lib/index.js:85
    chmodSync(tmp, 384);
  • 写入本地文件
    lib/index.js:87
    renameSync(tmp, TOKEN_FILE);
  • 读取本地文件
    lib/index.js:90
    if (!existsSync(TOKEN_FILE)) return null;
  • 读取本地文件
    lib/index.js:92
    const raw = readFileSync(TOKEN_FILE, "utf8").trim();
  • 删除本地文件
    lib/index.js:101
    unlinkSync(TOKEN_FILE);
  • 执行外部命令固定命令
    lib/index.js:106
    const child = spawn("gh", args, {
  • 请求外部主机github.com
    lib/index.js:160
    const res = await fetch("https://github.com/login/device/code", {
  • 发起网络请求
    lib/index.js:160
    const res = await fetch("https://github.com/login/device/code", {
  • 请求外部主机github.com
    lib/index.js:185
    const res = await fetch("https://github.com/login/oauth/access_token", {
  • 发起网络请求
    lib/index.js:185
    const res = await fetch("https://github.com/login/oauth/access_token", {
  • 请求外部主机api.github.com
    lib/index.js:233
    const res = await fetch(`https://api.github.com${path}`, {
  • 发起网络请求
    lib/index.js:233
    const res = await fetch(`https://api.github.com${path}`, {
  • 执行外部命令固定命令
    lib/index.js:272
    const child = spawn("gh", args, {
  • 读取本地文件
    lib/index.js:1316
    text = await readFile(gi, "utf8");
  • 写入本地文件
    lib/index.js:1323
    await writeFile(gi, next, "utf8");
  • 读取本地文件
    lib/index.js:1338
    canonicalParent = await realpath(parent);
  • 读取本地文件
    lib/index.js:1352
    if (existsSync(join(target, ".git"))) throw Object.assign( new Error(`目标目录已存在仓库:${target}`), { gitError: {
  • 读取本地文件
    lib/index.js:1633
    info = await stat(join(canonical, name));
  • 执行外部命令固定命令
    lib/index.js:2011
    const child = spawn("git", [
  • 写入本地文件
    lib/index.js:2347
    mkdirSync(STORAGE_DIR, { recursive: true });
  • 发起网络请求
    lib/index.js:3520
    const modalPromise = approval ? approval.request({
  • 发起网络请求
    src/client/api.ts:9
    const res = await fetch(path, {
  • 发起网络请求
    src/client/api.ts:122
    fetch(path: string): Promise<OpResult> { return call('/gitm/fetch', { path }) }
  • 读取本地文件
    src/host/activity.ts:64
    try { return statSync(p).isDirectory() } catch { return false }
  • 读取本地文件
    src/host/activity.ts:80
    if (existsSync(abs)) return { abs, dir: isDir(abs) ? abs : dirname(abs) }
  • 读取本地文件
    src/host/activity.ts:86
    if (existsSync(cur)) return { abs, dir: isDir(cur) ? cur : dirname(cur) }
  • 读取本地文件
    src/host/git-root.ts:29
    if (existsSync(join(current, GIT_MARK))) return current
  • 读取本地文件
    src/host/git-service.ts:466
    try { text = await readFile(gi, 'utf8') } catch { }
  • 写入本地文件
    src/host/git-service.ts:471
    await writeFile(gi, next, 'utf8')
  • 读取本地文件
    src/host/git-service.ts:479
    try { canonicalParent = await realpath(parent) } catch {
  • 读取本地文件
    src/host/git-service.ts:488
    if (existsSync(join(target, '.git'))) {
  • 读取本地文件
    src/host/git-service.ts:629
    info = await stat(join(canonical, name))
  • 读取本地文件
    src/host/git-service.ts:637
    const text = await readFile(join(canonical, name), 'utf8')
  • 执行外部命令固定命令
    src/host/git-service.ts:812
    const child = spawn('git', ['cat-file', 'blob', spec], { cwd: canonical, windowsHide: true })
  • 读取本地文件
    src/host/git-service.ts:929
    afterText = await readFile(join(canonical, name), 'utf8')
  • 执行外部命令固定命令
    src/host/github-auth.ts:37
    const child = spawn('powershell', ['-NoProfile', '-NonInteractive', '-Command', script], {
  • 写入本地文件
    src/host/github-auth.ts:81
    mkdirSync(STORAGE_DIR, { recursive: true })
  • 写入本地文件
    src/host/github-auth.ts:98
    writeFileSync(tmp, cipher, 'utf8')
  • 写入本地文件
    src/host/github-auth.ts:99
    try { chmodSync(tmp, 0o600) } catch { }
  • 写入本地文件
    src/host/github-auth.ts:100
    renameSync(tmp, TOKEN_FILE)
  • 读取本地文件
    src/host/github-auth.ts:104
    if (!existsSync(TOKEN_FILE)) return null
  • 读取本地文件
    src/host/github-auth.ts:106
    const raw = readFileSync(TOKEN_FILE, 'utf8').trim()
  • 删除本地文件
    src/host/github-auth.ts:115
    try { unlinkSync(TOKEN_FILE) } catch { }
  • 执行外部命令固定命令
    src/host/github-auth.ts:124
    const child = spawn('gh', args, { windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] })
  • 请求外部主机github.com
    src/host/github-auth.ts:169
    const res = await fetch('https://github.com/login/device/code', {
  • 发起网络请求
    src/host/github-auth.ts:169
    const res = await fetch('https://github.com/login/device/code', {
  • 请求外部主机github.com
    src/host/github-auth.ts:192
    const res = await fetch('https://github.com/login/oauth/access_token', {
  • 发起网络请求
    src/host/github-auth.ts:192
    const res = await fetch('https://github.com/login/oauth/access_token', {
  • 请求外部主机api.github.com
    src/host/github-service.ts:27
    const res = await fetch(`https://api.github.com${path}`, {
  • 发起网络请求
    src/host/github-service.ts:27
    const res = await fetch(`https://api.github.com${path}`, {
  • 执行外部命令固定命令
    src/host/github-service.ts:58
    const child = spawn('gh', args, { windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] })
  • 读取本地文件
    src/host/repo-store.ts:37
    if (!existsSync(SHELF_FILE)) { cache = []; return cache }
  • 读取本地文件
    src/host/repo-store.ts:39
    const rawText = readFileSync(SHELF_FILE, 'utf8').replace(/^ FEFF/, '')
  • 写入本地文件
    src/host/repo-store.ts:59
    mkdirSync(STORAGE_DIR, { recursive: true })
  • 写入本地文件
    src/host/repo-store.ts:61
    writeFileSync(tmp, JSON.stringify(load(), null, 2), 'utf8')
  • 写入本地文件
    src/host/repo-store.ts:62
    renameSync(tmp, SHELF_FILE)
  • 读取本地文件
    src/host/routes.ts:77
    await access(join(workspace.path, GIT_MARK))
  • 读取本地文件
    src/host/routes.ts:84
    await access(join(repo.path, GIT_MARK))
  • 读取本地文件
    src/host/routes.ts:193
    try { canonical = await realpath(p) } catch { throw Object.assign(new Error('路径不存在'), { gitError: { code: 'bad-request', message: 'path not found' } }
  • 读取本地文件
    src/host/routes.ts:209
    shelfRemove(await realpath(p).catch(() => p))
  • 读取本地文件
    src/host/routes.ts:438
    const canonical = await realpath(r.path)
  • 读取本地文件
    src/index.ts:39
    canonical = await realpath(path)
  • 发起网络请求
    src/tools.ts:97
    ? approval.request({
扫描于 2026/11/4(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
涉及外部主机:github.com、api.github.com

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-runtime@deepseek-ai/dsh-client-ui-slots@deepseek-ai/dsh-host-webserver@deepseek-ai/dsh-subprocess@deepseek-ai/dsh-tools@deepseek-ai/dsh-workspace
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 连接GitHub
  • 分支切换
  • 文件级审批卡片
展开完整介绍(68 字)↓

连接 GitHub 的可视化 git 面板,给 DeepSeek Harness 用:分支切换、文件级审批卡片、PR/issue 工作区

v2.0.02026-09-17
连接 GitHub 的可视化 git 管理器,用于 DeepSeek Harness。从 gitcompass 改名而来;修复了 Cordis 服务代理上的配置访问问题(apply(ctx, config))。提供预构建 tarball,免构建安装。
v1.6.32026-08-29
· gitcompass v1.6.3 一个连接 GitHub 的可视化 git 面板,用于 DeepSeek Harness,日常 git 工作流所需功能现已齐全。 · 亮点 · Trae 风格改动页:顶部提交框、状态字母、树形/平铺视图、彩色文件类型图标、出站改动卡片可逐层下钻(提交 → 文件 → 补丁) · 冲突条:合并/变基进行中 → 按文件选择保留我方/对方、中止、继续变基 · 安全网:撤销上次提交(软撤销)、修补、stash 列表支持逐条应用/丢弃 · 智能体集成:文件级审批卡片、会话预审批标签可撤销、待审批标签页角标、实时 SSE 推送 · gh-channel 推送:github.com:443 不可达时通过 GitHub REST 重建提交;推送后同步本地跟踪引用 · 自愈客户端:检测到 bundle 版本过期自动重载(每个版本只重载一次) · P1 功能集:pull --rebase 开关、标签(创建/删除/推送)、.gitignore 快速添加、图谱过滤、克隆到暂存架、设置(语言/轮询速度) · 行级 diff 着色、SVG 图标系统、双语(中/英)、深色/浅色主题 · 安装 dsh plugin add Dayi-Z/gitcompass 需要 Node 22.19+、dsh >= 0.1.0-rc.6。
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
dsh-git-manager DeepSeek Harness 的 GitHub 可视化 Git 管理插件——引导式 GitHub Flow 流程、GitLens 风格提交图谱(带 PR/CI 徽章)、一键 GitHub 登录,以及为 Agent 提供的结构化 Git 操作工具。 面板的呈现方式与 dsh-better-sidebar 同源:每一个颜色、字号角色与动效值都走 DSH 主题令牌;界面是平面的(发丝边框 + 悬停底色,流内没有阴影);纯图标按钮是圆形、透明底、悬停才浮出。明暗主题与任何 dsh-web-ui 皮肤都能直接重绘这个面板——面板内部没有自己的调色板,也没有主题选择器。详见 DESIGN.md。 2.0.0 起由 gitcompass 改名而来:包名、插件行 id(dsh-git-manager)、HTTP 路由(/gitm/)与 CSS 前缀(--gm-)一并迁移。模型侧的工具名(git_status、git_commit、github_pr_ 等)刻意保持不变——它们命名的是操作,不是产品。 功能特性 - 引导流程条(顶部):可视化展示 GitHub-Flow 六个阶段:分支 → 提交 → 推送 → PR → 评审 → 合并。 - 分支管理:查看本地/远程分支、切换、新建、删除、重命名、合并、拉取、检出远程分支。
展开完整文档(README 剩余 1 节)
dsh-git-manager

DeepSeek Harness 的 GitHub 可视化 Git 管理插件——引导式 GitHub Flow 流程、GitLens 风格提交图谱(带 PR/CI 徽章)、一键 GitHub 登录,以及为 Agent 提供的结构化 Git 操作工具。

面板的呈现方式与 dsh-better-sidebar 同源:每一个颜色、字号角色与动效值都走 DSH 主题令牌;界面是平面的(发丝边框 + 悬停底色,流内没有阴影);纯图标按钮是圆形、透明底、悬停才浮出。明暗主题与任何 dsh-web-ui 皮肤都能直接重绘这个面板——面板内部没有自己的调色板,也没有主题选择器。详见 DESIGN.md。

2.0.0 起由 gitcompass 改名而来:包名、插件行 id(dsh-git-manager)、HTTP 路由(/gitm/)与 CSS 前缀(--gm-)一并迁移。模型侧的工具名(git_status、git_commit、github_pr_ 等)刻意保持不变——它们命名的是操作,不是产品。

功能特性

- 引导流程条(顶部):可视化展示 GitHub-Flow 六个阶段:分支 → 提交 → 推送 → PR → 评审 → 合并。
- 分支管理:查看本地/远程分支、切换、新建、删除、重命名、合并、拉取、检出远程分支。
- 变更视图:文件状态(已暂存/未暂存/未跟踪)、暂存/取消暂存、提交、Diff 查看(点击文件查看变更)、贮藏/弹出、推送、拉取、抓取。
- 提交图谱(GitLens 风格 Lane 布局):三栏(列 / SHA / 主题),PR 徽章,cherry-pick 到当前分支,撤销提交。
- PR 管理:列出 PR、查看详情(检查、评审、评论)、创建 PR、Squash 合并、评审(通过 / 请求修改 / 评论)、添加评论。
- 议题(Issues):列出议题、查看详情、创建新议题、添加评论。
- GitHub 集成:设备流 OAuth 登录、PAT 输入、复用 gh CLI、加密 Token 存储(Windows DPAPI)。
- 结构化 Git 工具(Agent 侧):git_status、git_diff、git_branches、git_commit、git_push、github_pr_list/read/create/merge/comment/review、github_issue_list/read/create/comment。
- Agent 活动监视器:实时 SSE 事件流展示 Agent 正在执行的每次工具调用(开始/完成/失败),仓库观察器轮询捕获面板外的 bash git 操作(新提交 / 切换分支 / 工作区变更)。
- 面板内审批(面板权威):Agent 的写操作在面板中弹出审批卡片,可直接批准或拒绝;与 DSH 原生弹窗并行竞速,先到者生效。原生通道的自动拒绝(包括 approval policy 为 never 时的 ghost deny,例如 danger-full-access 预设自带 never)不能否决面板卡——任何审批策略下写操作都能走面板审批。面板决定一次性有效且不落盘;无面板在线时快速失败并提示打开面板(或先在面板中预批准),不再静默挂死。
- 多语言:自动跟随 DSH Web 界面语言(中文 / 英文)。
- 主题:面板不带自研调色板,颜色全部来自宿主主题令牌,因此明暗与第三方皮肤都能生效。
- 两种宿主形态:装了 dsh-better-sidebar 时,面板把自己注册成它的一个页签并把右栏让给它;没装时保留自己的右栏卡片,且可折叠。详见下文。

安装

dsh plugin --profile web add dsh-git-manager

本地开发:

dsh plugin --profile web add link:/path/to/dsh-git-manager

重启 dsh web,打开一个绑定 git 仓库的会话,右侧面板即显示「Git 管理」。

架构

src/
index.ts # Cordis 插件入口:注册路由 + 工具 + 系统提示词 tools.ts # Agent 侧结构化 git/GitHub 工具(写操作审批竞速) core/types.ts # 共享类型定义 host/ git-service.ts # 以工作区为边界的 git 操作服务 routes.ts # /gitm/ HTTP 路由(含 SSE 事件流 /gitm/events、审批端点) event-bus.ts # 内存事件总线 + 预批准表 + 面板审批 Broker + 仓库观察器 github-service.ts # GitHub REST 封装(Token 不离开宿主进程) github-auth.ts # 设备流、DPAPI Token 加密存储、gh CLI 同步 client/ index.ts # 浏览器端入口:选择宿主(better-sidebar 页签 / 独立卡片) embed.tsx # better-sidebar 页签注册(结构化类型,可选 peer) shell.tsx # 独立宿主:可折叠的右栏卡片 Panel.tsx # 主面板:分支 / 变更 / 图谱 / PR / 议题 / GitHub / Agent styles.ts # 全部样式,建立在宿主主题令牌之上(见 DESIGN.md) api.ts # /gitm/* 路由的类型化 Fetch 封装 events.ts # SSE 订阅 + 页签角标共用的共享事件存储 i18n.ts # 中英文双语词典 icons.tsx # 图标唯一来源(16px 网格、1.5 笔重内联 SVG)
graph.ts # 提交 DAG Lane 布局算法

宿主形态

面板不抢占宿主已经拥有的表面:

- 装了 dsh-better-sidebar —— 面板注册成它的一个侧栏页签(dsh-git-manager:panel,标题「Git 管理」,单实例幂等),不再自己挂右栏。从侧栏的「新建页签」列表里打开,之后随会话持久化。页签上带实时角标:当前有多少个写操作在等你批准。
- 没装 dsh-better-sidebar —— 面板保留自己的右栏卡片,头部多一个收起把手。收起后只剩头部条,并停止全部轮询(不会在后台继续打 git),状态落 localStorage。

探测是运行时的(ctx.get('betterSidebar')),所以 better-sidebar 始终只是可选 peer:没有硬依赖、构建期不 import 它的类型;注册失败也只降级成独立卡片,不会把面板弄丢。也可以用 localStorage['gm.host'] = 'dock' | 'tab' 手动覆盖(默认自动)。

面板还会跟随所属会话的工作区:先取宿主给的 scope.cwd,没有就用"当前选中的会话";你切换会话时它自动切到对应仓库——没见过的仓库会先自动收录(宿主会向上找到最内层的仓库根,所以会话停在一个嵌套仓库里时,选的是那个仓库而不是包着它的工作区)。绝不覆盖你手动选的仓库。

什么算"我正在改的文件夹"

会话的工作区往往只是个容器——D:\Harness 里套着十几个独立仓库——只看会话 cwd 永远不知道你此刻在动哪一个。所以宿主还盯着 tools/execute:取文件类工具(read / write / edit / grep / glob 等)的路径参数,向上找到所属仓库根,把它自动收进下拉框。还不存在的文件也算——观测发生在工具执行之前,write 新建文件恰恰是最该被看见的那一类活动。

- 自动收进来的条目标了 auto,下拉框里显示成 名字 · 自动:货架自己长了要看得见,才不会变成一件玄学。
- 自动条目上限 20 条,超了淘汰最旧的自动条目;手动收录的一条都不会动。
- 每收一条就往活动流里发一条 repo:auto-added。
- 想关掉:在插件那一行加 config.autoRegisterRepos: false——下面的悬挂条仍会显示正在动什么。

下拉框下面常驻一条两行悬挂提示,两个问题一眼可答:

会话文件夹 D:\Harness 正在修改 D:\Harness\dsh-learn-wiki

第一行是面板跟随的会话文件夹,第二行是 agent 此刻在动的文件夹(写类工具显示「正在修改」,只读类显示「正在读取」)。当第二行是个已收录、但不是当前选中的仓库时,旁边会出现一个切过去按钮。

开发

pnpm install
pnpm run build

构建产物:lib/(宿主端)和 client/(浏览器端 bundle)。

node scripts/test-activity.mjs # 文件活动自动收录(在临时 home 下跑,不碰真实货架)

许可证

MIT
预览分享卡片长什么样 ↓Dayi-Z/dsh-git-manager
分享 · DeepSeek Harness Hub
Dayi-Z/dsh-git-manager

连接 GitHub 的可视化 Git 面板。

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部