npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-git-lite

v0.4.0

Published

DSH 右侧栏(Web 与桌面版)的轻量 Git 面板,直接调用本机 git:改动、行内 diff、拉取、两阶段确认推送 / 发布分支、提交、分支(含远端)、上游对比、stash。A lite Git tab for the DeepSeek Harness sidebar, driven by your local git.

Readme

dsh-git-lite

DSH(DeepSeek Harness)右侧栏的轻量 Git 面板 —— Web 版与桌面版通用,直接调用你本机的 git,在侧边栏里看改动、行内 diff、拉取、推送、发布分支、提交、切分支、stash,不用切到终端。

A lite Git tab for the DeepSeek Harness sidebar, for both the web and desktop builds, driven by your local git: changes, inline diff, pull, push, publish branches, commit, branches and stash.

  • 轻量:只做基础 Git 操作,不做 DAG 图、不做交互式 rebase。
  • 原生行为:调用本机 git 二进制,遵守你的 ~/.gitconfig、hooks 和凭据配置,不另存 token。
  • 无依赖、无构建:纯 JS,dependencies 为空。
  • 面向 DSH 0.2.1-rc.2;Web 与桌面是同一套 Web 组合,所以同一份代码两边都能跑(差别只在装进哪个 profile,见「安装」)。

功能

| 类别 | 内容 | |---|---| | 查看改动 | 变更文件列表(状态码 M/A/D/R/? + 增删行数,按「冲突 / 已暂存 / 变更 / 未跟踪」分组,冲突组只在有冲突时出现且排最前),点任意文件看单栏行内着色 diff | | 提交历史 | 提交列表(短 sha、信息、refs 徽标、作者、时间,按日期分组)→ 点开看该提交完整 patch 与文件清单 → 再点文件看单文件 diff;「加载更早的 50 条」分页。历史顶部显示当前分支 ↔ 上游的关系(同步 / 领先 / 落后 / 已分叉),落后的远端独有提交单独成区列在最前,本地未推送的提交带「未推送」徽标 | | 同步 | 拉取(默认 --ff-only,分叉时明确拒绝而不是悄悄产生合并提交)、抓取(fetch --all --prune) | | 推送 / 发布 | 两阶段确认:先看将推送的分支 / 上游(或发布目标)/ ahead 数 / commit 列表,确认后才真正执行。没有上游的本地分支(新建分支,或远端分支被删)会走「发布分支」:推到 origin(没有 origin 时只有唯一 remote 才自动选),并建立 upstream | | 提交 | 暂存 / 取消暂存(可勾「全部暂存」);两条提交路径见下 | | 批量暂存 | 两个分组的标题右端各有一个动作:「变更 / 未跟踪」组头 = 全部暂存(git add -A)、「已暂存」组头 = 全部取消暂存(git restore --staged)—— 只动暂存区、不提交,且不额外占一行高度(代价:组头不是吸顶的,列表滚下去时会跟着滚走) | | 冲突 | 未解决冲突单独成一组排在列表最前(红色组头 + 文件行)。冲突行右侧是不可点的 !(不是 −/+:git add 会把冲突标记当成解决结果,而 − 正好会把它送进「变更」组拿到 +),详情区也不提供暂存 / 取消暂存。两条批量按钮同样都拒绝执行,唯一出路是「Agent 解决冲突」(只解决、不提交)。点开冲突文件能看到带 <<<<<<< 标记的差异;modify/delete 这类 git 不提供差异的冲突,面板会说明是哪种冲突以及两条出路。有冲突时**「提交」按钮也是禁用的** —— git 在存在未解决条目时一律拒绝提交 | | 分支 | 下拉按「本地 / 远端」分组;远端分支检出为本地跟踪分支(同名本地分支已跟踪别的远端时明确拒绝,不静默切换)。识别单分支克隆(remote 只抓了部分分支)并提示;工作区有冲突改动时给出明确提示 | | 储藏 | git stash push / git stash pop | | 入口 | 右侧栏「Git」标签页、工作区启动卡、以及会话头部右侧的分支胶囊(分支名 + 改动数 + ahead/behind) |

界面语言跟随 DSH 的 locale(中文 / English),配色取 DSH 设计令牌,因此明暗主题与第三方主题包自动跟随。

0.4.0 更新

  • 无上游分支可以发布:新建的本地分支、或远端分支被删后 upstream 还在([gone])时,推送按钮不再永久变灰,而是变成「发布分支」;预览后确认会创建远端分支并建立 upstream。
  • 远端选择不猜:origin 优先;没有 origin 时只有唯一 remote 才自动选;多个 remote 且没有 origin 会明确报错。upstream 已配置但引用被删时,沿用原来的 remote / 分支名重新发布。
  • 两阶段确认更完整:publish 预览额外核对远端与目标引用(防 TOCTOU),执行 git push --set-upstream,仍然没有任何 force 入口。
  • 预览里的提交列表上限 100 条,避免首次发布老仓库时把整部历史塞进弹层。
  • 测试:host 71 项、client 83 项。

