📦 v0.1.2-alpha.5 🔖 master@49a606b · 2026-09-02 ⚖️ MIT 🧩 256 个插件包 · 50 个分组

DeepSeek Harness
深度讲解

DeepSeek 官方开源的 Agent 运行时框架。
它的全部叙事只有一句话——Everything is a Plugin:连模型适配器、工具注册表、会话日志、甚至 Agent 主循环本身,都是可替换的插件。

⭐ 209k+ stars ⚙️ 基于 Cordis 元框架 🚧 开发者预览版
开始深入 ↓
滚动阅读 · 全文含 14 个可交互演示
Chapter 0

它是什么,不是什么

模型负责"想",Harness 负责"做"。DeepSeek Harness(CLI 名 dsh)是把 DeepSeek 模型接入文件系统、终端、网页、沙箱与其他 Agent 的运行时环境——地位相当于 Claude Code 之于 Anthropic,是 DeepSeek 的官方 Vibe Coding 入口。

🧠

不是新模型

它不训练、不替代 DeepSeek 模型,而是围绕模型搭建让模型能"动手"的基础设施。

🔌

不是 API 客户端

SDK/HTTP 封装只占它极小一角;它提供的是完整的 Agent 能力面:会话、工具、沙箱、审批、持久化。

🛠️

是 Agent Harness

把模型接入真实世界:文件、终端、代码执行、子 Agent、定时任务、人类协作……让模型成为能规划多步任务的自主智能体。

🧩

一切皆插件

基于 Cordis 插件元框架(DeepSeek 为其发表论文 A Programming Paradigm for Spatiotemporal Composability)。没有需要打补丁的"特权内核"——扩展 dsh = 在旁边挂一个插件。

🚧官方警告:项目处于 developer preview,迭代极快,"THERE WILL BE COMPATIBILITY-BREAKING CHANGES"(必然会有破坏性变更)。运行前官方要求先阅读 SAFETY.md(见第 8 章安全模型)。
Chapter 1

三分钟跑起来

一条命令启动完整 Web UI。点击"运行",看模拟终端里会发生什么。

zsh — deepseek-harness
真实环境需要 Node.js;--no-open 可不自动开浏览器

📦 从源码运行

git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install && pnpm run build
pnpm dsh web   # 使用已构建产物,不重新编译

🎛️ 五种开箱 Profile

一个 dsh 启动器,按名字组合不同的插件树:

web — Web GUI(默认别名) headless — 一次性运行器 sdk — JSON-RPC 服务 sdk-minimal — 极简 SDK 树 acp — 自动化协议服务器

Python SDK 也会以平台 wheel(deepseek-harness-sdk-runtime-<platform>-<arch>)打包这份 CLI,默认启动 dsh --profile sdk。

Chapter 2

地基:Cordis 的五个概念

读懂 Cordis,就读懂了 dsh 的一切。这五个机制组合出一个结果:任何部件都能被配置替换,注册即效果、卸载即回滚。

1
Plugin = Service

插件即服务

插件是一个实现 Service 的对象:可以是带 inject/apply(ctx) 的函数,也可以是 Service 子类,由 Cordis 挂载进当前上下文。

最小单元
2
Context

上下文 = 服务仓库

服务认领稳定的 ctx.<key>(如 ctx.tools、ctx.llm),其他插件按键查找而不是 import 具体实现——这就是可替换性的来源。

服务定位
3
inject

声明式依赖

插件声明需要哪些服务,Cordis 会等它们就绪再激活。加载顺序由"服务需求"表达,不再需要手工排启动序。

加载顺序
4
Typed Events

类型化事件

服务用 TypeScript 声明合并登记事件名,再按五种模式派发。事件是 dsh 的扩展点——拦截几乎一切行为。

扩展点
5
Reversible Effects

可逆注册

Prompt 区块、工具 schema、适配器、Provider、监听器,全部经 ctx.effect() / ctx.on() 安装;插件卸载时按注册逆序自动拆除。

热插拔
★
Result

没有特权内核

模型适配器、工具注册表、会话日志、Agent 主循环……产品里的每一部分都是插件。扩展 = 并排挂载;替换 = 改一行配置。

架构哲学
⚡互动演示 · waterfall:环绕式中间件

一次 agent/pre-step 请求依次流过三个监听器。委托型监听器修改共享请求后调 next() 传递;拥有决策权的监听器可以不调 next() 直接返回,下游全部跳过。

request
Policy

L1 审批策略

检查输入是否放行;拥有最终决策权,可短路

→
Annotate

L2 上下文注入

向请求追加注入的上下文片段

→
Observe

L3 观测记录

遥测监听器,只看不动

点击 ▶ 播放,观察 request 在监听器之间的流转。

五种派发模式(事件公共契约的一部分)

模式等待完成?派发顺序有返回值?语义
emit否按注册序观察否广播通知,无人能拦
waterfall否按注册序是环绕中间件:next() 委托,不调即短路;prepend: true 抢先注册
parallel是全部并行否扇出并发执行
serial是按注册序是串行接力,如 agent/turn-stopping 终检
bail否按注册序是第一个给出 bail 值的监听器截停
深挖 · waterfall 的源码级语义

ctx.waterfall 本质是 around-middleware:监听器签名收到 (...args, next)。调用 next() 把(可能已包装的)结果交给下一个服务;不调用直接 return 即短路。返回值沿 next() 的返回值向上传播。

  • 合作型监听器的惯例:修改共享的请求/决策对象,然后委托 next();
  • 也可以整个替换返回值,下游只会看到替换后的结果;
  • 单决策事件(如 pre-step 的准入决策)中,短路就是设计意图——策略监听器拥有决策权时不委托;只做标注/观测的监听器必须委托。

实战纪律:事件归属要按域划分——工具流水线事件归 ctx.tools,模型流式归 ctx.llm,活跃 Agent 协调归 ctx.agents。策略与拦截优先用事件,直接能力调用优先用服务方法。

Chapter 3

启动与组装:Profile → Bundle → 插件树

一次 dsh 运行 = 一棵在启动时按有序层组装出来的插件树。每一层都只能"替换/插入配置行",于是上游永远可以被下游补丁覆盖。

