Skip to content

Latest commit

 

History

358 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ohmydsh

DeepSeek Harness(DSH)的声明式定制仓 —— 一份 manifest 管理全部定制,幂等物化到 ~/.dsh

CI License: MIT Node.js Conventional Commits PRs Welcome

English · 快速开始 · 架构 · 贡献 · 安全 · 更新日志


本仓库是 DSH(DeepSeek Harness)的定制仓:总配置统一管理,各项定制可插拔、独立版本、独立维护,但都在同一仓库内

为什么需要它

手工维护 AI agent 运行时的插件、版本和配置很容易变成一堆"改过但没人记得为什么"的本地状态。ohmydsh 用一份声明式 manifest 把这些收敛成可复现、可审查、可回滚的工程资产:

  • 🎛 单一开关面 —— dsh.yaml 管住 DSH 版本、第三方插件、自研 package、patch、skill 与环境级指令。
  • 🔁 幂等物化 —— dsh build 把仓库状态同步到 ~/.dsh,重复执行结果一致,失败 fail closed。
  • 🔌 可插拔 —— 每项定制独立启用、禁用、升级、移除;enabled: false ≠ 删除。
  • 📌 精确 pin,不 vendor —— 第三方只存版本 pin、覆盖片段与审查记录,信任面清晰可查。
  • 🚀 自动跟版 —— autoUpdate 检测新版 DSH 后阻塞式升级、重跑 sync 并自动提交,工作区不干净时不动手。
  • 📐 规范驱动 —— 行为变化先过 OpenSpec(proposal → design → spec → tasks),再落实现。

真相源约定

  • 仓库是唯一真相源dsh.yaml + 各定制目录 + instructions/dsh-home.md = 完整配置;~/.dsh 是物化产物。
  • package-lock.json 是全部 npm workspace 的唯一依赖锁;TypeScript local package 只提交 src/,gitignored lib/ 由根 build/sync 生成。
  • cordis.patch.yml、presets/skills 与 $DSH_HOME/AGENTS.md 都应从仓库修改后重新 sync。AGENTS.md 有 ownership/hash 漂移防护:发现未托管文件或本地改动时会报错并保留,不会静默覆盖或删除。
  • OpenSpec checking 长期只提交报告、trail、gate、复现脚本或显式审核的 test fixture;raw history/baseline 和批量截图应放外部 artifact,或在报告中声明仅临时留存。
  • 提交前运行 npm testnpm run check:artifacts,防止生成产物、nested lock、raw evidence 或重复架构图进入 Git。
  • 禁用 ≠ 删除:enabled: false 只表示不物化,仓库内容保留,随时可重新启用。

目录结构

dsh.yaml                  # 总配置(唯一开关面)
BACKLOG.md                # 想法池
openspec/                 # spec-driven 变更流程
scripts/bootstrap.sh       # clone 后初始化:检查 Node 环境 + 安装依赖(幂等)
scripts/install.sh         # 一键安装:bin/dsh → ~/.local/bin(幂等,可卸载)
scripts/sync.mjs          # manifest → ~/.dsh 物化
instructions/dsh-home.md  # 工作环境级模型指令源文件
packages/<name>/          # 自研 bundle 插件(见 packages/README.md)
presets/<id>/             # agent preset(见 presets/README.md)
patches/<id>.yml          # 纯 composition 片段 / 对 remote 包的覆盖(见 patches/README.md)
skills/<name>/            # skill(见 skills/README.md)
docs/notes/               # 可长期检索的问题与决策记录
tests/                    # sync 黑盒回归测试

架构图

ohmydsh 架构图:仓库真相源 → sync 物化 → ~/.dsh → DSH 运行时

展示资产为 archify-out/ohmydsh-architecture.dual.svg(单文件,自带明暗主题适配); 可编辑图源为 archify-out/ohmydsh-architecture.json,架构变化时更新图源并重新导出该 SVG。

使用

从零开始(clone 以后到能用的完整流程;macOS / Linux / WSL / Git Bash 通用,bin/dsh 是 bash 脚本,Windows 原生不支持):