从 0.3.0 升级不需要改配置;宿主半区有改动,重启应用即可。

0.3.0 更新

  • 远端分支可见:分支下拉按「本地 / 远端」分组,远端分支可直接检出为本地跟踪分支;同名本地分支已跟踪别的远端时明确拒绝,不静默切换。
  • 历史顶部显示上游关系:同步 / 领先 / 落后 / 已分叉;落后的远端独有提交单独成区,本地未推送提交带「未推送」徽标。
  • 外部 git fetch 也能跟上:面板轮询会比较 HEAD、分支、上游、远端引用与 ahead/behind,在终端里抓取后历史与对比会自动重载。
  • 抓取 / 拉取 / 推送 / 切分支 / 提交之后统一重载历史与对比;单分支克隆的 fetch 覆盖范围会在分支下拉与抓取提示里说明。
  • 提示行改为「一行成功摘要 + 可关闭的失败诊断块」。

从 0.2.x 升级不需要改配置;重启应用即可(宿主半区新增了只读的 /compare 路由)。

安装

profile 是分开的。 桌面版读 ~/.dsh/profiles/desktop,Web 版读 ~/.dsh/profiles/web。 装到哪个 profile,插件就只出现在哪个版本里 —— 装进 web 却去桌面版找「Git」标签页,是找不到的。

桌面 profile 由桌面应用独占管理:用 PATH 上的普通 dsh 跑 plugin --profile desktop 会被直接拒绝(error: profile "desktop" is managed exclusively by the Electron application)。 必须用桌面安装目录里的 CLI(<安装目录>\resources\runtime\cli\bin\dsh.cmd)—— 下面的脚本会自动找到它。 装/卸之前请完全退出 DeepSeek Harness(含托盘图标),装完再启动。

前置条件

  • DSH 0.2.1-rc.2。Web 版与桌面版跑的是同一套 Web 组合,所以两边行为一致;本版本已在 0.2.1-rc.2 的桌面版实测。 插件依赖官方右侧栏框架 @deepseek-ai/dsh-client-ui-sidebar-right 的 0.2.0 契约。
  • 本机有 git(面板直接调用它)。不需要 pnpm —— 桌面自带的 CLI 内含 pnpm。

桌面版(Windows)

# 1) 完全退出 DeepSeek Harness(含托盘图标)
# 2) 从源码链接安装:改完代码刷新页面即生效
.\install.cmd
# 3) 重新启动 DeepSeek Harness

install.cmd 只是 install.ps1 的薄包装。本机执行策略是 AllSigned,直接跑 .ps1 会报「未对文件进行数字签名」,包装脚本用进程级 -ExecutionPolicy Bypass 绕开。 想先看它到底要执行什么,加 -DryRun:

.\install.cmd -DryRun
# 桌面安装:E:\Application\DeepSeek Harness  (DSH 0.2.1-rc.2)
# CLI      :…\resources\runtime\cli\bin\dsh.cmd
# profile  :desktop  (C:\Users\<你>\.dsh\profiles\desktop)
# 安装源   :link:E:\Game\Pidan-Workshop\dsh-git-lite
# (DryRun)将执行:& '…\dsh.cmd' plugin --profile desktop add link:E:\…\dsh-git-lite

脚本不自己拼 profile 的加载器条目,而是把活交给官方 CLI:一个组合包(bundle) 要同时登记 profile 的 dependencies、dsh.profile.bundles 与 cordis.patch.yml 三处, 官方实现才是权威,手搓很容易半对半错(症状是标签页不出现、或出现两次)。

也可以完全手打(脚本做的就是这件事):