🥞互动演示 · 点层看树
bundle · dsh-base共享第一层:模型适配器 · 工具 · 持久化 · 沙箱与审批策略 · 设置 · 凭据 · 遥测
bundle · dsh-web-app叠加浏览器应用:Web GUI 宿主(API 网关 + HTTP 路由)+ 客户端
profile · cordis.patch.ymlprofile 内置补丁:按 id 定位行,整行替换或插入新行
home 级补丁 + --patch 覆盖Harness home 的用户补丁,最后是命令行 --patch 临时覆盖
← 从第 1 层开始点,右侧行随层点亮 ├─ llm-deepseek ; 模型适配器 → ctx.llm ├─ tools ; 工具注册表 → ctx.tools ├─ agent-loop ; 主循环本身也是插件 → ctx.agentLoop ├─ session ; 追加式会话日志 → ctx.sessions ├─ sandbox-bwrap ; 沙箱后端 → ctx.sandbox └─ settings/credentials ; 设置与凭据接缝 ├─ host/api-gateway ; Web 宿主:HTTP 路由 └─ client/shell ; 浏览器端 UI └─ + my-plugin ; 你的插件行(示例) └─ ~ llm-deepseek → llm-openai ; 一行配置换掉模型

🔍 看到你机器上的树

dsh --profile web --dump-config 会打印实际启动的每一行配置——打印出来的任何一行,都能被你自己的补丁替换。

🔥 web 可热重载

自定义 profile 默认 live patch reload;web 开箱即热。而 headless / sdk / acp 在启动时一次性应用所有层——一次性程序跑起来再换依赖会破坏生命周期。

✂️ sdk-minimal 例外

它是唯一不套 dsh-base 的组合:一个 bundle 自拥完整显式 SDK 树,追求最小面。仓库用 verify-application-entrypoints 脚本守住"所有 Node 应用入口必须经过 dsh"。

Chapter 4 · 全篇高潮

灵魂:一次 Turn 的完整生命周期

两个基本单位:Step = 一次模型请求 + 它触发的工具调用;Turn = 零或多个 Step(打开于首个输入被认领,关闭于再无所欠)。下面的时序图逐事件点亮,右侧同步解说。