git clone <仓库地址> && cd ohmydsh
./scripts/bootstrap.sh     # ① 初始化:检查 Node 环境 + 安装依赖(只需一次,幂等)
./scripts/install.sh       # ② 安装 dsh 命令到 ~/.local/bin
dsh build && dsh           # ③ 物化定制配置并启动,UI 自动打开
  • 前置要求:Node.js >= 22 + npm >= 10(推荐 .nvmrc 中的版本);根 package.jsonengines 声明最低版本,bootstrap 只在低于最低版本时报错,更高版本仅提示不阻塞;
  • 依赖出问题想重装:./scripts/bootstrap.sh --force;
  • install.sh 默认装到 ~/.local/bin/dsh(想换目录:DSH_BIN_DIR=/opt/bin ./scripts/install.sh);重复执行可覆盖更新,不影响 ~/.dsh 物化产物;
  • 装的是相对符号链接,仓库整体移动后命令依然可用,无需重装;
  • ~/.local/bin 不在 PATH,脚本会打印各 shell(bash/zsh)的配置提示;
  • 卸载:./scripts/install.sh uninstall;
  • 跳过脚本?在仓库根执行等价的原始命令也行:
    ln -s "$PWD/bin/dsh" "$HOME/.local/bin/dsh"

快速上手(命令已装好;还没装?先看上面「从零开始」):

dsh build   # 1. 首次:按 dsh.yaml 把定制物化到 ~/.dsh(改了配置后也要重跑)
dsh         # 2. 启动:自动在后台拉起(是否就绪后自动打开 UI 由 web.open 决定,默认开;本仓库默认关)
dsh stop    # 3. 停止服务
  • 想一步到位?"构建 + 启动"用 dsh -b;
  • 启动后 UI 在 **http://127.0.0.1:3080**(换端口:`dsh -p 8080`);
  • 每次启动/停止,终端都会打印当前加载的插件清单,一眼看清生效了哪些定制;
  • 重复执行 dsh 不会起第二个实例:已在运行就只是帮你把 UI 打开。

日常命令(按场景查):

场景 命令 说明
启动 dsh 未运行 → 后台拉起 + 打开 UI;已运行 → 打开 UI;UI 也已打开 → 提示"已在运行"。UI 打开策略:显式 DSH_OPEN_APP(PWA/应用)优先;未配置时自动探测已安装的 DeepSeek Harness PWA,命中即只开 PWA;否则浏览器。dsh.yamlweb.open: false(本仓库默认)则不自动打开,需要时 dsh --open
构建 + 启动 dsh -b 改过 dsh.yaml 或插件后,先重新物化再启动
只构建 dsh build 只把配置物化到 ~/.dsh,不启动
停止 dsh stop 按监听端口验证并停掉 DSH server,同时关闭 PWA 与 Chrome 中同端口的 DSH 标签;非 DSH 进程占端口时拒绝误杀
重启 dsh restart 停 server → 关闭全部 UI → 确认端口释放 → 启动 server → 按 web.open 只打开 PWA(存在时),一步到位
看历史 dsh history 历次启动的时间 / DSH 版本 / 端口 / 插件清单(记录在 ~/.dsh/dsh-startup.log)
一键清空定制 dsh reset 移除自定义插件、preset、skill,并安全撤销托管的 $DSH_HOME/AGENTS.md(反悔了?dsh build 就能恢复)
统一升级插件 dsh plugin-update 检测远端插件新版本(兼容性/稳定性判定)→ 逐条确认 → 改 dsh.yaml + sync + 自动提交;--dry-run 只预览,--yes 跳过确认;needs-review 条目永远等人工
调试 dsh --foreground 前台运行,日志直接打在终端
换端口 dsh -p 8080 默认 3080
不弹 UI dsh --no-open 启动/检测时不自动打开 UI(优先级最高;dsh --open 反方向强制打开)

小知识:"build" 就是按 dsh.yaml 物化到 ~/.dsh(即 node scripts/sync.mjs,幂等可重跑);DSH_HOME 未设置或只含空白时默认 ~/.dsh,也支持 DSH_HOME=~/...;DSH 版本单一来源是 dsh.yamldshVersion,启动时动态读取。

自动升级 DSH 运行体(autoUpdate,默认开):

  • dsh(未运行)/ dsh -b / dsh build / dsh restart 前置会检测 @deepseek-ai/dsh 在 registry 目标频道(latestnext)的最新版本;低于最新即阻塞式自动升级再继续:改 dsh.yamldshVersion + 同族 @deepseek-ai/dsh-* pin → 重跑 sync 物化 → git commit --no-verify(chore(dsh): auto-bump <旧> → <新>)→ 再启动;
  • 只会自动改写名字匹配 @deepseek-ai/dsh-* 且 pin 等于旧运行体的条目,第三方插件与刻意钉住的其他版本不动;改写前留 dsh.yaml.bak,sync 失败即从备份回滚并报错不启动;
  • 前提是工作区干净:仓库有未提交改动时不升级,输出会说明原因(提交后下次启动自动跟上);检测失败/离线时按当前版本继续,不阻塞;
  • 逃生门 & 频道:想钉在旧版,dsh.yamlautoUpdate.enabled: false 或临时 DSH_SKIP_UPDATE=1 dsh;追 next(前夜版)用 DSH_UPDATE_CHANNEL=next dsh(或改 autoUpdate.channel);
  • 升级/跳过/离线事件记录在 ~/.dsh/dsh-startup.log,dsh history 可见。