& "$env:ProgramFiles\DeepSeek Harness\resources\runtime\cli\bin\dsh.cmd" `
    plugin --profile desktop add link:E:\path\to\dsh-git-lite

Web 版

# 同版本的 dsh 在 PATH 上(npm i -g @deepseek-ai/[email protected])
dsh plugin --profile web add dsh-git-lite                    # npm 发布后
dsh plugin --profile web add /path/to/dsh-git-lite           # 本地目录
dsh plugin --profile web add link:/path/to/dsh-git-lite      # 链接安装,改完刷新即生效

桌面自带的 CLI 同样能装 web profile(它自带 pnpm,所以本机不需要另外装):

dsh.cmd plugin --profile web add dsh-git-lite

装完重启

重启 dsh web / DeepSeek Harness 后生效。然后打开右侧栏切到 Git 标签页, 或直接点会话头部右侧那个带分支名的胶囊。

卸载

.\uninstall.cmd                 # 桌面版
.\uninstall.cmd -Profile web    # Web 版

等价于 dsh plugin --profile <profile> remove dsh-git-lite。

版本不兼容会被拦下

package.json 对 @deepseek-ai/dsh-client-ui-sidebar-right 声明了 peer 范围 ^0.2.0-rc.2(DSH 的兼容闸门按 prerelease 解析,0.2.1-rc.2 能通过)。dsh 在安装时与每次启动时都会读它,运行时版本不满足会明确拒绝, 而不是让插件半死不活。确实要放行(自担崩溃与数据损坏风险):

dsh plugin --profile desktop allow-version [email protected] --dsh-version <精确运行时版本> --accept-risk

从 0.1.5-rc.2 升级

0.2.0 的客户端半区有两处不兼容,本版本已迁移;不支持 0.1.x,升级前请先卸载旧版:

| 旧写法(0.1.5) | 新写法(0.2.0) | |---|---| | sessions.list.getSnapshot().current 取会话 id | 席位标准套件下发的 props.sessionId | | sessions.binding(id).session.prompt(...) 发消息 | ctx.sessions.scope(id).get('conversation').send(text) |

前者的症状值得记一笔:sessions.list 还在,但它的 state 里已经没有 current, 于是旧代码拿到的永远是 undefined,面板发出的每个请求都缺 sessionId、宿主一律回 bad-request —— 不抛异常,表现为「面板一直加载不出东西」,极易被误判成宿主的问题。

使用

两条提交路径(本插件的核心区分)

「让 AI 写一条提交信息」和「让 agent 帮你提交」不是一回事:

① ✨ 生成信息 + 提交

宿主把 git status + git diff + 最近 10 条提交标题喂给模型,生成信息填进输入框,你改完再点「提交」。

  • 能看到:改了什么;看不到:为什么改(它没有对话上下文,只有 diff)
  • 快,且不消耗会话轮次

② 交给 Agent 提交

往当前会话投一条消息,由会话 agent 用完整对话上下文自己暂存、写信息、提交。

  • 与你在输入框里手打「提交一下」走的是同一条路径,信息质量与风格推断一致
  • agent 会自己看仓库既有风格再跟
  • 代价:异步、消耗一个会话轮次;提交过程作为普通一轮出现在会话日志里,可审计、可中断

怎么选:日常小改动用 ①;改动背后有「为什么」要说清楚时用 ②。

提交区三个按钮的顺序刻意是 ✨ 生成信息 → 交给 Agent 提交 → 提交:辅助动作在前, 你自己提交的按钮放最后(主操作靠右)。三个按钮各带说明浮层。

推送为什么要点两次

推送是面板里唯一会改动远端的操作,所以做成两阶段:

  1. 点「推送」→ 只返回预览:分支、上游、ahead 数、将要推送的 commit 列表。
  2. 你确认后才执行。确认时会校验 token 未用过、未过期,且 HEAD 与分支仍与预览时一致(防止预览之后仓库又变了)。

没有上游的分支(刚建的本地分支,或远端分支被删后 upstream 还在)按钮会变成 「发布分支」:预览显示目标远端、将创建的远端分支和提交列表;确认后执行 git push --set-upstream <remote> <branch>,一次完成「创建远端分支 + 建立 upstream」。 远端选择不猜:origin 优先,没有 origin 时只有唯一 remote 才自动选;多个 remote 且没有 origin 时明确报错,让你回终端指定。upstream 配置还在、但远端引用 已被 prune 的分支,会沿用原来的 remote / 分支名重新发布,不会悄悄改到别的目标。

另外,force push 在结构上不可能:普通推送只推当前分支到其上游;发布分支也只 带 --set-upstream 和一个显式 refspec,没有任何 force 入口。argv 由宿主内部构造, 客户端无法注入参数。

分支胶囊

会话头部右侧的胶囊显示当前分支、改动数、ahead/behind,点一下打开面板。

  • 会话目录不是 git 仓库时,胶囊显示为虚线弱化的「无仓库」(而不是静默消失 —— 那样分不清「没仓库」和「插件坏了」),鼠标悬停看原因。
  • 切会话时先清空再重新加载,所以不会把上一个会话的分支名短暂显示给你。

配置

全部可选。自定义 profile 的加载器条目时在 cordis.patch.yml 里给它加 config (桌面版是 ~/.dsh/profiles/desktop/cordis.patch.yml,Web 版是 .../web/...):

- insert:
    - id: git-lite
      name: dsh-git-lite
      inject: [webServer, sessions, workspaceRegistry]
      config:
        pullMode: ff-only        # ff-only(默认)| merge
        maxDiffBytes: 262144     # diff 返回上限,超出截断并标记
        confirmTtlMs: 120000     # push 确认 token 有效期(毫秒)
        messagePrompt: ''        # 覆盖「生成信息」用的 system prompt
        commitPrompt: ''         # 覆盖「交给 Agent 提交」注入的指令文本

用 dsh plugin add 装的话,条目由 bundle 自身的 cordis.patch.yml 提供; 上面这种写法是给"自己插加载器条目"的场景(例如已手工放进 node_modules 的包) 加配置用的。

插件页里的标题与描述

「设置 → 插件」页显示的标题与描述跟随界面语言(中文 / English),词典在 locale/en.json 与 locale/zh.json:

// locale/zh.json
{ "meta": { "title": "Git 面板", "description": "右侧栏的轻量 Git 面板,直接调用你本机的 git:…" } }

要给自己的 fork 再加一门语言,就往 locale/ 里再放一个 <语言 id>.json (例如 ja.json),字段同为 meta.title / meta.description。两条硬性要求:该文件必须靠 package.json 的 exports 放行("./locale/*.json")并且写进 files —— 否则 dsh 会静默退回成「显示裸包名、没有描述」,本地用 link: 开发时完全看不出问题。

常见问题

右侧栏没有「Git」标签页? 按顺序查三件事:

  1. 装到哪个 profile 了? 桌面版读 desktop,Web 版读 web,两者互不相通。 查 ~/.dsh/profiles/<profile>/package.json 的 dsh.profile.bundles 里有没有 dsh-git-lite。
  2. 重启过应用吗? 装/卸都需要重启才生效。
  3. 启动被告知版本不兼容了吗? package.json 的 peer 范围是 ^0.2.0-rc.2(prerelease 会被放行,0.2.1-rc.2 不受影响); 运行时不是 0.2.x 时 dsh 会明确拒绝加载,而不是静默。按 README「版本不兼容会被拦下」处理。

胶囊一直是灰色「无仓库」? 说明该会话的目录确实不是 git 仓库,或不在已注册工作区里。悬停看 tooltip,具体原因有四类: no-workspace(没有工作目录或目录已不存在)、workspace-unknown(不在任何工作区里)、 not-a-repo(目录链上没有 .git)、outside-workspace(仓库根在工作区之外)。 这不是插件故障 —— 而是如实告诉你这里没有仓库可用。

面板一直加载不出东西,或提示 sessionId is required? 那是 0.2.0 之前「拿不到会话身份」的症状。本版本已改为从席位标准套件取 props.sessionId;若你在自己的 fork 里看到它,说明回退到了读 sessions.list.current 的旧写法(该字段在 0.2.0 已被移除)。npm test 里有一条回归闸门专门钉这个。

拉取报分叉错误? 默认 pullMode: ff-only,本地与远端各有提交时会拒绝而不是替你造一个合并提交。 想让它自动合并,把 pullMode 改成 merge,或回终端处理。

推送/拉取提示凭据错误? 面板在无终端的 web 进程里运行,缺凭据时会立刻失败而不是挂住等输入。 先在本机终端里对该仓库跑一次 git push,让凭据助手记好,再回面板操作。

改了代码什么时候要重启? 改了 lib/index.js(宿主半区)必须重启应用;只改 lib/client.js(浏览器半区) 刷新页面即可;两者都改就重启 + 刷新。

开发

纯 JS,无构建步骤。宿主半区 lib/index.js,浏览器半区 lib/client.js。

node --check lib/index.js
node --check lib/client.js
npm test                      # host 冒烟 71 项 + client 冒烟 83 项

两个冒烟测试都不需要 DSH 运行时,但 host 冒烟会真的调用本机 git(resolveRepo 的仓库解析用例),所以需要一个能正常 spawn 子进程的环境。

Windows 检出注意:仓库里按 .editorconfig 存的是 LF,而 core.autocrlf=true 会把它检成 CRLF。以前有几条用例硬编码了 \n 与 POSIX 的 /tmp,在 Windows 上会 假红;现在 client 冒烟先归一化行尾,host 冒烟用 os.tmpdir() 当"存在但不是仓库" 的样本,两个平台都能过。

设计取舍、安全模型细节、以及真机迭代踩过的坑(含每个 bug 的根因与回归测试), 都在 docs/DESIGN.md (npm 页面上相对链接会失效,所以这里用绝对地址)。

安全

  • 工作目录由宿主解析:客户端只发 sessionId,不传路径。目录要依次通过 realpath 解析、 已注册工作区校验、以及「git 仓库根仍在该工作区内」三道闸门,所以不存在「让宿主在任意目录跑 git」这条路。
  • 参数由宿主构造:argv 一律以数组传给 execFile,绝不由客户端拼接,不存在 shell 注入面; 路径参数拒绝绝对路径与 .. 逃逸,分支名以 - 开头直接拒绝。
  • 推送 / 发布分支需二次确认,且 force push 结构上不可能。

License

MIT © Pidan Workshop