🎬循环模拟器 0 / 16
点击 ▶ 播放,或用"单步"逐事件推进。青绿色 chip = 持久会话事件(写日志、可重放),灰 chip = 运行时扩展点。
durable · 会话持久事件(turn/*, step/*, user/message, assistant/*, tool/*) live · 运行时扩展点(agent/*, llm/stream, tools/*)
深挖 · 这张时序图背后不变的规则
  • 事件三域:会话持久事件(写日志 + session/event 广播,重载后仍在)|Agent 事件(agent/*,携带活跃 Agent:收件箱、步骤、状态、请求、校验、继续)|能力事件(fs/*、tools/*、telemetry/*,把策略/适配器挂到接缝上,不碰循环)。
  • 单一收件箱:输入经一个 inbox 进入驱动器。部分消息立即唤醒;注入的上下文在箱内等待,直到下一条消息顺路带走。
  • pre-step 的决定是权威的:监听器可整体改写被认领的消息,也可拒绝;被拒绝或首认领即为空 → 仍会关闭一个"一步都没花"的持久回合,日志记录这次尝试。改写 enter 决策时必须展开({ ...decision, messages })以保留 startsRequestSeries 等声明。
  • 工具执行:按执行模式分类,屏障 + 有界滚动池,开跑前重分类;pre 有序、execute 并发、post 有序。
  • 压缩(compaction)就挂在这条流上:dsh-compaction-basic 用 agent/pre-step 查压力、用 agent/request-error 只认上下文溢出;先做免模型的工具结果修剪,再做摘要;修剪/摘要推进了表面替换世代才开新重试回合,否则原始错误仍是权威。
Chapter 5

会话日志 = 唯一事实源

一条不变的铁律:"Model-visible means logged"——凡是到达过模型眼前的,必须能从日志重建,且有运行时断言强制执行。Fork、Resume、回放、遥测、UI 渲染,全部从这条追加式日志派生。

// session-YYYYMMDD.jsonl —— 追加式 SessionEvent 流

deriveMessages() · 模型历史投影

日志落一条,投影长一格 →

原始 assistant/chunk 单独保留,保证回放与 UI 保真;dsh-session-projection 增量折叠已提交事件,宿主用 stateOf() 读类型化状态、用 snapshot() 批量取裁剪后的客户端视图。

🧬这也解释了 fork 为什么便宜:分叉就是在回合边界引用同一条日志(ctx.agents.create({ sessionId, seed, meta: { parentSession, seedLength } })),只有 agent-loop 发布的会话才持久化。新增"模型可见输入"的唯一正确姿势 = 扩展 SessionEventMap 加一种新事件、再从日志渲染它。
Chapter 6

能力接缝 Seam:换一个 Provider,换掉半个产品

Seam = 可替换的能力,由三个角色构成完整能力:Service Definition(声明接口、拥有 ctx.<key>)+ Service Provider(实现)+ Consumer(通常是模型可见的工具)。角色可分包也可同包,但单独一个角色不构成 seam。

① Service Definition

dsh-shell · ShellExecutor

声明 shell 执行世界的接口,认领 ctx.shell。可以是抽象类,也可以是注册表(如 WebRuntime)——但绝不是 TS interface。

② Service Providers

dsh-bash-localdsh-bash-sandbox

多个实现并存:本地直跑,或经 bwrap / Landlock / Seatbelt 收容。指向哪一个,由配置行决定。

③ Consumers

dsh-tool-bash

模型看到的 bash 工具只是消费者——它对背后是谁毫无感知,schema 却始终稳定。

🔀互动演示 · 拨动 Provider,看下游整体搬家

fs 与 subprocess 两个 Provider 共享同一个"执行世界"——所以切到远程沙箱时,Bash、PTY、LSP、glob/grep 一起搬走,不需要任何 Provider 分叉。

bash 工具 PTY 持久终端 LSP 语言服务 glob / grep (ripgrep) run_code 代码运行时
本地执行:直接跑在你的机器上,配合 ctx.sandbox 后端(bwrap / Landlock / Seatbelt)可在 spawn 前包装 argv 收容进程。

接缝目录(部分)——每个都是一句话能说清的 ctx.<key>

ctx.llm 模型适配器注册表ctx.tools 工具注册表+守卫流水线ctx.fs 文件系统ctx.shell Shell 执行ctx.subprocess 子进程ctx.sandbox 进程收容ctx.terminals 持久 PTYctx.jobs 后台作业ctx.web 搜索/抓取ctx.lsp 语言服务ctx.subagents 子代理ctx.skills 技能ctx.goals 目标ctx.commands 人类命令ctx.webhookRuntime 外部事件ctx.settings 设置ctx.credentials 凭据ctx.storage 存储枢纽ctx.sessionPersistence 会话持久化ctx.userQuestions 人机问答ctx.planMode 计划模式ctx.agentTeams 多 Agent 团队(实验)

Subagent 的 Provider 谱系同样宽广:从"全新子代理"到"另一个产品里的委托回合",都藏在同一个接口后面。这就是"换一个 Provider 改变半个产品"的含义。

Chapter 7

六大概念技术拆解

Context、Memory、Session、Agent、RAG、Plugin——六个被说烂了的词,在 dsh 里各有精确的技术含义。每个概念按同一把尺子拆:一句话直觉 → 机制 → 源码级事实 → 与其他 harness 对照。

①

Context · 上下文

Model-visible request state
一句话直觉:模型每一步都是失忆的——Context 就是它"这一眼"能看到的世界。Context 不是存储,是每次请求现场组装的视图。
  • 四路汇流成一次请求:系统提示区块 + 工具 schema(ctx.systemPrompt 瀑布组装)+ 从会话日志派生的历史(deriveMessages())+ agent.inject() 注入的上下文(落入下一次被接纳的请求)。
  • context 组是真实的插件族:agent-instructions(装载/刷新 AGENTS.md、CLAUDE.md 工作区指令)、file-reference(@file 提及语法)、session-reference(跨会话快照引用)、time-context(每步时钟)、tmux-context(每回合 tmux 位置感知)——上下文的每一部分都是可摘除的插件。
  • 两个减压阀:compaction(dsh-compaction-basic 在 agent/pre-step 查压力 → 免模型的工具结果修剪 → 才轮到摘要);spill(工具结果溢出:超限结果完整存入 ctx.spillStore,模型只拿到可追读的定位器)。
🪟互动演示 · 上下文窗口配平
横向对照:Claude Code 用 CLAUDE.md + auto-compact 解决同类问题;dsh 把"上下文从哪来"拆成了可插拔的 context 插件 + 两条独立减压阀——上下文策略本身是被编程的对象。
②

Memory · 记忆

Persistence without a memory module
一句话直觉:dsh 故意不内置"记忆"模块(全仓库没有 memory 包)。它把记忆拆成四层持久化原语——记忆是数据的形状,不是功能。
L0 事实追加式会话日志(jsonl/sqlite 持久化)——发生过的事实,永不改写
L1 派生session-projection 增量折叠出的类型化状态(带持久缓存,跨版本可读)
L2 跨会话storage 枢纽(json/sqlite 后端)· skills(程序性记忆)· goals(目标状态)· attachments(持久附件)
L3 指令agent-instructions 插件装载 AGENTS.md / CLAUDE.md——工作区指令 ≠ 自动记忆,是每次现场加载的上下文
  • 对照实验:Hermes 的记忆是主动的(Agent 自策划何时写 MEMORY.md、任务后自创技能);dsh 的记忆是被动的——只有日志在你不注意时默默长着。
  • 为什么这样设计:自动记忆策略(写什么、忘什么)争议极大且高度场景化。dsh 把 L0-L2 做对做稳,把"记忆策略"留给上层建造者——这正是基底与产品的分工。
  • 检索记忆:会话历史不是死数据——session-query 五个只读工具 + SQLite FTS5 让旧会话可搜可追溯(见 RAG 节)。
横向对照:Claude Code = CLAUDE.md + auto memory;Codex = AGENTS.md 分层;Hermes = 学习循环(自策划记忆 + 自创技能 + Honcho 用户建模);dsh = 提供记忆的原材料,不提供记忆的价值观。
③

Session · 会话

Append-only event log
一句话直觉:Session 不是"聊天记录",是一条只能追加的类型化事件流——把它当数据库表的 redo log,而不是文档。
  • 事件解剖:每条 SessionEvent 有单调 seq、类型来自 SessionEventMap(turn/start、user/message、assistant/chunk、tool/call……)、append-only 不可改写。
  • 一条不变量统治一切:"到过模型眼前的必须能从日志重建",有运行时断言执法。assistant/message 额外记录 token 用量与 sourceEventSeqs(指回确切的 chunk 事件)——可溯源到流。
  • 持久化是接缝:SessionPersistence(create/open/stat/list/export),开箱 jsonl 后端,换 SQLite 只需实现接口。
  • 投影层:dsh-session-projection 增量折叠已提交事件,宿主 stateOf() 读状态、snapshot() 出裁剪视图;投影缓存刚落地跨版本读兼容(升级不炸旧缓存——最近一周的提交主题)。
  • 分叉即引用:ctx.agents.create({sessionId, seed, meta:{parentSession, seedLength}}) 在回合边界引用同一条日志,零拷贝。
turn/startuser/msgchunktool/callresultturn/end seq 单调递增 · append-only · 不可改写 持久化SessionPersistencejsonl / sqlite 后端 投影projection 折叠stateOf()/snapshot() 分叉回合边界引用parentSession+seed → 回放(重读日志)→ resume(断点续跑)→ UI 渲染(session/event)→ 遥测 / 标题 / 压缩→ session-query FTS5 检索 不变量:model-visible ⇒ logged(断言执法)
横向对照:各家都有"会话",差别在地位——多数产品里会话是 UI 概念;dsh 里它是整个系统的因果记录,连"模型看到了什么"都要向它对账。
④

Agent · 智能体

Identity + inbox + scope + loop
一句话直觉:Agent ≠ 一段对话。一个 Agent = 收件箱 + 驱动循环 + scope(能看/能做什么)+ 自己的会话日志——前章的"循环"只是它四分之一。
  • 活注册表:ctx.agents;agent/* 事件暴露收件箱拼接、状态机(running/idle)、请求、校验、继续、错误——UI 与 SDK 全靠它协调。
  • scope 系统(dsh 独有的精确性):注册分全局/scoped 两级、flat 不继承——子代理的可见性用 lineage 数据表达,绝不用 scope 结构传递。agent.ctx 注册即"scope 可见 + scope 生命周期"。
  • shadowing = per-agent 人格机制:scope 内同名工具/提示区块/变量遮蔽全局同名者(most-specific-wins),且对其他 Agent 不可见;被过滤掉的全局工具在 prompt 里消失且执行时拒绝——与不存在无异。
  • setup window:创建者有窗口期组合 Agent 的世界(注册工具/区块/变量),setup 只注册、不驱动——发布前完成,之后不可偷塞。
  • goal round:一个目标轮 = 一个 goal 来源的 turn;激活态(armed/disarmed)故意不进持久重放 → resume/fork 后自动续跑必须经人类授权的 resume 变更——安全的持久自治。

子代理谱系(同一个 ctx.subagents 接缝后的四种形态):

fresh child一次性子代理,跑完即弃(subagent 工具默认)
continuable后台可续:send_message 可以中途纠偏(steer),interrupt_agent 可打断,list_agents 列举
Agent Teams(实验)持久花名册 + 任务板 + 邮箱,叠在可续子代理上;dsh-base 默认禁用
结构化循环workflow(脚本编排)与 ralph(fresh-agent 多轮 + 有界 handoff 报告)
收件箱语义:部分消息立即唤醒驱动器;注入的上下文只在箱内等待,搭下一条消息的便车进入——不会单独打断工作。
横向对照:Claude Code 的 Task 子代理、Codex 的 exec 编排、Hermes 的隔离子代理都是固定形态;dsh 把"子代理是什么"也做成接缝——从"全新子代理"到"另一个产品里的委托回合"都能是 Provider。
⑤

RAG · 检索增强

Agentic retrieval, not embedding pipeline
一句话直觉:全仓库 grep 不到 embedding / vector store——dsh 没有 RAG 模块,这是一个立场,不是缺口。它的答案是:让 Agent 带着工具现场查。

Embedding RAG(dsh 未采用)

预切分 → 向量化 → 相似度召回 → 塞进上下文。
优:海量语料、模糊语义匹配。
代价:索引永远滞后于文件;切分破坏代码结构;召回不可解释;多一套向量基础设施。

Agentic Retrieval(dsh 的选择)

模型在循环中自主决定查什么、怎么查、查不到再怎么查——检索变成可审计的多步推理而非一次黑盒相似度。

dsh 提供的检索原语(全部模型可见):

glob / grep — 内置 ripgrep 前台子进程,免装 rg session_search — SQLite FTS5 会话全文检索 spill 定位器 — 超限结果追读 lsp — 符号级定义/引用 @file / session-reference — 精确引用 skill catalog — 程序性知识目录
  • 为什么代码检索适合"不向量化":代码是精确符号系统,ripgrep + 结构遍历(LSP)在准确性与新鲜度上碾压向量召回;文件永远是最新的,没有索引延迟这回事。
  • 真需要向量 RAG?写一个 ctx.tools 插件包装你的向量库(如 sqlite-vec / 外部服务),schema 自动进组装——十分钟的事。这正是"一切皆插件"的意义:缺省立场不等于封死道路。(此扩展思路为讲者基于插件体系的推断,官方未内置。)
横向对照:Claude Code / Codex 同样以 agentic 检索为主(grep/glob + 索引服务可选);Hermes 的 FTS5 会话检索与 dsh 同构。2026 年的现实:编码 harness 集体押注 agentic retrieval,向量 RAG 留给了企业知识库场景。
⑥

Plugin · 插件

The atom of the product
一句话直觉:在 dsh 里"给产品加功能" = 写一个导出 apply(ctx) 的文件 + 在 cordis.yml 加一行。没有框架引导代码,没有插件 API 注册表——Context 本身就是 API。

① 最小可用(官方教程原文)

// hello.ts — 导出 apply,Loader 挂载时调用
export function apply(ctx: Context) {
  ctx.effect(() => { // 注册即效果
    const t = setInterval(tick, 200)
    return () => clearInterval(t) // 卸载逆序回滚
  })
}

② 认领一个 ctx 键 + 声明依赖

class Greeter extends Service {
  constructor(ctx) { super(ctx, 'greeter') }
}
// 消费方按 key 注入,等待其就绪
export const inject = ['greeter']

③ 类型化事件(声明合并)

declare module '@deepseek-ai/cordis' {
  interface Events {
    'stats/report'(name: string, n: number): void
  }
}
ctx.emit('stats/report', name, next)

④ 声明式配置(Schemastery,支持热更新)

export const Config = Schema.object({
  greeting: Schema.string().default('Hello'),
  targets: Schema.array(String).default(['world']),
})
export function apply(ctx, config: Config) { … }
  • 组合在配置里,不在代码里:cordis.yml 的条目并发启动,顺序由 inject 依赖表达,与书写位置无关;patch 按 id 整行替换(第 3 章演示)。
  • 三种形态:函数(最常用)/ 对象 / Service 子类——"用到服务再升级成类"。
  • 打包与生态:包名 @deepseek-ai/dsh-*,GitHub topic dsh-plugin 获得可发现性;bundle 即"可安装的 patch 层"(dsh.bundle 字段)。
  • 动态侧:cordis_* 工具让 Agent 在 vm 沙箱里定义/挂载/卸载包(运行中的包还能注册新工具);extensions 组让 Agent 巡检活插件树——插件系统对模型也是可编程的。
横向对照:Claude Code 的"文件即接口"(hooks/skills 是数据,内核解释执行)与 Codex 的配置扩展都保守在"配置面";dsh 是唯一把产品功能全部表达为可加载代码单元的 harness——灵活性的上限与认知成本的下限,都是它。
收束 · 六个概念如何在一次请求里协同

用户敲入一句话 → Agent 的收件箱认领它 → Context 插件们现场组装视图(agent-instructions 装载指令、time-context 塞入时钟、pre-step 决定准入与压缩)→ Plugin 们注册的 prompt 区块与工具 schema 拼成请求 → 循环驱动 → 模型调工具,Plugin 守卫流水线执行(spill 溢出大结果)→ 每一步作为 Session 事件追加落盘 → Memory 的投影层增量折叠出状态供 UI 与下次派生使用 → 下一步模型用 RAG 原语(grep/FTS5/LSP)现场检索补上下文。六个词不是六个功能,是同一次请求的六个侧面。

Chapter 8

设计哲学:dsh 到底在赌什么

把 dsh 放回 harness 谱系,它的选择才有分量。所有 harness 回答的是同一个问题——"如何给模型一个可信赖的行动身体?"——但四家代表给出了四种不同的答案。

🧱

Claude Code
一个有主见的产品

Anthropic。harness 即产品:内核闭源、边缘用文件开放——CLAUDE.md 记忆、hooks 脚本、skills 工作流、agents 定义、MCP 服务器,全是"文件即接口"。设计循环四拍:收集上下文 → 行动 → 验证 → 重复。赌的是:把最好的编码伴侣直接交付给你。

🛡️

Codex CLI
一个加固的内核

OpenAI。Rust 原生单二进制(codex-rs,60+ crates),把"不信任模型输出"做进内核:OS 级沙箱(macOS Seatbelt / Linux Landlock+seccomp)叠 4 档审批策略;扩展走 config.toml、MCP 与生命周期 hooks(企业还有 requirements.toml 受管层)。赌的是:安全与性能的确定性。

🌱

Hermes
一个会成长的身体

Nous Research。harness 的第一性目标是随使用变强:内置学习循环——Agent 自策划记忆(MEMORY.md / SOUL.md / USER.md)、复杂任务后自创技能且"技能在使用中自我改进"、跨会话用户建模(Honcho);七种执行后端(本地/Docker/SSH/Modal…)、全平台消息入口。赌的是:长期陪伴产生复利。

🧩

dsh
一块组合基底

DeepSeek。前三种都保留了"产品内核",dsh 是唯一把内核也交出来的:没有特权核心,产品 = 一份插件配置——连主循环都是插件。它赌的是:harness 领域还没定型,可组合性本身就是产品,让别人能在它上面造出前三种。

谱系定位图:四家在"产品 ↔ 基底"光谱上的位置

开箱即用的产品 深度可组合的基底 封闭/厂商内核 开放生态 / 自托管 Claude Code闭源内核 · 文件开放边缘 · SDK 开源 Codex CLI全开源 · 但内核一体化,扩展走配置 Hermes开源自托管 · 产品成型 · 以记忆/技能成长 dsh连循环都是插件 · 产品=配置

dsh 的八条设计逻辑

1
Microkernel

微内核,无特权层

agent-loop、tools、session、llm 全是平权插件。改行为 ≠ 改内核,而是在旁边挂插件——升级永不冲突。

2
Config as Product

配置即产品

web/headless/sdk/acp 四种产品 = 同一基底的不同配置行。造"下一代编码产品"不需要 fork,写一个 profile。

3
Key, not Import

按键查找,不按导入

服务经 ctx.<key> 定位而非 import 实现 → 消费者与提供者解耦 → 换 Provider 换掉半个产品(第 6 章的接缝经济学)。

4
Events as Seams

事件即扩展点

五种类型化派发模式,waterfall = 环绕中间件。拦截点铺满全程(pre-step/request/tools),策略与机制分离。

5
Log as Truth

日志即真相

"到过模型眼前的必须能从日志重建"——有运行时断言执法。回放/fork/UI/压缩全是投影,一个事实源消除一类 bug。

6
Reversible Effects

可逆注册

一切注册都是 effect,卸载即逆序回滚 → 热重载、动态插件、scope 生命周期才可能正确而非碰巧正确。

7
Self-hosting

自反性:造 harness 用 harness

这个仓库本身就是证据:AGENTS.md 规约 Agent 贡献者、.agents/notes 存 Agent 决策记录、工具目录由真实启动插件生成、extensions 组让 Agent 巡检/挂载自己的插件、cordis_* 工具让模型给自己装工具。

8
Competitors as Plugins

竞品生态也是插件

hooks-claude-code / hooks-codex 桥直接运行你已有的两家 hooks 配置;ACP 对接自动化;MCP 分组接标准生态。不要求你迁徙,要求你叠加。

⚖️诚实的代价(trade-offs):极致可组合的另一面是——256 个包的认知成本 vs Codex 单二进制的可审计性;TypeScript/Node 运行时 vs Rust 原生性能;预览期"必然破坏性变更" vs 稳定产品承诺;把 Cordis 框架供应商化(rescope 进 @deepseek-ai 域发布)意味着框架演进风险自担。dsh 不是"更好的 Claude Code",它是另一个物种:赌的是 harness 领域需要的是 Linux 内核,而不是又一个发行版。
深挖 · 两条原始决策记录里的哲学

① "Foundation over blast radius"(根基优先于爆炸半径)——AGENTS.md 原文:首个正式 tag 发布前,"prefer correct foundations to compatibility shims: rename or repackage freely"。后端直接拒绝旧磁盘格式,SQLite 用单调 SCHEMA_VERSION,会话格式版本停在 0、无兼容承诺。这是预发布期把"正确性"排在"兼容性"前面的公开宣言——也解释了为什么 README 敢写"必然破坏性变更"。

② Vendored rescope(框架收编)——Cordis 及其基础库被 vendor 进仓库、以 @deepseek-ai/cordis 等名字发布:因为所有 harness 包都以框架为 peer dependency,"发布 harness 就等于发布这一层",用上游名字会squat 注册表。映射由脚本 rescope-vendor 机械执行、卫生门禁校验,上游快照版本全表留痕。框架从"依赖"变成"自己的地基"——微内核哲学的最终自洽。

Chapter 9

工具全家桶 · 24 个工具包,50+ 模型可见工具

每个工具包向 ctx.tools 注册 schema,经系统提示组装进入模型视野。点卡片看细节;官方工具目录由脚本真实启动每个工具插件读取 schema 生成,并有完整性守卫防漏——文档即运行时事实。

Chapter 10

横向对比:同一个需求,四家的答案

维度表格看全景;下面的需求对比器点一个具体需求,看四家分别怎么解。

🔍需求对比器
维度Claude CodeCodex CLIHermesdsh
形态Node.js CLI + IDE/桌面/网页同引擎Rust 原生单二进制(codex-rs,60+ crates)Python 3.11(uv 管理)+ 消息网关TS/Node,pnpm monorepo,256 包 / 50 组
开源CLI 闭源(仓库仅 issues);Agent SDK 开源Apache-2.0 全开源MIT 全开源MIT 全开源;Cordis 框架供应商化
循环归属产品内置(SDK 化后可复用)内核内置内置 + 学习循环循环本身是插件(agent-loop 包)
扩展模型文件即接口:CLAUDE.md / hooks / skills / agents + MCPconfig.toml + MCP + 生命周期 hooks(企业受管层)YAML 配置 + MCP + toolsets + 自创技能Cordis 插件树:profile / bundle / patch,一切皆插件
工具体系内置编码工具 + MCP 动态接入内置 + MCP + skills40+ 内置 + toolset 分发 + MCP24 工具包 / 50+ 工具 + PTC(run_code)+ cordis_* 动态自增
上下文auto-compact + /context 管理内核管理 + 云端任务分工分层记忆 + FTS5 会话检索 + 轨迹压缩追加式日志=真相,派生投影 + 压缩/溢出(spill)策略
沙箱权限模式 + 审批提示 + 沙箱化 bashOS 级:Seatbelt / Landlock+seccomp + 4 档审批7 种执行后端(本地/Docker/SSH/Modal/Daytona…)ctx.sandbox 接缝(bwrap/Landlock/Seatbelt)+ 执行世界整体远程化(E2B)
多智能体Task 子代理 + agent teams(实验)codex exec 编排 + 云端并行任务隔离子代理并行工作流ctx.subagents 接缝 + Agent Teams(实验)+ workflow / ralph
记忆成长CLAUDE.md + auto memoryAGENTS.md 分层发现学习循环:自策划记忆 + 自创技能 + 用户建模会话持久化 / 标题 / 目标;成长非主打
一句话"最好的编码伴侣,拿来就用""最可信的本地内核,安全先行""越用越懂你的私人 Agent""要不同的 harness?请自便,这里全是零件"
🎯

选 Claude Code / Codex,当…

你要的是今天就能高效干活的编码搭档:产品打磨度、稳定性和安全审计都最好。两者差异主要是生态与审美,而不是架构哲学。

💬

选 Hermes,当…

你要的是跨会话成长的个人 Agent:它记得你、自创技能、活在你的 Telegram/Discord 里。harness 在这里被优化成"随时间增值的资产"。

🔬

选 dsh,当…

你要改造 Agent 运行时本身:换模型编排策略、定制工具流水线、研究 harness 设计、或在其上长出自己的产品。它还准备了 hooks 桥——你可以带着 Claude Code / Codex 的 hooks 配置直接来用:生态不是敌人,是插件。

Chapter 11

安全与权限深潜:信任是要被编程的

第 14 章的 SAFETY.md 摘录只是底线声明。这一章拆开 dsh 真正的防御工事:五层防线如何分工、每层被攻破的后果、以及"失败即关闭"的审批哲学。

"
Never hand untrusted output the ambient environment or predictable paths.—— docs/defensive-patterns.md:把环境变量与可预测路径交给不可信输出,是这个仓库明文禁止的缺陷类。
🛡️互动演示 · 攻击走查:一次恶意输入要闯几关
📦

sandbox · 同世界收容

服务契约(dsh-sandbox)+ 各平台后端(sandbox-local:Linux bwrap/Landlock、macOS Seatbelt;Windows 走 sandbox-windows-acl 受限令牌)+ sandbox-policy 按调用解析文件副作用策略。消费者在 spawn 前包装 argv——收容是能力,不是补丁。

🙋

approval · 失败即关闭

dsh-user-approval 是渠道无关的一次性审批接缝,明确设计为 fail-closed——审批器缺席/出错时,决策是拒绝而非放行。permission-presets 把"沙箱模式 + 审批策略"打包成用户可选的权限档位。

🧹

credentials · 秘密不入配置

凭据接缝只流转引用值与记录,secret 值永不进配置文件;credentials-local 做 env/.env 分层;需要人机对话才能取得的凭据走 authorization 流程注册表。子进程环境额外清洗:凡名字含 *KEY*/*SECRET*/*TOKEN*/*PASSWORD* 一律剥离。

defensive-patterns:把踩过的坑立法(节选)

这份文档的每个条目都是真实发生过或差点发生的缺陷类,写成防止复发的规则——这是安全工程里最珍贵的一手材料。

正交结果独立上报

进程可能"超时了且 exit 0"(它吞了信号)。timedOut/signal/exitCode 各自独立上报,绝不把一个标志嵌进另一个的分支——否则调用方把截断的运行读成干净成功。

拆除要达到静止,而非请求静止

发出 kill/abort 就返回的 teardown 留下孤儿。清理必须 async 并等待子进程退出(kill → await done),且先关监听器注册表再杀——迟到完成保持安静。

临时文件走私密路径

spill/临时文件用 0700 私有目录、随机名、独占创建('wx' + 0600)——可预测的世界可读路径就是在邀请符号链接竞态。

链接形路径只能 unlink

可能成为符号链接/junction 的路径:先 lstat 判断再 unlink(只删链接不跟进目标);递归 rmSync 留给确知的真实目录。

横向对照:Codex 把同样机制焊死在内核(Seatbelt/Landlock+seccomp,三档沙箱 × 四档审批,不可换);Claude Code 走权限模式 + 逐次审批;dsh 的差异是把每层都做成可换接缝 + 按调用解析的策略——灵活性换来的代价是:组合正确性成了你的责任。官方立场从未变:沙箱与审批降低风险但不保证隔离,不可信负载请用一次性环境。
Chapter 12

工程自举:这个仓库如何用 Agent 造自己

dsh 最被低估的部分不是代码,是建造过程本身:1714 条 Agent 决策记录、100% 覆盖率门禁、录制会话回放测试、由真实启动插件生成的文档——一套让"不确定性的系统"保持确定性的工程体系。

"
Verify the world, not the self-report.—— docs/testing.md:端到端断言要重跑命令、重读文件;对 Agent 自身输出的关键词探测,只会让作弊的 Agent 通过。
1,714Agent 决策记录
1,294 / 343已实施 / 已归档
54 / 20提议中 / 被否决
100%逐文件覆盖率门禁
6条测试通道
4篇事故复盘(postmortem)

六条测试通道(docs/testing.md 浓缩)

通道机制独门规则
Unitvitest,测试与被测代码同目录每个注册表必须有 HMR 安全测试:dispose 贡献 fiber,断言清理干净
Coverage 门禁packages/*/*/src 逐文件 100%"未覆盖的行常常是该删的死代码,而非欠的测试"——门禁同时是清理器
Real-API e2e带 key 打真实 DeepSeek API,无 key 自跳过"我们是 DeepSeek——不做配给制的真实 API 测试";无 key 测试只证明管道通,冒烟测试启动真实 profile 发一条 prompt 检查世界
Snapshot录制 session.jsonl 供回放,回放结果即期望改动场景必须同 PR 带录制会话;可变场景独立比对完整工作区树,且 record/refresh 永不改写该树
Web 浏览器快照Chromium + ARIA 证据CI 强制只读 DSH_SNAPSHOT=replay——期望产物永不被 CI 改写,每个 diff 都人工过目
构建产物冒烟发布件 bin 在裸 node 下运行"真实入口"指发布工件:tsx 会掩盖 settle 竞态与模块解析失败

💀 事故复盘 0001:178 个绿测,照样当天崩溃

ACP 服务器带着 178 个通过的单测和 100% 行覆盖上线,真实编辑器(Zed)一连上就崩:第一发 session/new 就报 cannot get property "agents" without inject。

  • 根因 #1:一行多余的 export default apply——Loader 把命名导出的 inject 丢弃了。所有测试都是手工挂载插件,从未走过真实 Loader 路径。
  • 根因 #2:修掉后又在 session/load 暴露第二个独立 bug(shadow 边界上的可选服务查找)——同一个错误串后面藏着两个 bug。
  • 制度的回应:新增免 key 的真实 Loader 覆盖;规则:"一个守卫只有在回归能让它变红时才算守卫——引入回归、看它红、再回滚。"

📓 一条 Agent Note 长什么样(节选)

投影缓存跨版本读兼容(2026-09-02,本周):session_projcache 磁盘结构三代演进,升级后的 home 出现"首次启动即把坏文档永久写入新树"的投毒。决策:声明式读兼容——

// 域 owner 声明哪些旧版本仍可读
projcache: version 6,
compatibleVersions: [3, 4, 5]
// 读容忍旧版本;写永远戳当前版本
// (读到旧记录,下一次 checkpoint 自然推进)

过期的缓存只付出更长的尾部重放,绝不给出错值、绝不拒载。1,714 条这样的记录构成了仓库的制度记忆——决策可追溯、可否决(rejected 目录就放着 20 条)。

🔁互动演示 · 一次提交的生命周期(自动播放)
STEP 1
Agent 提交 PR

贡献者是人类或 Agent(遵循 AGENTS.md)

STEP 2
静态门禁

lefthook + oxlint + 类型检查 + rescope-vendor:check

STEP 3
测试矩阵

六通道并行:覆盖率门禁拆分并发分区

STEP 4
doc-sync 重生成

工具目录由真实启动插件读取 schema;漏写文档=CI 失败

STEP 5
Agent Note 必写

架构决策落 note,进 implemented/ 或 rejected/

STEP 6
合并 master

行为变更与记录同步入库——制度记忆持续生长

🪞自举的完整闭环:extensions 组让 Agent 巡检/挂载活插件、cordis_* 工具让模型给自己装工具、Agent Notes 由 Agent 撰写、工具目录由 Agent 贡献的插件自动生成文档——dsh 的建造过程就是它运行时能力的最大用户。社区侧的 learn-claude-code(76k stars 的"从零造 harness"课程)用 17 课教人手写这些机制——下一章你会看到,它的课程目录与 dsh 的插件目录几乎一一对应。
Chapter 13

理论透镜:旧问题的新皮肤

dsh 的每个设计都能在计算机科学里找到血统。戴上三副透镜——事件溯源、效果系统、操作系统——那些"为什么"会突然全部对齐。

"
Agent harness 的问题,多数是被重新发明过的旧问题——只是这次运行在自然语言上。事件溯源·效果系统·操作系统:三副透镜,一次对齐。
🔍

透镜 A · 事件溯源 Event Sourcing

The log is the database
对号入座:dsh 的会话架构就是事件溯源(Event Sourcing)+ CQRS 的教科书实现——而且它把这套范式最疼的"演进治理"也提前踩平了。
事件溯源概念dsh 中的化身备注
Event Store追加式会话日志(SessionEvent + SessionEventMap 事件目录)写路径唯一:到过模型眼前的必须先落日志
读模型投影deriveMessages() / session-projection 增量折叠UI、fork、遥测都是只读投影——读写分离
SnapshotstateOf() / projection-cache 持久缓存缓存过期只损失重放时间,绝不给错值
事件流分支fork(parentSession + seed 引用同一条日志)零拷贝分叉
读模型版本治理compatibleVersions 声明式读兼容(本周刚落)事件溯源系统最经典的痛,dsh 用一张声明表解决
🔍

透镜 B · 效果系统与时空可组合性

The Cordis paper, demystified
对号入座:Cordis 不是"又一个插件框架"——它是一篇形式化论文(arXiv:2608.25512)的实现。论文把动态组合拆成两个正交维度:

时间可组合 Temporal

"组件被移除时,其副作用可被完全撤销。"机制 = 可逆效果(revertible effects):每次上下文变换都保留逆操作。你在第 2 章看到的 ctx.effect(() => { … return () => … }) 就是它的运行时形态——热重载、动态插件、scope 生命周期之所以"正确而非碰巧正确",根子在这。

空间可组合 Spatial

"声明式管理组件间依赖,并对其变化做出响应。"机制 = 响应式协同效果(reactive coeffects):上下文变化对照组件的协同效果规约,触发其激活/停用——你在 inject = ['greeter'] 里见的就是它:依赖即激活条件,加载顺序被声明取代。

论文的雄心在最后一步:一个演算(calculus)把单组件的保证扩展到任意交错的组件系统——"不同组件的效果可交错而不互相干扰"的观察等价性。这正是 256 个包还能保持秩序的理论底座。值得一提的是:论文把自进化 Agent harness 列为该范式的头号动机案例——先有理论,再造 harness,顺序本身就是稀缺品。

🔍

透镜 C · 操作系统:抽象与虚拟化的哲学

dsh is an OS for agents — literally
教科书怎么说:经典操作系统概论给 OS 两重身份——资源管理者(管 CPU、内存、设备、文件)与扩展机器(把丑陋的裸机抽象成好用的假象);四个特征——并发、共享、虚拟、异步。dsh 的每个支柱都能对号入座:资源管理者 ↔ 上下文/token/工具预算/后台作业的调度;并发 ↔ 多 Agent 与工具并发池;共享 ↔ 共享工作区与 storage 枢纽;异步 ↔ inbox/ jobs/schedule——连"执行速度不可预知"这条异步性后果都有对应物(第 11 章那条防御规则的原话就是:Async state is not synchronous state)。而"虚拟",是 dsh 用得最重的一招,值得单独拆开。
🪞

抽象的哲学 · 扩展机器是怎么造出来的

Abstraction: the extended machine
一句话直觉:OS 教科书说,抽象就是把"丑陋的硬件"藏起来,给上层一个简洁到可以忽略实现的接口。dsh 给模型造的,正是一台这样的扩展机器——模型眼里的世界是被层层构造出来的。

第一层 · 指令集抽象

工具 schema 就是模型的 ISA(指令集架构)。模型不学"如何 spawn 进程",它只学 bash("ls")——就像程序员写 read() 而不碰磁盘控制器。守卫流水线 = syscall 入口检查;schema 的稳定性承诺 = ABI 兼容承诺("换后端不改指令集",正是设备无关接口的定义)。

第二层 · 接缝抽象

ctx.shell / ctx.fs / ctx.llm 是教科书"设备独立性软件"层的翻版:上层(工具消费者)只认接口,下层(Provider)可任意更换。dsh 判定好抽象的三角色判据——Service Definition / Provider / Consumer 缺一不可——与教科书判定设备独立性的判据同构。

第三层 · 事件抽象

"世界上发生过什么"被抽象成类型化事件流(SessionEventMap)——如同 OS 把一切 I/O 抽象成文件读写。模型看见了什么、做了什么、结果是什么,统一成一种可重放的货币。

教科书也提醒:抽象必然泄漏(leaky abstraction)。模型有时确实需要知道真实世界细节(工作目录、平台差异)——dsh 的对策不是假装不泄漏,而是把泄漏面制度化:system-prompt 的环境描述、context 插件(time-context / tmux-context)按需注入真实世界坐标。

🌀

虚拟化的哲学 · 一份物理,多份逻辑

Virtualization: one physical, many logical
一句话直觉:教科书定义虚拟化为"把一份物理实体变成多份逻辑对应物"(时分复用 CPU → 虚拟处理器;空分复用内存 → 虚拟存储器;SPOOLing → 虚拟设备)。dsh 最大的手笔是:它虚拟化的不是 CPU 或内存,而是"整台执行机器"本身。

整机虚拟化(dsh 的招牌)

fs 与 subprocess 两个 Provider 共享同一个"执行世界"并作为整体切换:本地世界、OS 沙箱世界、E2B 远程世界。Agent 坚信自己在操作一台电脑——但"那台电脑"是配置出来的。这就是虚拟机监控器的定义:客户机(模型的世界观)与宿主机(你的 Mac)彻底解耦。第 6 章的拨动开关演示,本质上是在热迁移整台虚拟机。

内存虚拟化(上下文即内存)

上下文窗口 = 稀缺的物理内存。对照精确得可怕:compaction = 页面置换(把冷页压成摘要);spill = swap(工具结果换出到 spillStore,定位器就是 swap handle,可按需换入);scope = 页表(决定这个 Agent 的地址空间里哪些页可见);shadowing = 私有映射(同名工具只在本地改写,如同写时复制);agent.inject() = 动态映射新页进下一次请求。

处理器虚拟化(时分复用)

教科书:一个物理 CPU 时分复用出 N 个虚拟处理器。dsh:一个 agent-loop 驱动器时分复用地驱动注册表里的多个 Agent;jobs 运行时是后台调度器;工具调用的有界滚动池就是并发度控制(= OS 的进程数限制)。

设备虚拟化(SPOOLing 精神)

教科书用 SPOOLing 把独占打印机变成共享逻辑设备。dsh:terminal_* 把一次性命令执行虚拟成可复用、可排队的持久设备(PTY);jobs 把"跑个后台任务"虚拟成统一的作业对象;time-context 更妙——每一步都有自己的虚拟时钟视图。

教科书还会问:虚拟化的代价是什么?间接与治理。dsh 的回答也教科书式:用不变量治理(model-visible ⇒ logged)、用断言执法、用投影缓存把间接的代价压到尾部重放。

🔍

速查表 · OS 概念 ↔ dsh 化身

The complete mapping
对号入座:把三副透镜的结论浓缩成一张速查表。点左侧任意 OS 概念,看它的 dsh 化身。
← 点一个概念开始
🧅互动演示 · 一次 bash 调用的抽象栈(剥洋葱)
点击任意一层,看它向上隐藏了什么。
🔍

把镜头拉远 · 整个领域在收敛

Convergent evolution
证据:learn-claude-code(76k stars 的"从零造 Claude Code"课程)把 harness 拆成 17 个必学机制——与 dsh 的插件目录逐行对得上。社区教材和工业实现独立收敛到同一张功能清单,这就是"canonical harness mechanisms"存在的证明。
🧭终章一句话:Agency comes from the model; the harness is the environment. 模型给智能,harness 给身体。Claude Code 把身体调教成最好的产品,Codex 把身体锻造成最硬的内核,Hermes 让身体随岁月生长——而 dsh 说:身体的所有零件都应该可拆卸。哪条路线赢不重要,重要的是 2026 年这四条路线都在场上。
深挖 · 三副透镜的失效边界(诚实的部分)
  • 事件溯源透镜:dsh 的日志是"单 Agent 会话粒度"的事件流,没有全局事件总线跨会话排序——跨 Agent 的一致性(Agent Teams 的任务板)用的是另一套持久状态,不是事件溯源。
  • 效果系统透镜:可逆效果保证的是框架内注册的撤销;spawn 出的子进程、写出的真实文件属于"外部世界",只能靠守卫规则(如拆除达到静止)约定,无法由演算保证。
  • OS 类比透镜:最大的错位在调度——OS 调度的是确定性的指令流,dsh"调度"的 Agent 会自己决定何时让出 CPU(结束回合)。这是全新问题,四家 harness 都还在用朴素方案。
  • 虚拟化透镜:dsh 的"整机虚拟化"依赖一条共享不变量——fs 与 subprocess 必须指向同一个执行世界(这是约定,不是通用 VMM 的强制隔离);也没有指令级仿真——远程世界里跑不了只有本地才有的程序。抽象也必然泄漏:模型有时需要真实世界坐标(路径/平台),dsh 的对策是把泄漏面制度化(环境描述 + context 插件按需注入),而非假装密封。
Chapter 14

实战与生态:扩展点速查 · 安全模型

在 dsh 里加功能,第一步是"选对事件域"。点左边任何目标,右边高亮对应机制——这是官方扩展手册的浓缩版。

🪝

与 Claude Code / Codex 兼容

hooks 分组内置 Claude Code / Codex 共享线协议库(wire-protocol),acp profile 提供自动化专用 Agent Client Protocol 服务器——可把现有生态工具接进来,也能把 Claude Code / Codex 当子 Agent 调。

🐍

Python SDK 同构

Python 侧暴露的是 profile 选择与有序补丁文件(不是完整 Cordis 树);持久外部插件经 dsh plugin 安装。JSON-RPC 协议与 TS 客户端/服务端在 sdk 分组。

🌍

生态与社区

插件用 GitHub topic dsh-plugin 获得可发现性;问题走 GitHub Discussions;官方 Discord 社区。文档站:deepseek-harness.github.io。

🛡️安全模型(SAFETY.md 原话摘录):这是未经安全审计的实验性软件,不得视为安全或生产就绪。它能执行模型生成的代码、加载第三方插件、访问网络/进程/凭据/文件。沙箱、审批、权限控制只是降低风险,不保证隔离——不要把 dsh 当作不可信工作负载的唯一安全控制。官方建议:最小权限运行;优先用一次性虚拟机/容器/专用环境;备份可触及的文件;允许前审查插件、配置与待执行命令。