临时 rc.2 运行体防卡死策略(默认启用):

  • @deepseek-ai/dsh@0.1.1-rc.2 已有精确版本的 npx 或 ohmydsh pnpm 缓存时,启动、build 和官方 CLI 都直接执行缓存入口,不重复运行 npx 计算预发布 peer 依赖;
  • 两级缓存都缺失时,rc.2 默认跳过已观察到可能长期卡死的 npm/libnpmexec 通道,改用有超时、临时 staging 和完整性校验的 pnpm 固定缓存;失败不会换用其他 DSH 版本,也不会覆盖已有可用缓存;
  • 仅用于隔离诊断或验证上游修复时,可单次运行 DSH_ALLOW_NPX_PROVISION=1 dsh ... 恢复 npx-first,但仍受超时保护;它与只控制版本检测的 DSH_SKIP_UPDATE=1 含义不同;
  • dsh stop 始终只做本地进程/UI 清理,不触发 npm/npx/pnpm。临时策略的删除 gate:隔离冷 npx install、连续 build、重复 restart 均能在超时内稳定通过后,删除 scripts/lib/dsh-cli.mjs 中唯一的 rc.2 策略项及对应测试。

UI 打开方式(web.open 开关 + DSH_OPEN_APP 选目标,不用改 shell 配置):

  • 默认:就绪后自动打开,目标=系统默认浏览器打开 http://127.0.0.1:3080;
  • 不想自动弹任何 UI:dsh.yamlweb.open: false(本仓库默认关)后 dsh build,或临时 dsh --no-open;需要时 dsh --open 强制打开;
  • 官方 dsh web 自身默认也会打开浏览器;ohmydsh 启动官方进程时固定传 --no-open,只保留本启动器一个 UI opener,避免一次命令打开两个 tab;
  • 想用 PWA 窗口 / 指定 App 打开:仓库根 .env.local(gitignored,模板见 .env.local.example)写 DSH_OPEN_APP=...,启动时自动生效;也可以临时 DSH_OPEN_APP="xxx.app" dsh(行内优先);
  • 注意:自定义端口(dsh -p)时 PWA 打开的是自己的 start_url,可能对不上,这种情况用 --no-open 手动开。

sync 行为按定制类型:

类型 source 物化动作
package local dsh plugin add file:<packages/<id>>(自动进 profile bundles)
package remote dsh plugin add <spec>(自动进 profile bundles)
preset copy 到 ~/.dsh/.agent-presets/<id>
patch 按 manifest 顺序合并生成 profile cordis.patch.yml
skill copy 到 ~/.dsh/skills/<id>

顶层 dependencies: = 无 bundle 的支撑包(如 remote 定制缺失的 peer),精确版本 pin 装为 plain dependency、不进 bundle 层;定制条目用 deps: 引用其包名声明归属(安装仍以顶层列表为唯一入口,sync 校验引用,悬空引用报错)。

定制项按需开关(enabledEnv,可选字段,任意 customizations 条目都能声明):声明后同名 DSH_ 环境变量覆盖该条目的 enabled,作用范围是单条定制而不是整个 profile——用于"仓库里默认关闭,但在有权限/有需要的机器上用环境变量按需打开"的场景,例如内部专属包:公开分享这份仓库时它不该默认安装,但在有权限的机器上不想手改 dsh.yaml。写法:

- id: some-internal-plugin
  enabled: false            # 仓库默认关闭
  enabledEnv: DSH_SOME_PLUGIN  # 同名 env 覆盖上面的 enabled;必须是大写 DSH_ 前缀

DSH_SOME_PLUGIN=1(或 true/yes/on)在该机器上启用,=0(或 false/no/off)禁用;不设置或取值无法识别时回退到 enabled 字段。enabledEnv 名字不合法(不是大写 DSH_ 前缀)时 sync 直接报错并中止,避免拼错后"开关看起来没生效"却毫无提示。改动后同样需要 dsh build 才生效。仓库内 dsh-traex-bridge(内部包)就是这个模式的实例,见下方「第三方定制」。

