relay-dsh-plugin-claude 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,23 +6,36 @@
6
6
  [![GitHub stars](https://img.shields.io/github/stars/yangbobo2021/relay-dsh-plugin-claude?style=flat)](https://github.com/yangbobo2021/relay-dsh-plugin-claude/stargazers)
7
7
  [![MIT license](https://img.shields.io/github/license/yangbobo2021/relay-dsh-plugin-claude)](LICENSE)
8
8
  [![DSH compatibility](https://img.shields.io/badge/DSH-0.1.1--rc.2-2f7d68)](https://github.com/deepseek-ai/deepseek-harness)
9
- [![npm provenance](https://img.shields.io/badge/npm_provenance-verified-2f9e44)](https://www.npmjs.com/package/relay-dsh-plugin-claude/v/0.1.1-rc.2)
9
+ [![npm provenance](https://img.shields.io/badge/npm_provenance-verified-2f9e44)](https://www.npmjs.com/package/relay-dsh-plugin-claude/v/0.1.4)
10
10
 
11
11
  English | [中文](README.zh.md)
12
12
 
13
13
  **npm package:** [`relay-dsh-plugin-claude`](https://www.npmjs.com/package/relay-dsh-plugin-claude)
14
14
  · [All Relay DSH plugins](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/dsh-plugins.md)
15
15
 
16
- [![Live npm-installed Relay plugins in official DSH](https://raw.githubusercontent.com/yangbobo2021/Relay/codex/relay-foundation/docs/media/dsh-plugin-suite-demo.gif)](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/dsh-plugins.md)
16
+ **Run Claude Code inside official DeepSeek Harness without switching interfaces
17
+ or maintaining a DSH fork.**
17
18
 
18
- *Real npm-installed demo on official DSH: live Codex and Claude replies, a
19
- workspace file preview, and an executed terminal command. [Watch the H.264
20
- MP4](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/media/dsh-plugin-suite-demo.mp4?raw=1).*
19
+ `relay-dsh-plugin-claude` adds **Claude Code as a native conversation backend**
20
+ to the official [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)
21
+ (DSH) Web UI. You keep DSH's workspace, conversation history, composer,
22
+ approvals, questions, and tool display while each DSH Session continues one
23
+ Claude Agent SDK session. The plugin installs independently; no Relay checkout
24
+ is required.
21
25
 
22
- `relay-dsh-plugin-claude` adds **Claude Code as a conversation backend** to the
23
- official [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)
24
- (DSH) Web UI. After installation, **Claude Code** appears in DSH's New Session
25
- mode menu. One DSH Session is bound to one Claude Agent SDK session.
26
+ ## Try It on Official DSH
27
+
28
+ Complete normal Claude Code authentication with `claude` before the first
29
+ Session. The install requires Node.js 22.13 or newer and `pnpm` on `PATH`. Then
30
+ stop DSH Web, install the tested release candidate, and restart DSH:
31
+
32
+ ```bash
33
+ npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add relay-dsh-plugin-claude@next
34
+ npx @deepseek-ai/dsh@0.1.1-rc.2 web
35
+ ```
36
+
37
+ Open **New Session**, select a workspace, choose **Claude Code** from the mode
38
+ menu, and send a message.
26
39
 
27
40
  ![Codex and Claude Code in the DSH New Session mode menu](docs/images/dsh-new-session-backends.jpg)
28
41
 
@@ -30,6 +43,13 @@ The screenshot was captured from official DSH `0.1.1-rc.2` with the Codex and
30
43
  Claude plugins installed. If you install only this plugin, only **Claude Code**
31
44
  is added.
32
45
 
46
+ [Review all Relay DSH plugins](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/dsh-plugins.md)
47
+ · [report an install result](https://github.com/yangbobo2021/relay-dsh-plugin-claude/issues)
48
+
49
+ If this removes an interface switch from your DSH workflow,
50
+ [star this plugin](https://github.com/yangbobo2021/relay-dsh-plugin-claude).
51
+ That signal helps other DSH users find a tested Claude Code backend.
52
+
33
53
  ## Do I Need This Plugin?
34
54
 
35
55
  Install it when you want to:
@@ -45,7 +65,7 @@ Install it when you want to:
45
65
  You do not need it to use DSH's standard agents. It also does not add Relay
46
66
  Events, file browsing, or a terminal panel. Those are separate optional plugins.
47
67
 
48
- ## Quick Start With Official DSH
68
+ ## Complete Setup and Compatibility
49
69
 
50
70
  The steps below were validated with:
51
71
 
@@ -89,7 +109,7 @@ Use `@latest` to install the current stable release:
89
109
  npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add relay-dsh-plugin-claude@latest
90
110
  ```
91
111
 
92
- At the time of writing, `latest` resolves to stable version `0.1.0`. The linked
112
+ At the time of writing, `latest` resolves to stable version `0.1.4`. The linked
93
113
  npm page is the source of truth for the current version.
94
114
 
95
115
  #### npm prerelease (recommended during DSH preview)
@@ -102,7 +122,7 @@ contains the latest model-selection synchronization fix:
102
122
  npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add relay-dsh-plugin-claude@next
103
123
  ```
104
124
 
105
- At the time of writing, `next` resolves to `0.1.1-rc.2`.
125
+ At the time of writing, `next` resolves to `0.1.4`.
106
126
 
107
127
  #### GitHub development build
108
128
 
@@ -116,7 +136,7 @@ npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add github:yangbobo2021/rel
116
136
  full Commit SHA instead. For example:
117
137
 
118
138
  ```bash
119
- npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add github:yangbobo2021/relay-dsh-plugin-claude#v0.1.1-rc.2
139
+ npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add github:yangbobo2021/relay-dsh-plugin-claude#v0.1.4
120
140
  ```
121
141
 
122
142
  The official DSH CLI initializes the `web` Profile if it does not exist, asks
@@ -151,6 +171,31 @@ at startup, so restarting after installation, update, or removal is required.
151
171
  There is no separate activation command. A successful install plus a DSH restart
152
172
  activates the bundle and registers the managed **Claude Code** mode automatically.
153
173
 
174
+ ### 5. Import an existing Claude terminal Session
175
+
176
+ 1. Open the target Workspace or one of its Sessions in DSH.
177
+ 2. Select **Import Claude Sessions** below the Workspace list.
178
+ 3. Review the full Session IDs, titles, source paths, activity times, and import
179
+ status. Select one, several, or all Sessions.
180
+ 4. Select **Import selected**, then open the imported DSH Session.
181
+ 5. Send the next message and confirm that it continues the same native Claude
182
+ Session.
183
+
184
+ The selector uses the Claude Agent SDK's public Session APIs and matches the
185
+ terminal `/resume` scope. It excludes worktrees, SDK/headless Sessions,
186
+ already-bound Sessions, and Sessions outside the exact registered Workspace.
187
+ The imported history is a one-time presentation snapshot of user text, visible
188
+ assistant text and thinking, and completed textual tool activity. Unknown or
189
+ private blocks are skipped; Claude's source transcript is never modified.
190
+
191
+ The SDK inventory does not expose a durable running/idle status. Avoid writing
192
+ the same Session from another Claude client while continuing it in DSH. If
193
+ resume fails, DSH keeps the exact imported binding for retry and never silently
194
+ creates a replacement Session. Import is unavailable with the CLI fallback.
195
+ See
196
+ [`docs/spec/claude-native-session-import.md`](docs/spec/claude-native-session-import.md)
197
+ for the complete contract and delivery cases.
198
+
154
199
  ## What Works
155
200
 
156
201
  - One persistent Claude Agent SDK session per DSH Session
@@ -161,7 +206,47 @@ activates the bundle and registers the managed **Claude Code** mode automaticall
161
206
  final answer
162
207
  - DSH approval and user-question flows
163
208
  - Interruption and session continuation
209
+ - Selective import and exact-ID continuation of existing Claude terminal Sessions
164
210
  - Generic DSH tools exposed through an in-process Claude SDK MCP server
211
+ - Dedicated native Claude `Glob` and `Grep` search tools on every SDK query
212
+ - Pre-persistence redaction of sensitive environment values from tool output
213
+
214
+ ### Sensitive environment output
215
+
216
+ Before each new or resumed SDK turn, the plugin resolves Claude's effective
217
+ environment and classifies credential-bearing variable names such as `SECRET`,
218
+ `TOKEN`, `PASSWORD`, and `API_KEY`. Exact occurrences of those values in tool
219
+ results are replaced before the result reaches Claude, DSH activity, or the
220
+ native Claude JSONL transcript. Variables explicitly listed in Claude sandbox
221
+ credential settings are protected as well. Ordinary environment values and
222
+ successful tool outputs without a match are left unchanged.
223
+
224
+ This protection covers successful tool results; it does not rewrite user
225
+ prompts, tool inputs, arbitrary values that are not identifiable from host
226
+ configuration, or SDK execution failures without a replaceable tool output.
227
+ See
228
+ [`docs/spec/claude-tool-output-redaction.md`](docs/spec/claude-tool-output-redaction.md)
229
+ for the complete contract and acceptance cases.
230
+
231
+ ### Explicit local Claude plugins
232
+
233
+ Trusted Host configuration can load an uninstalled local Claude plugin into
234
+ business conversations by setting `claudePlugins` on this DSH plugin:
235
+
236
+ ```yaml
237
+ config:
238
+ claudePlugins:
239
+ - type: local
240
+ path: /absolute/path/to/plugin
241
+ ```
242
+
243
+ The order and optional `skipMcpDiscovery` Boolean are forwarded to every new and
244
+ resumed Claude Agent SDK query. Hidden title-generation Sessions use no local
245
+ plugins. A non-empty list is rejected when the CLI fallback is active because
246
+ the CLI backend cannot honor this SDK option. Local plugins execute as the DSH
247
+ user, so configure only reviewed paths. See
248
+ [`docs/spec/claude-local-plugins.md`](docs/spec/claude-local-plugins.md) for the
249
+ full contract and acceptance cases.
165
250
 
166
251
  Tools execute through the owning Agent's DSH tool runtime and remain subject to
167
252
  DSH permissions and Claude approval behavior. The tool bridge requires the
package/README.zh.md CHANGED
@@ -6,29 +6,48 @@
6
6
  [![GitHub Stars](https://img.shields.io/github/stars/yangbobo2021/relay-dsh-plugin-claude?style=flat)](https://github.com/yangbobo2021/relay-dsh-plugin-claude/stargazers)
7
7
  [![MIT 许可证](https://img.shields.io/github/license/yangbobo2021/relay-dsh-plugin-claude)](LICENSE)
8
8
  [![DSH 兼容版本](https://img.shields.io/badge/DSH-0.1.1--rc.2-2f7d68)](https://github.com/deepseek-ai/deepseek-harness)
9
- [![npm 来源证明](https://img.shields.io/badge/npm_provenance-verified-2f9e44)](https://www.npmjs.com/package/relay-dsh-plugin-claude/v/0.1.1-rc.2)
9
+ [![npm 来源证明](https://img.shields.io/badge/npm_provenance-verified-2f9e44)](https://www.npmjs.com/package/relay-dsh-plugin-claude/v/0.1.4)
10
10
 
11
11
  [English](README.md) | 中文
12
12
 
13
13
  **npm 包名:** [`relay-dsh-plugin-claude`](https://www.npmjs.com/package/relay-dsh-plugin-claude)
14
14
  · [全部 Relay DSH 插件](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/dsh-plugins.zh.md)
15
15
 
16
- [![在官方 DSH 中实装运行的 Relay 插件](https://raw.githubusercontent.com/yangbobo2021/Relay/codex/relay-foundation/docs/media/dsh-plugin-suite-demo.gif)](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/dsh-plugins.zh.md)
17
-
18
- *演示来自官方 DSH 上的真实 npm 安装:Codex 与 Claude 返回真实回复,Files
19
- 预览工作区文件,Terminal 实际执行命令。[观看 H.264
20
- MP4](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/media/dsh-plugin-suite-demo.mp4?raw=1)。*
16
+ **无需切换界面或维护 DSH Fork,直接在官方 DeepSeek Harness 中运行 Claude
17
+ Code。**
21
18
 
22
19
  `relay-dsh-plugin-claude` 为官方
23
20
  [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)Web
24
- 界面增加 **Claude Code 对话后端**。安装后,DSH 的新建会话模式菜单中会出现
25
- **Claude Code**。每个 DSH Session 会绑定一个 Claude Agent SDK Session。
21
+ 界面增加原生 **Claude Code 对话后端**。你可以继续使用 DSH 的工作区、对话
22
+ 历史、输入框、审批、提问和工具展示;每个 DSH Session 会持续绑定一个 Claude
23
+ Agent SDK Session。本插件可独立安装,不需要下载 Relay 仓库。
24
+
25
+ ## 在官方 DSH 中立即试用
26
+
27
+ 首次创建 Session 前,请先运行 `claude` 完成 Claude Code 的正常认证。安装
28
+ 要求 Node.js 22.13 或更高版本,并且 `pnpm` 已加入 `PATH`。然后停止 DSH Web,
29
+ 安装经过测试的候选版本并重新启动:
30
+
31
+ ```bash
32
+ npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add relay-dsh-plugin-claude@next
33
+ npx @deepseek-ai/dsh@0.1.1-rc.2 web
34
+ ```
35
+
36
+ 打开 **New Session**,选择工作区,再从模式菜单中选择 **Claude Code** 并发送
37
+ 消息。
26
38
 
27
39
  ![DSH 新建会话菜单中的 Codex 和 Claude Code](docs/images/dsh-new-session-backends.jpg)
28
40
 
29
41
  上图来自安装了 Codex 和 Claude 插件的官方 DSH `0.1.1-rc.2`。如果只安装
30
42
  本插件,菜单中只会新增 **Claude Code**。
31
43
 
44
+ [查看全部 Relay DSH 插件](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/dsh-plugins.zh.md)
45
+ · [反馈安装结果](https://github.com/yangbobo2021/relay-dsh-plugin-claude/issues)
46
+
47
+ 如果它能让你少切换一个界面,欢迎
48
+ [Star 本插件](https://github.com/yangbobo2021/relay-dsh-plugin-claude)。
49
+ 这些真实信号能帮助更多 DSH 用户找到经过验证的 Claude Code 后端。
50
+
32
51
  ## 什么情况下需要这个插件?
33
52
 
34
53
  以下情况适合安装:
@@ -44,7 +63,7 @@ MP4](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/medi
44
63
  使用 DSH 标准 Agent 不需要安装本插件。本插件也不提供 Relay Events、文件
45
64
  浏览和终端面板,这些能力由其他可选插件提供。
46
65
 
47
- ## 基于官方 DSH 的快速安装
66
+ ## 完整安装与兼容性说明
48
67
 
49
68
  以下步骤已经在这些版本上实际验证:
50
69
 
@@ -85,7 +104,7 @@ claude
85
104
  npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add relay-dsh-plugin-claude@latest
86
105
  ```
87
106
 
88
- 本文更新时,`latest` 指向稳定版 `0.1.0`。最新版本请以链接中的 npm 页面
107
+ 本文更新时,`latest` 指向稳定版 `0.1.4`。最新版本请以链接中的 npm 页面
89
108
  为准。
90
109
 
91
110
  #### npm 预发布版(DSH 预览阶段推荐)
@@ -97,7 +116,7 @@ npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add relay-dsh-plugin-claude
97
116
  npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add relay-dsh-plugin-claude@next
98
117
  ```
99
118
 
100
- 本文更新时,`next` 指向 `0.1.1-rc.2`。
119
+ 本文更新时,`next` 指向 `0.1.4`。
101
120
 
102
121
  #### GitHub 开发版
103
122
 
@@ -111,7 +130,7 @@ npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add github:yangbobo2021/rel
111
130
  SHA。例如:
112
131
 
113
132
  ```bash
114
- npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add github:yangbobo2021/relay-dsh-plugin-claude#v0.1.1-rc.2
133
+ npx @deepseek-ai/dsh@0.1.1-rc.2 plugin --profile web add github:yangbobo2021/relay-dsh-plugin-claude#v0.1.4
115
134
  ```
116
135
 
117
136
  官方 DSH CLI 会在需要时初始化 `web` Profile,通过 `pnpm` 安装所选软件包和
@@ -143,6 +162,27 @@ npx @deepseek-ai/dsh@0.1.1-rc.2 web
143
162
  插件不需要单独的激活命令。安装成功并重启 DSH 后,Bundle 会自动激活,
144
163
  并注册由插件管理的 **Claude Code** 模式。
145
164
 
165
+ ### 5. 导入已有的 Claude 终端会话
166
+
167
+ 1. 在 DSH 中打开目标工作区或其中一个 Session。
168
+ 2. 点击工作区列表下方的 **导入 Claude 会话**。
169
+ 3. 检查完整 Session ID、标题、源路径、活动时间和导入状态,然后选择一个、
170
+ 多个或全部会话。
171
+ 4. 点击 **导入所选会话**,再打开导入后的 DSH Session。
172
+ 5. 发送下一条消息,确认它继续的是同一个原生 Claude Session。
173
+
174
+ 选择器只使用 Claude Agent SDK 的公开 Session API,其范围与终端 `/resume`
175
+ 一致。它会排除 worktree、SDK/headless、已经绑定以及不属于当前精确注册工作区
176
+ 的 Session。导入历史是一次性的展示快照,包含用户文本、可见的助手文本与
177
+ thinking,以及已有结果的文本工具活动。未知或私有块会被跳过,Claude 源转录
178
+ 不会被修改。
179
+
180
+ SDK 列表不提供持久的 running/idle 状态。通过 DSH 继续会话时,应避免另一个
181
+ Claude 客户端同时写入同一个 Session。如果恢复失败,DSH 会保留原始绑定供
182
+ 重试,绝不会静默创建替代 Session。CLI fallback 不支持导入。完整契约和交付
183
+ 用例见
184
+ [`docs/spec/claude-native-session-import.md`](docs/spec/claude-native-session-import.md)。
185
+
146
186
  ## 支持的能力
147
187
 
148
188
  - 每个 DSH Session 持续绑定一个 Claude Agent SDK Session
@@ -152,7 +192,40 @@ npx @deepseek-ai/dsh@0.1.1-rc.2 web
152
192
  - 在对话中持久展示 Claude 最终回答所引用的工作区图片
153
193
  - DSH 原生审批和用户提问流程
154
194
  - 中断和会话延续
195
+ - 选择性导入已有 Claude 终端会话,并通过原始 ID 继续
155
196
  - 通过进程内 Claude SDK MCP Server 提供通用 DSH 工具
197
+ - 在每次 SDK 查询中启用 Claude 原生 `Glob` 与 `Grep` 专用搜索工具
198
+ - 在工具结果持久化前脱敏其中的敏感环境变量值
199
+
200
+ ### 敏感环境变量输出脱敏
201
+
202
+ 每次新建或恢复 SDK turn 前,插件都会解析 Claude 的有效环境,并识别变量名中
203
+ 含有 `SECRET`、`TOKEN`、`PASSWORD`、`API_KEY` 等凭据特征的值。工具结果中
204
+ 与这些值完全相同的内容,会在进入 Claude、DSH activity 或 Claude 原生 JSONL
205
+ 转录之前替换。Claude sandbox 凭据设置中显式列出的环境变量也会受到保护。
206
+ 普通环境值及没有命中的成功工具输出保持不变。
207
+
208
+ 该保护仅覆盖成功工具结果,不会改写用户消息、工具输入、无法从 Host 配置
209
+ 识别的任意内容,或 SDK 未提供可替换输出的执行失败。完整契约与验收用例见
210
+ [`docs/spec/claude-tool-output-redaction.md`](docs/spec/claude-tool-output-redaction.md)。
211
+
212
+ ### 显式加载本地 Claude 插件
213
+
214
+ 可信的 Host 配置可以通过本 DSH 插件的 `claudePlugins` 字段,将未安装的
215
+ 本地 Claude 插件加载到业务对话中:
216
+
217
+ ```yaml
218
+ config:
219
+ claudePlugins:
220
+ - type: local
221
+ path: /absolute/path/to/plugin
222
+ ```
223
+
224
+ 插件顺序和可选的 Boolean 字段 `skipMcpDiscovery` 会传递给每次新建及恢复的
225
+ Claude Agent SDK 查询。标题生成等隐藏辅助 Session 不加载这些插件。CLI
226
+ fallback 无法实现该 SDK 能力,因此非空列表会被明确拒绝。因为本地插件以
227
+ DSH 用户身份运行,只应配置经过审查的路径。完整契约和验收用例见
228
+ [`docs/spec/claude-local-plugins.md`](docs/spec/claude-local-plugins.md)。
156
229
 
157
230
  工具通过当前 Agent 的 DSH 工具运行时执行,并继续受到 DSH 权限和 Claude
158
231
  审批机制约束。工具桥接依赖默认 SDK 后端。如果开发者明确选择 CLI fallback,
@@ -0,0 +1,56 @@
1
+ # Claude Local Plugin Loading
2
+
3
+ ## Contract
4
+
5
+ The DSH host configuration may provide `claudePlugins`, an ordered array of
6
+ Claude Agent SDK local-plugin descriptors:
7
+
8
+ ```yaml
9
+ config:
10
+ claudePlugins:
11
+ - type: local
12
+ path: /absolute/path/to/plugin
13
+ skipMcpDiscovery: false
14
+ ```
15
+
16
+ Each descriptor must contain `type: local` and a non-empty `path`.
17
+ `skipMcpDiscovery`, when present, must be Boolean. Unknown fields are rejected.
18
+ Relative paths remain relative and are interpreted by the Claude Agent SDK.
19
+ Relay does not check path existence before the SDK starts, avoiding a separate
20
+ check/use result from the SDK's authoritative load.
21
+
22
+ The configuration is trusted startup configuration: a local Claude plugin can
23
+ load instructions, hooks, agents, commands, Skills, and MCP definitions with the
24
+ same operating-system access as the Claude process. It is not accepted from a
25
+ conversation message or model output.
26
+
27
+ ## Session behavior
28
+
29
+ - A configured list is cloned into every new business Claude SDK Session.
30
+ - A linked DSH Session resumed after a Host restart receives the current Host
31
+ list, including when its older link record predates this option.
32
+ - Every query for that Claude Session carries the same ordered list, including
33
+ resumed queries.
34
+ - Message-level plugin replacement is rejected before `query()`; conversation
35
+ input and model output cannot introduce a local plugin path.
36
+ - An explicit empty list disables configured plugins for that Session.
37
+ - Hidden auxiliary Sessions, including title generation, always use an explicit
38
+ empty list. They must not run user plugin hooks or discover user plugin Skills.
39
+ - With no configured list, Relay omits the SDK `plugins` option and preserves
40
+ existing behavior.
41
+ - The CLI backend cannot load SDK local-plugin paths. It rejects a non-empty list
42
+ with `CLAUDE_LOCAL_PLUGINS_REQUIRE_SDK` instead of silently dropping it.
43
+
44
+ ## Delivery acceptance
45
+
46
+ | ID | Scenario | Required result |
47
+ | --- | --- | --- |
48
+ | LP1 | New Session | Runtime creation and first SDK query receive the exact ordered descriptors. |
49
+ | LP2 | Continued Session | A later query uses `resume` and receives the same descriptors. |
50
+ | LP3 | Host restart | Runtime resume receives the current configured descriptors without relying on the persisted link record. |
51
+ | LP4 | No configuration | Runtime and SDK options do not gain a `plugins` property. |
52
+ | LP5 | Auxiliary Session | Runtime creation receives `plugins: []`. |
53
+ | LP6 | Invalid configuration | Relay fails before creating a Session or invoking `query()`. |
54
+ | LP7 | CLI backend | A non-empty descriptor list fails explicitly and spawns no process. |
55
+ | LP8 | Real SDK load | With no CLI installation or setting source, SDK init reports the target plugin and namespaced Skill exactly once. |
56
+ | LP9 | Message injection | A message-level `plugins` field fails before SDK `query()` and does not alter the Session list. |
@@ -0,0 +1,114 @@
1
+ # Native Claude Session Import
2
+
3
+ This specification defines how `relay-dsh-plugin-claude` discovers an existing
4
+ Claude terminal Session, creates its DSH presentation, and continues the exact
5
+ same native Session. It is the delivery contract for migration case
6
+ `CLD-SES-004`.
7
+
8
+ ## Supported backend and source boundary
9
+
10
+ Import is available only when the active Claude Agent SDK exposes the public
11
+ `listSessions`, `getSessionInfo`, and `getSessionMessages` functions. The Host
12
+ must call those APIs and must not parse Claude's private JSONL storage. The CLI
13
+ fallback reports `CLAUDE_SESSION_IMPORT_UNAVAILABLE`; it must not return an empty
14
+ or fabricated inventory.
15
+
16
+ The scan calls `listSessions` with the exact registered DSH Workspace path,
17
+ `includeWorktrees: false`, and `includeProgrammatic: false`. This matches the
18
+ Claude terminal `/resume` inventory: SDK/headless, daemon, worktree, sidechain,
19
+ and other-Workspace Sessions are not import candidates. Every returned `cwd` is
20
+ canonicalized and checked again by the plugin because SDK filtering alone is not
21
+ the authorization boundary.
22
+
23
+ The public SDK inventory is a point-in-time snapshot. It does not expose a
24
+ durable running/idle field, so DSH must not label a candidate as completed or
25
+ promise that another Claude client is no longer writing it.
26
+
27
+ ## Inventory and selection
28
+
29
+ Each candidate exposes the full native Session ID, deterministic title, source
30
+ path, source `lastModified`, and either `ready` or `recoverable` status. The
31
+ ordering is descending source activity time with Session ID as a deterministic
32
+ tie-breaker. Already-bound Sessions remain in aggregate counts but are not
33
+ selectable or disclosed as candidates. Sessions outside the exact Workspace are
34
+ neither counted nor disclosed.
35
+
36
+ The UI defaults to every eligible candidate and supports selecting one, several,
37
+ all, or none. An empty selection cannot be submitted. The request carries the
38
+ exact selected `sessionIds`. Before creating or mutating a DSH Session, the Host
39
+ rescans and validates the entire selection. Empty, malformed, duplicate,
40
+ unknown, cross-Workspace, stale, or already-bound IDs reject the selection
41
+ without partial mutation. Omitting `sessionIds` retains the Host's import-all
42
+ API behavior; an explicit empty array is invalid.
43
+
44
+ After selection validation, an individual persistence or DSH composition
45
+ failure may produce a partial batch result. Its durable import state remains
46
+ recoverable and retrying the same source must continue that transaction instead
47
+ of creating a second DSH Session.
48
+
49
+ ## History projection
50
+
51
+ The Host reads the selected source again with `getSessionInfo` and
52
+ `getSessionMessages` immediately before reserving its binding. The source ID and
53
+ canonical `cwd` must still match. DSH receives a deterministic presentation seed
54
+ containing:
55
+
56
+ - top-level user text, whether the public SDK returns it as a string or text blocks;
57
+ - visible assistant text and SDK `thinking` blocks as DSH reasoning;
58
+ - a tool call only when its matching tool result exists;
59
+ - textual tool-result content and its error flag.
60
+
61
+ Malformed messages, pre-turn assistant content, system/private blocks, unmatched
62
+ tool calls or results, non-text tool-result blocks, and unknown future block
63
+ types are skipped and counted. They must never be converted into explanatory
64
+ model text. The source transcript is read-only and is never changed by import.
65
+
66
+ The initial DSH title comes from `customTitle`, `summary`, or `firstPrompt`, and
67
+ the DSH list recency comes from the source timestamps. History projection and
68
+ title persistence must complete before Workspace attachment is committed.
69
+
70
+ Import creates a one-time DSH presentation snapshot. It does not poll the source
71
+ or merge turns written later by a second Claude client. Turns sent through DSH
72
+ after import are persisted normally by DSH and the native Claude Session.
73
+
74
+ ## Binding and recovery
75
+
76
+ One DSH Session binds at most one native Claude Session, and one native Claude
77
+ Session binds at most one DSH Session. Imported DSH IDs are deterministic from
78
+ the complete source Session ID. The binding and the monotonic transaction states
79
+ `reserved`, `session-created`, `hydrated`, `attached`, and `committed` are
80
+ persisted before the next state is attempted.
81
+
82
+ Restart, duplicate request, concurrent request, and retry must converge on the
83
+ same DSH Session and native Session. Opening or sending the next DSH turn resumes
84
+ the exact imported native Session ID. If resume fails because the source is busy,
85
+ missing, or temporarily unavailable, the plugin reports
86
+ `CLAUDE_IMPORTED_SESSION_RESUME_FAILED`, keeps the binding, and creates no
87
+ replacement Session.
88
+
89
+ ## Web route
90
+
91
+ The Host exposes one exact POST route at `/api/relay/claude/import`. It accepts
92
+ JSON only, bounds request size, resolves the requested path through DSH's
93
+ registered Workspace service, and returns no-store responses. Loopback requests
94
+ are accepted. A non-loopback caller requires a constant-time checked Bearer token
95
+ configured by `claudeImportToken` or `RELAY_CLAUDE_IMPORT_TOKEN`.
96
+
97
+ ## Delivery acceptance
98
+
99
+ Delivery requires all of the following evidence:
100
+
101
+ 1. The historical plugin revision reproduces the absence of native Session
102
+ discovery/import for the same source fixture.
103
+ 2. Focused tests cover SDK capability failure, exact inventory options,
104
+ Workspace isolation, deterministic ordering, selection atomicity, source
105
+ revalidation, projection, one-to-one durability, concurrency, retry, and the
106
+ no-replacement resume rule.
107
+ 3. Client tests cover Workspace choice, selection, request payloads, chunked
108
+ NDJSON progress, error handling, disabled empty submission, and refresh order.
109
+ 4. A real installed SDK lists and reads a native terminal Session using only the
110
+ public APIs.
111
+ 5. Official DSH imports that Session, displays the projected history and title,
112
+ and sends the next turn to the same complete native Session ID.
113
+ 6. Typecheck, the full repository test suite, build, package-content inspection,
114
+ and remote CI all pass.
@@ -0,0 +1,40 @@
1
+ # Claude Search Tool Contract
2
+
3
+ ## Scope
4
+
5
+ The Claude Agent SDK backend exposes Claude's dedicated `Glob` and `Grep`
6
+ tools on every business and auxiliary query. This contract does not apply to
7
+ the text-only CLI fallback.
8
+
9
+ ## Availability
10
+
11
+ Native Claude builds may otherwise provide filename and content search only
12
+ through Bash. The plugin must opt into `Glob` and `Grep` through the SDK's
13
+ `allowedTools` option so both dedicated tools are present without an approval
14
+ round trip. It must do so for new and resumed Sessions and whether or not the
15
+ owning DSH turn contributes tools.
16
+
17
+ The bare allow entries intentionally auto-approve only these two native,
18
+ read-only search tools, so the SDK does not call `canUseTool` for them. They do
19
+ not grant any mutation tool. The plugin still registers the permission callback
20
+ for every tool that is not otherwise allowed, and the SDK remains authoritative
21
+ for search path resolution and access enforcement.
22
+
23
+ The search entries augment the allowlist. They must never replace an
24
+ `mcp__dsh__*` entry created by the DSH tool bridge or alter the configured
25
+ permission mode, permission callback, working directory, plugins, or Session
26
+ continuation options.
27
+
28
+ ## Delivery Acceptance
29
+
30
+ 1. A query without DSH-contributed tools allows exactly the dedicated `Glob`
31
+ and `Grep` additions and does not create a DSH MCP server.
32
+ 2. A query with DSH-contributed tools preserves every generated
33
+ `mcp__dsh__*` allow entry after `Glob` and `Grep`.
34
+ 3. A fresh real SDK Session uses native `Glob` followed by native `Grep` to
35
+ find a precommitted unique path and marker, with no Bash fallback, approval,
36
+ or workspace mutation.
37
+ 4. The same run returns the exact expected path and marker, and the recorded
38
+ SDK initialization advertises both tool names.
39
+ 5. Existing SDK option, interaction, image, plugin, and DSH tool-bridge tests
40
+ remain green.
@@ -0,0 +1,68 @@
1
+ # Claude Tool-Output Redaction
2
+
3
+ ## Status
4
+
5
+ This document defines the plugin-owned secret-redaction contract for the
6
+ default Claude Agent SDK backend. It is the tracked delivery specification for
7
+ `CLD-ENV-003` and GitHub Issue #29.
8
+
9
+ ## Contract
10
+
11
+ The plugin must resolve the effective Claude settings before every new or
12
+ resumed turn, using the same workspace and `settingSources` passed to the SDK.
13
+ The effective environment is the SDK process environment overlaid with the
14
+ resolved settings environment.
15
+
16
+ An environment value is sensitive when its non-empty variable name contains a
17
+ credential-bearing segment such as `SECRET`, `TOKEN`, `PASSWORD`, `PASSWD`,
18
+ `API_KEY`, `ACCESS_KEY`, `PRIVATE_KEY`, or `CREDENTIALS`. A variable explicitly
19
+ listed under `sandbox.credentials.envVars` is also sensitive, regardless of its
20
+ name. If multiple sensitive names have the same value, the lexicographically
21
+ first name supplies the deterministic replacement marker.
22
+
23
+ Before a successful tool result is delivered to the model, SDK consumers, or
24
+ native Session persistence, the plugin must run a synchronous SDK `PostToolUse`
25
+ callback. Every exact occurrence of a sensitive value in a string anywhere in
26
+ the structured tool response is replaced with
27
+ `[REDACTED_ENV:<VARIABLE_NAME>]`. Longer values are processed first so an
28
+ overlapping shorter value cannot partially expose them.
29
+
30
+ The callback must not return `updatedToolOutput` when no configured value
31
+ occurs. This preserves the original object and avoids an identity rewrite that
32
+ could compete with another legitimate output-rewriting hook.
33
+
34
+ The redacted result, not the raw result, must be visible in both normalized SDK
35
+ activity and the native Claude JSONL transcript. Tool execution status and
36
+ non-sensitive output remain unchanged.
37
+
38
+ ## Boundaries
39
+
40
+ This contract protects tool output containing values from the effective Claude
41
+ environment. It does not rewrite user prompts, tool inputs, arbitrary values
42
+ that cannot be classified from host configuration, files created by tools, or
43
+ errors for which the SDK emits `PostToolUseFailure` without a replaceable tool
44
+ output. It applies to the SDK backend; the explicit CLI fallback does not offer
45
+ the required pre-persistence hook contract.
46
+
47
+ The implementation must use the supported SDK result-replacement lifecycle.
48
+ Post-hoc edits to Claude JSONL files are forbidden because they are racy and can
49
+ damage Session continuation.
50
+
51
+ Claude treats output rewrites from multiple synchronous hooks as competing
52
+ replacements. A trusted administrator who installs another `PostToolUse` hook
53
+ that supersedes this plugin's redacted result must ensure that replacement does
54
+ not reintroduce a protected value; the plugin cannot sanitize output created
55
+ after its callback has returned.
56
+
57
+ ## Delivery Acceptance
58
+
59
+ 1. The historical `CLD-ENV-003` probe reproduces the pre-fix leak while the
60
+ Bash tool completes successfully.
61
+ 2. The same probe against the fixed plugin executes Bash exactly once, keeps
62
+ the expected final marker, and finds zero raw-secret occurrences in SDK
63
+ activity, the native transcript, diagnostics, and final text.
64
+ 3. Focused tests cover sensitive-name detection, explicit credential names,
65
+ nested structured output, ordinary values, no-op output, and both new and
66
+ resumed turns.
67
+ 4. Typecheck, the complete test suite, build, package dry-run, a real SDK probe,
68
+ and an official DSH end-to-end run all pass.