环境级 instructions

顶层 agentInstructions 不是一种 customization type。启用时,sync 校验 source 是仓库内相对文件,加 GENERATED/provenance 头后原子写入 $DSH_HOME/AGENTS.md,并在 .dsh-sync-state.json 记录来源与部署哈希。连续 build 幂等;禁用、删除字段或 dsh reset 时,只会删除仍匹配已部署哈希的目标。目标若已有未托管内容,或托管后被修改,sync 会保留文件并报错,要求人工决定如何处理。

DSH 官方 standard preset 会自动加载,无需复制出 ohmydsh preset。$DSH_HOME/AGENTS.md 给该 DSH 工作环境提供前馈模型指导;它不是权限授予,也不是强制安全边界,实际能力始终由最新 runtime context 与工具执行策略决定。dsh-sandbox-notes skill 继续保留,用于需要时查阅完整背景与恢复细节。

现象、迁移原因、错误恢复规则与验证步骤见 docs/notes/dsh-home-agent-instructions.md

第三方定制(remote)约定

  • 只存三样:精确版本 pin个人覆盖片段(patches/<id>.yml)、条目说明(note/审查记录);不 vendor 源码
  • 升级 = 改 pin 重跑 sync(默认由 autoUpdate 自动完成,见上方「自动升级」;DSH_SKIP_UPDATE=1 恢复纯手工改 pin 模式)。
  • 安全提醒:插件即第三方代码(社区列表明示警告),安装前先看源码,note 记录来源与审查结论。
  • dsh-traex-bridge(内部专属包):来自 bnpm/内网(code.byted.org),鉴权与推理流量走 ByteDance 内网服务,仓库默认 enabled: false + enabledEnv: DSH_TRAEX_BRIDGE(见上方「定制项按需开关」)。克隆本仓库的机器默认不装它;有内网权限时,本机 .env.local(gitignored)加一行 DSH_TRAEX_BRIDGE=1dsh build 即可启用,详见 dsh.yaml 条目 note
  • llm-subscriptions 订阅 provider 插件(dsh-plugin-subscriptions,当前 pin 0.5.2+pr40.d927e3a = 上游 PR #40「按模型默认推理档」临时 fork tarball,设置页每模型默认档列表收起,详见 dsh.yaml 条目 note;上游合并发版后切回 npm):Claude 登录 = 导入本机 Claude Code 凭据(秒登录,不弹 OAuth),升级与选型细见 change openspec/changes/2026-08-20-llm-subscriptions-upgrade(含 ADR-0001)。回滚:dsh.yaml 该条目 spec/version 改回 dsh-plugin-subscriptions@0.5.2 / 0.5.2(或删除临时条目) → dsh build → 重启;codex 会话不受影响,可无损回滚。

开发流

  • 新想法 → BACKLOG.md;单项实施 → openspec change(openspec new change <name>);
  • 自研 package 改代码后要 bump 版本(manifest 同步),sync 才会重装;
  • DSH 运行体由 autoUpdate 自动升级并重跑 sync 恢复全部定制;手工升级同样 = 改 dshVersion 后重跑 sync。

提交前请运行:

npm test                 # sync 黑盒回归测试
npm run check:artifacts  # 防止产物 / nested lock / raw evidence 入库

贡献

欢迎 Issue 与 PR。动手前请先读 CONTRIBUTING.md,它说明了阅读顺序、OpenSpec 规范驱动流程、验证要求与提交规范。

参与本项目需遵守行为准则。安全问题请勿开公开 Issue,按 SECURITY.md 私下报告。

项目文档

文档 说明
CONTRIBUTING.md 贡献流程、开发环境与验证要求
SECURITY.md 漏洞报告渠道与本项目特有的安全考量
CHANGELOG.md 仓库级变更记录
CODE_OF_CONDUCT.md 社区行为准则
openspec/specs/ 系统当前应满足的行为规范
docs/adr/ 已接受的长期架构决策
docs/notes/ 实现背景、运行约束与验证方法
BACKLOG.md 想法池

致谢

  • DeepSeek Harness (DSH) —— 本仓库定制的运行体本体。
  • 各第三方插件作者;来源、许可与审查结论记录在 dsh.yaml 对应条目的 note 中。

许可

本项目基于 MIT License 发布。

第三方定制以 pin 方式引用、不 vendor 源码,各自遵循其原始许可;packages/worktree-session 的交互概念参考详见该目录下的 NOTICE

About

dsh 集成配置

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages