@norman-else/dsh-claude 0.1.5 → 0.1.7
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/INSTALL.md +55 -46
- package/LICENSE +21 -21
- package/README.md +191 -183
- package/cordis.patch.yml +12 -12
- package/legacy-preset/agent.cordis.yml +11 -11
- package/legacy-preset/preset.yml +4 -4
- package/lib/bin.mjs +1 -1
- package/lib/bin.mjs.map +1 -1
- package/lib/client.d.ts +5 -0
- package/lib/client.js +80 -149
- package/lib/client.js.map +1 -1
- package/lib/{events-qlmU1KrH.mjs → events-DP0Ov_Re.mjs} +3 -8
- package/lib/events-DP0Ov_Re.mjs.map +1 -0
- package/lib/index.d.mts +12 -2
- package/lib/index.mjs +163 -19
- package/lib/index.mjs.map +1 -1
- package/lib/{presenters-DbfG-9KQ.mjs → presenters-YMR2WMjn.mjs} +2 -2
- package/lib/presenters-YMR2WMjn.mjs.map +1 -0
- package/lib/{preset-installer-D8q3_-wJ.mjs → preset-installer-BKw-SdOm.mjs} +5 -20
- package/lib/preset-installer-BKw-SdOm.mjs.map +1 -0
- package/lib/preset-route.mjs +2 -2
- package/lib/preset-route.mjs.map +1 -1
- package/package.json +3 -1
- package/preset/claude/agent.cordis.yml +11 -11
- package/preset/claude/preset.yml +4 -4
- package/lib/events-qlmU1KrH.mjs.map +0 -1
- package/lib/presenters-DbfG-9KQ.mjs.map +0 -1
- package/lib/preset-installer-D8q3_-wJ.mjs.map +0 -1
package/INSTALL.md
CHANGED
|
@@ -1,46 +1,55 @@
|
|
|
1
|
-
# Agent Installation Runbook
|
|
2
|
-
|
|
3
|
-
This runbook is idempotent for a local `dsh-claude` checkout and an existing DSH `web` profile.
|
|
4
|
-
|
|
5
|
-
## 1. Verify the checkout
|
|
6
|
-
|
|
7
|
-
```sh
|
|
8
|
-
cd /path/to/dsh-claude
|
|
9
|
-
export PATH="/opt/homebrew/bin:$PATH"
|
|
10
|
-
pnpm install
|
|
11
|
-
pnpm check
|
|
12
|
-
node lib/bin.mjs doctor
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Stop if Doctor cannot find an authenticated local Claude Code installation. Do not request, copy, or write credentials.
|
|
16
|
-
|
|
17
|
-
## 2. Link the bundle into the current Web profile
|
|
18
|
-
|
|
19
|
-
The bundle
|
|
20
|
-
|
|
21
|
-
```sh
|
|
22
|
-
dsh plugin --profile web add "link:$(pwd)"
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Do not start another DSH Web server. This bundle must load in the existing app at `http://127.0.0.1:56454`.
|
|
26
|
-
|
|
27
|
-
## 3. Refresh and smoke test
|
|
28
|
-
|
|
29
|
-
1. Refresh the existing DSH Web page.
|
|
30
|
-
2. Confirm **Claude** appears in the new-session Agent Preset picker.
|
|
31
|
-
3. Run one existing native preset prompt and verify it remains native.
|
|
32
|
-
4. Create a Claude session and send a read-only prompt.
|
|
33
|
-
5. Send one edit prompt; verify DSH displays a permission request. Exercise reject first, then allow once with a harmless temporary file.
|
|
34
|
-
6. Cancel a running prompt and confirm the cancelled session owns no child `claude` process that is still executing cancelled work or left orphaned/unowned.
|
|
35
|
-
7. Refresh the browser and continue the session.
|
|
36
|
-
8. Restart DSH and confirm the next prompt resumes the persisted Claude session.
|
|
37
|
-
|
|
38
|
-
A live prompt can consume the user's Claude subscription. Keep it minimal.
|
|
39
|
-
|
|
40
|
-
## 4. Uninstall
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
|
|
1
|
+
# Agent Installation Runbook
|
|
2
|
+
|
|
3
|
+
This runbook is idempotent for a local `dsh-claude` checkout and an existing DSH `web` profile.
|
|
4
|
+
|
|
5
|
+
## 1. Verify the checkout
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
cd /path/to/dsh-claude
|
|
9
|
+
export PATH="/opt/homebrew/bin:$PATH"
|
|
10
|
+
pnpm install
|
|
11
|
+
pnpm check
|
|
12
|
+
node lib/bin.mjs doctor
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Stop if Doctor cannot find an authenticated local Claude Code installation. Do not request, copy, or write credentials.
|
|
16
|
+
|
|
17
|
+
## 2. Link the bundle into the current Web profile
|
|
18
|
+
|
|
19
|
+
The bundle retains its package-contained system preset and installs a protected compatibility copy at `$DSH_HOME/.agent-presets/claude` during Host activation. This works around DSH `0.1.0-rc.6` through `0.1.0-rc.8` replacing third-party preset roots. Existing user-modified files are preserved rather than overwritten.
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
dsh plugin --profile web add "link:$(pwd)"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Do not start another DSH Web server. This bundle must load in the existing app at `http://127.0.0.1:56454`.
|
|
26
|
+
|
|
27
|
+
## 3. Refresh and smoke test
|
|
28
|
+
|
|
29
|
+
1. Refresh the existing DSH Web page.
|
|
30
|
+
2. Confirm **Claude** appears in the new-session Agent Preset picker.
|
|
31
|
+
3. Run one existing native preset prompt and verify it remains native.
|
|
32
|
+
4. Create a Claude session and send a read-only prompt.
|
|
33
|
+
5. Send one edit prompt; verify DSH displays a permission request. Exercise reject first, then allow once with a harmless temporary file.
|
|
34
|
+
6. Cancel a running prompt and confirm the cancelled session owns no child `claude` process that is still executing cancelled work or left orphaned/unowned.
|
|
35
|
+
7. Refresh the browser and continue the session.
|
|
36
|
+
8. Restart DSH and confirm the next prompt resumes the persisted Claude session.
|
|
37
|
+
|
|
38
|
+
A live prompt can consume the user's Claude subscription. Keep it minimal.
|
|
39
|
+
|
|
40
|
+
## 4. Uninstall
|
|
41
|
+
|
|
42
|
+
Clean up the managed preset while the profile can still execute the package CLI, then remove the plugin:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
dsh plugin --profile web exec dsh-claude remove-preset
|
|
46
|
+
dsh plugin --profile web remove @norman-else/dsh-claude
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
DSH has no plugin uninstall lifecycle hook, so direct package removal can leave the compatibility preset behind. After direct removal, no source checkout is required; run the matching package version:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
pnpm dlx @norman-else/dsh-claude@<version> remove-preset
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Cleanup refuses to delete user-modified preset content.
|
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 dsh-claude contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-claude contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,183 +1,191 @@
|
|
|
1
|
-
# dsh-claude
|
|
2
|
-
|
|
3
|
-
Run the local Claude Code CLI as a first-class main conversation inside DeepSeek Harness (DSH).
|
|
4
|
-
|
|
5
|
-
`dsh-claude` does not recreate Claude Code with an API client. It starts the user's installed `claude` executable through the official Agent SDK protocol, keeps one live process per active DSH session, and leaves Claude Code in charge of its own agent loop, tools, `CLAUDE.md`, Skills, Hooks, Plugins, MCP servers, settings, and authentication.
|
|
6
|
-
|
|
7
|
-
## What it adds
|
|
8
|
-
|
|
9
|
-
- A `Claude` Agent Preset in the normal new-session preset picker.
|
|
10
|
-
- A `claude` DSH model provider with Claude Code's `default`, `opus[1m]`, `fable`, `sonnet`, and `haiku` choices.
|
|
11
|
-
- Long-lived Claude processes with per-session serialization, idle eviction, cancellation, and persisted Claude session resume.
|
|
12
|
-
- DSH approval prompts for Claude tool permission requests.
|
|
13
|
-
- Durable, redacted plugin-sidecar activity for thinking summaries, tool calls/results, permissions, subagents, status, usage, and errors.
|
|
14
|
-
- Native turn-tail activity cards and a Settings → Claude Code Doctor panel.
|
|
15
|
-
- A safe CLI for Doctor and managed preset install/remove.
|
|
16
|
-
|
|
17
|
-
## Requirements
|
|
18
|
-
|
|
19
|
-
- macOS (v0.1 verification target).
|
|
20
|
-
- DeepSeek Harness compatible with `0.1.0-rc.5` public plugin APIs.
|
|
21
|
-
- A local Claude Code installation already authenticated by the user.
|
|
22
|
-
- Node.js 20 or later.
|
|
23
|
-
|
|
24
|
-
The plugin never manages Claude credentials. Use an already authenticated local Claude Code installation, or configure its absolute executable path in DSH.
|
|
25
|
-
|
|
26
|
-
## Install in DSH
|
|
27
|
-
|
|
28
|
-
Install the published package into the DSH Web profile:
|
|
29
|
-
|
|
30
|
-
```sh
|
|
31
|
-
dsh plugin --profile web add @norman-else/dsh-claude
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Wait for the Web profile to rebuild, then refresh the existing DSH page. Open a new conversation and select **Claude** from the Agent Preset picker.
|
|
35
|
-
|
|
36
|
-
The package ships
|
|
37
|
-
|
|
38
|
-
## Use
|
|
39
|
-
|
|
40
|
-
1. Open a new DSH conversation.
|
|
41
|
-
2. Choose **Claude** in the Agent Preset picker.
|
|
42
|
-
3. Choose **Default (recommended)**, **Opus (1M context)**, **Fable**, **Sonnet**, or **Haiku**.
|
|
43
|
-
4. Send a normal text prompt.
|
|
44
|
-
5. Answer Claude tool permissions through the existing DSH approval UI.
|
|
45
|
-
6. Expand **Claude Code activity** beneath a completed assistant turn to inspect the redacted execution trail.
|
|
46
|
-
|
|
47
|
-
Native DSH presets remain available and keep the native DSH agent loop.
|
|
48
|
-
|
|
49
|
-
### Current input boundary
|
|
50
|
-
|
|
51
|
-
v0.1 forwards only the newest direct human text in a DSH step. It intentionally ignores the DSH system prompt, DSH tool schemas, and injected plugin messages because Claude Code owns those surfaces. Image-only prompts are rejected with an actionable error.
|
|
52
|
-
|
|
53
|
-
## Permission and sandbox boundary
|
|
54
|
-
|
|
55
|
-
Claude Code runs in its normal local configuration and can read/write `~/.claude` so that authentication, settings, plugins, and session recovery continue to work.
|
|
56
|
-
|
|
57
|
-
Every Claude permission callback is bridged to `ctx.approval.request(...)`:
|
|
58
|
-
|
|
59
|
-
- `allowed-once` is the only granting result.
|
|
60
|
-
- reject, cancel, missing answerer, and audit failure all deny the action.
|
|
61
|
-
- DSH `never` approval policy therefore fails closed.
|
|
62
|
-
- DSH access modes map to Claude permission modes: `read-only` → `plan`, `workspace-write` → `acceptEdits`, and explicitly acknowledged `danger-full-access` → `bypassPermissions`.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
- One
|
|
70
|
-
-
|
|
71
|
-
- Default
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
- DSH
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
node lib/bin.mjs doctor
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
pnpm
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
pnpm release
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
### Claude
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
1
|
+
# dsh-claude
|
|
2
|
+
|
|
3
|
+
Run the local Claude Code CLI as a first-class main conversation inside DeepSeek Harness (DSH).
|
|
4
|
+
|
|
5
|
+
`dsh-claude` does not recreate Claude Code with an API client. It starts the user's installed `claude` executable through the official Agent SDK protocol, keeps one live process per active DSH session, and leaves Claude Code in charge of its own agent loop, tools, `CLAUDE.md`, Skills, Hooks, Plugins, MCP servers, settings, and authentication.
|
|
6
|
+
|
|
7
|
+
## What it adds
|
|
8
|
+
|
|
9
|
+
- A `Claude` Agent Preset in the normal new-session preset picker.
|
|
10
|
+
- A `claude` DSH model provider with Claude Code's `default`, `opus[1m]`, `fable`, `sonnet`, and `haiku` choices.
|
|
11
|
+
- Long-lived Claude processes with per-session serialization, idle eviction, cancellation, and persisted Claude session resume.
|
|
12
|
+
- DSH approval prompts for Claude tool permission requests and native DSH question forms for Claude clarifications.
|
|
13
|
+
- Durable, redacted plugin-sidecar activity for thinking summaries, tool calls/results, permissions, question lifecycle, subagents, status, usage, and errors.
|
|
14
|
+
- Native turn-tail activity cards and a Settings → Claude Code Doctor panel.
|
|
15
|
+
- A safe CLI for Doctor and managed preset install/remove.
|
|
16
|
+
|
|
17
|
+
## Requirements
|
|
18
|
+
|
|
19
|
+
- macOS (v0.1 verification target).
|
|
20
|
+
- DeepSeek Harness compatible with `0.1.0-rc.5` public plugin APIs.
|
|
21
|
+
- A local Claude Code installation already authenticated by the user.
|
|
22
|
+
- Node.js 20 or later.
|
|
23
|
+
|
|
24
|
+
The plugin never manages Claude credentials. Use an already authenticated local Claude Code installation, or configure its absolute executable path in DSH.
|
|
25
|
+
|
|
26
|
+
## Install in DSH
|
|
27
|
+
|
|
28
|
+
Install the published package into the DSH Web profile:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
dsh plugin --profile web add @norman-else/dsh-claude
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Wait for the Web profile to rebuild, then refresh the existing DSH page. Open a new conversation and select **Claude** from the Agent Preset picker.
|
|
35
|
+
|
|
36
|
+
The package ships a read-only system preset and, during Host activation, installs a protected compatibility copy at `$DSH_HOME/.agent-presets/claude`. The compatibility copy is required because DSH `0.1.0-rc.6` through `0.1.0-rc.8` replace third-party preset roots during profile boot. Installation is idempotent and never overwrites user-modified preset content.
|
|
37
|
+
|
|
38
|
+
## Use
|
|
39
|
+
|
|
40
|
+
1. Open a new DSH conversation.
|
|
41
|
+
2. Choose **Claude** in the Agent Preset picker.
|
|
42
|
+
3. Choose **Default (recommended)**, **Opus (1M context)**, **Fable**, **Sonnet**, or **Haiku**.
|
|
43
|
+
4. Send a normal text prompt.
|
|
44
|
+
5. Answer Claude tool permissions through the existing DSH approval UI and Claude clarifying questions through DSH's native question form.
|
|
45
|
+
6. Expand **Claude Code activity** beneath a completed assistant turn to inspect the redacted execution trail.
|
|
46
|
+
|
|
47
|
+
Native DSH presets remain available and keep the native DSH agent loop.
|
|
48
|
+
|
|
49
|
+
### Current input boundary
|
|
50
|
+
|
|
51
|
+
v0.1 forwards only the newest direct human text in a DSH step. It intentionally ignores the DSH system prompt, DSH tool schemas, and injected plugin messages because Claude Code owns those surfaces. Image-only prompts are rejected with an actionable error.
|
|
52
|
+
|
|
53
|
+
## Permission and sandbox boundary
|
|
54
|
+
|
|
55
|
+
Claude Code runs in its normal local configuration and can read/write `~/.claude` so that authentication, settings, plugins, and session recovery continue to work.
|
|
56
|
+
|
|
57
|
+
Every Claude permission callback is bridged to `ctx.approval.request(...)`:
|
|
58
|
+
|
|
59
|
+
- `allowed-once` is the only granting result.
|
|
60
|
+
- reject, cancel, missing answerer, and audit failure all deny the action.
|
|
61
|
+
- DSH `never` approval policy therefore fails closed.
|
|
62
|
+
- DSH access modes map to Claude permission modes: `read-only` → `plan`, `workspace-write` → `acceptEdits`, and explicitly acknowledged `danger-full-access` → `bypassPermissions`.
|
|
63
|
+
- Claude `AskUserQuestion` is always routed to `ctx.userQuestions`, including under Full access; cancellation or an unavailable question surface denies the interaction, and answer content is not copied into the sidecar.
|
|
64
|
+
|
|
65
|
+
This is a permission-policy bridge, not kernel-level workspace confinement. DSH `0.1.0-rc.5` exposes one writable sandbox root, while full Claude compatibility also requires writable `~/.claude`. The plugin therefore does **not** claim that paths outside the workspace are technically unwritable. It still uses DSH managed subprocess ownership for explicit argv, credential-shaped environment scrubbing, cancellation, and whole-process-tree termination.
|
|
66
|
+
|
|
67
|
+
## Process and recovery behavior
|
|
68
|
+
|
|
69
|
+
- One live streaming-input Claude query per active DSH session.
|
|
70
|
+
- One active top-level turn at a time per session.
|
|
71
|
+
- Default maximum: 4 live Claude processes.
|
|
72
|
+
- Default idle eviction: 30 minutes.
|
|
73
|
+
- The Claude session id and redacted presentation metadata are persisted in a plugin-owned sidecar under `$DSH_HOME/plugins/dsh-claude/sessions`; new DSH logs contain no `claude-code/*` events.
|
|
74
|
+
- After normal eviction or DSH restart, the next prompt resumes that Claude session.
|
|
75
|
+
- A crash after visible Claude/tool activity is reported as **outcome unknown**. The plugin never automatically replays that prompt because its side effects may already have happened.
|
|
76
|
+
- Cancelling a DSH turn interrupts Claude and tears down that session's process entry (bounded interrupt, then close/abort/terminate/join); the next prompt re-establishes the process from the persisted Claude session id. Plugin unload and agent disposal also terminate the owned process tree.
|
|
77
|
+
- DSH outer model retries are disabled for this provider.
|
|
78
|
+
|
|
79
|
+
## Doctor
|
|
80
|
+
|
|
81
|
+
Inside DSH, open **Settings → Claude Code** and run Doctor.
|
|
82
|
+
|
|
83
|
+
From the checkout:
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
node lib/bin.mjs doctor
|
|
87
|
+
node lib/bin.mjs doctor --executable /absolute/path/to/claude
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Doctor reports only the resolved executable, version, coarse authentication category/method/provider/subscription, handshake state, configured limits, and process count. It never returns tokens, email, organization id, settings content, or environment secrets.
|
|
91
|
+
|
|
92
|
+
Executable resolution order:
|
|
93
|
+
|
|
94
|
+
1. configured absolute path
|
|
95
|
+
2. `claude` on DSH's scrubbed PATH
|
|
96
|
+
3. `~/.local/bin/claude`
|
|
97
|
+
4. `/opt/homebrew/bin/claude`
|
|
98
|
+
5. `/usr/local/bin/claude`
|
|
99
|
+
|
|
100
|
+
To configure a nonstandard path, edit the plugin row in the Web profile composition:
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
- id: llm-claude
|
|
104
|
+
name: '@norman-else/dsh-claude'
|
|
105
|
+
config:
|
|
106
|
+
executablePath: /absolute/path/to/claude
|
|
107
|
+
model: default
|
|
108
|
+
idleTimeoutMs: 1800000
|
|
109
|
+
maxProcesses: 4
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Development
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
git clone https://github.com/Norman-else/dsh-claude.git
|
|
116
|
+
cd dsh-claude
|
|
117
|
+
export PATH="/opt/homebrew/bin:$PATH"
|
|
118
|
+
pnpm install
|
|
119
|
+
pnpm check
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
To test this source checkout in DSH without publishing it:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
dsh plugin --profile web add "link:$(pwd)"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
To inspect the package that would be published:
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
pnpm pack --pack-destination ./dist-pack
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Release
|
|
135
|
+
|
|
136
|
+
Update the version in `package.json`, commit it, and push the clean release commit first. Then verify and publish both npm and GitHub releases:
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
pnpm release:check
|
|
140
|
+
pnpm release
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The release script requires `HEAD` to match the current branch on `origin`. It runs the full project check and npm package preview, publishes the public npm package, waits for npm metadata propagation, verifies npm's `gitHead`, and creates a matching `v<version>` GitHub Release with generated notes. It is safe to rerun after a partial failure: an existing npm version or GitHub Release is accepted only when it points to the current commit.
|
|
144
|
+
|
|
145
|
+
The project uses fixture/state-machine tests and a minimal SDK-level handshake probe (a tool-disabled, one-turn `query()` against the resolved local executable). Full DSH-linked live acceptance (native coexistence, Claude turn, permission allow/deny, cancel, resume, orphan-process check) is run after the Host restart per `INSTALL.md`. The Agent SDK is pinned to `0.3.233`; runtime execution is forced to the resolved local Claude executable through `pathToClaudeCodeExecutable`.
|
|
146
|
+
|
|
147
|
+
## Uninstall
|
|
148
|
+
|
|
149
|
+
Remove the managed compatibility preset before removing the package:
|
|
150
|
+
|
|
151
|
+
```sh
|
|
152
|
+
dsh plugin --profile web exec dsh-claude remove-preset
|
|
153
|
+
dsh plugin --profile web remove @norman-else/dsh-claude
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
DSH does not expose a plugin uninstall lifecycle hook, so removing the package directly can leave `$DSH_HOME/.agent-presets/claude` behind. If the package was already removed, clean it up without cloning the source repository by running the matching installed version through npm:
|
|
157
|
+
|
|
158
|
+
```sh
|
|
159
|
+
pnpm dlx @norman-else/dsh-claude@<version> remove-preset
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Both cleanup paths remove only installer-managed content. They fail without deleting anything if a preset file was user-modified; preserve or remove that custom content manually after review.
|
|
163
|
+
|
|
164
|
+
## Troubleshooting
|
|
165
|
+
|
|
166
|
+
### Claude preset appears broken
|
|
167
|
+
|
|
168
|
+
Confirm the package remains installed in the intended profile with `dsh plugin --profile web why @norman-else/dsh-claude`, then restart that profile so Host activation can install or refresh the protected managed preset. You can also run `dsh plugin --profile web exec dsh-claude install-preset` explicitly.
|
|
169
|
+
|
|
170
|
+
### Executable is missing
|
|
171
|
+
|
|
172
|
+
Run Doctor and set an absolute `executablePath`. GUI application PATH often omits `~/.local/bin`.
|
|
173
|
+
|
|
174
|
+
### Claude is signed out
|
|
175
|
+
|
|
176
|
+
Run the supported local flow directly:
|
|
177
|
+
|
|
178
|
+
```sh
|
|
179
|
+
/absolute/path/to/claude auth login
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
DSH does not proxy login or store credentials.
|
|
183
|
+
|
|
184
|
+
### A turn says “outcome unknown”
|
|
185
|
+
|
|
186
|
+
Inspect the activity record and workspace before sending a new instruction. Do not repeat a potentially side-effecting prompt blindly.
|
|
187
|
+
|
|
188
|
+
## Architecture records
|
|
189
|
+
|
|
190
|
+
- Product and architecture spec: `docs/aegis/spec/2026-08-15-dsh-claude-spec.md`
|
|
191
|
+
- Implementation plan: `docs/aegis/plan/2026-08-15-dsh-claude-implementation-plan.md`
|
package/cordis.patch.yml
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
# dsh-claude host bundle. The preset stays inside this package as a system
|
|
2
|
-
# preset, so removing the profile dependency removes the complete integration.
|
|
3
|
-
- id: agent-presets
|
|
4
|
-
config:
|
|
5
|
-
default: standard
|
|
6
|
-
roots:
|
|
7
|
-
- path: !!js "process.getBuiltinModule('node:path').join(process.getBuiltinModule('node:path').dirname(process.getBuiltinModule('node:module').createRequire(ctx.baseUrl).resolve('@norman-else/dsh-claude/package.json')), 'preset')"
|
|
8
|
-
trust: system
|
|
9
|
-
|
|
10
|
-
- insert:
|
|
11
|
-
- id: llm-claude
|
|
12
|
-
name: '@norman-else/dsh-claude'
|
|
1
|
+
# dsh-claude host bundle. The preset stays inside this package as a system
|
|
2
|
+
# preset, so removing the profile dependency removes the complete integration.
|
|
3
|
+
- id: agent-presets
|
|
4
|
+
config:
|
|
5
|
+
default: standard
|
|
6
|
+
roots:
|
|
7
|
+
- path: !!js "process.getBuiltinModule('node:path').join(process.getBuiltinModule('node:path').dirname(process.getBuiltinModule('node:module').createRequire(ctx.baseUrl).resolve('@norman-else/dsh-claude/package.json')), 'preset')"
|
|
8
|
+
trust: system
|
|
9
|
+
|
|
10
|
+
- insert:
|
|
11
|
+
- id: llm-claude
|
|
12
|
+
name: '@norman-else/dsh-claude'
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# Shipped by dsh-claude. Claude Code owns the inner agent loop and tools;
|
|
2
|
-
# this system preset contributes only the request-route override. DSH resolves
|
|
3
|
-
# the bare package specifier from the host profile when mounting system roots.
|
|
4
|
-
- id: claude-code-route
|
|
5
|
-
name: '@norman-else/dsh-claude/preset-route'
|
|
6
|
-
# Entry-local isolate realm: each session's preset mount gets its own
|
|
7
|
-
# claudeCommands service instance (keeps mountPreset's leaked-service check
|
|
8
|
-
# happy and prevents cross-session collisions). The host reads it through
|
|
9
|
-
# dsh-agent-presets' serviceForAgent().
|
|
10
|
-
isolate:
|
|
11
|
-
claudeCommands: true
|
|
1
|
+
# Shipped by dsh-claude. Claude Code owns the inner agent loop and tools;
|
|
2
|
+
# this system preset contributes only the request-route override. DSH resolves
|
|
3
|
+
# the bare package specifier from the host profile when mounting system roots.
|
|
4
|
+
- id: claude-code-route
|
|
5
|
+
name: '@norman-else/dsh-claude/preset-route'
|
|
6
|
+
# Entry-local isolate realm: each session's preset mount gets its own
|
|
7
|
+
# claudeCommands service instance (keeps mountPreset's leaked-service check
|
|
8
|
+
# happy and prevents cross-session collisions). The host reads it through
|
|
9
|
+
# dsh-agent-presets' serviceForAgent().
|
|
10
|
+
isolate:
|
|
11
|
+
claudeCommands: true
|
package/legacy-preset/preset.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Shipped by dsh-claude. Copy this system preset under a new id to customize it.
|
|
2
|
-
name: Claude
|
|
3
|
-
description: Use the local Claude Code as the complete agent runtime inside DSH.
|
|
4
|
-
order: 10
|
|
1
|
+
# Shipped by dsh-claude. Copy this system preset under a new id to customize it.
|
|
2
|
+
name: Claude
|
|
3
|
+
description: Use the local Claude Code as the complete agent runtime inside DSH.
|
|
4
|
+
order: 10
|
package/lib/bin.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as parseClaudeVersion, n as ensureManagedPreset, r as removeManagedPreset } from "./preset-installer-
|
|
2
|
+
import { i as parseClaudeVersion, n as ensureManagedPreset, r as removeManagedPreset } from "./preset-installer-BKw-SdOm.mjs";
|
|
3
3
|
import { access } from "node:fs/promises";
|
|
4
4
|
import { delimiter, isAbsolute, join } from "node:path";
|
|
5
5
|
import { homedir } from "node:os";
|
package/lib/bin.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.mjs","names":[],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { access } from 'node:fs/promises'\nimport { constants } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { delimiter, isAbsolute, join } from 'node:path'\nimport { spawnSync } from 'node:child_process'\nimport { scrubbedParentEnv } from '@deepseek-ai/dsh-subprocess'\nimport { parseClaudeVersion } from './executable.ts'\nimport { ensureManagedPreset, removeManagedPreset } from './preset-installer.ts'\n\nfunction option(name: string): string | undefined {\n const index = process.argv.indexOf(name)\n return index < 0 ? undefined : process.argv[index + 1]\n}\n\nasync function executable(configured?: string): Promise<string | undefined> {\n const candidates: string[] = []\n if (configured !== undefined) candidates.push(configured)\n else {\n for (const directory of (process.env.PATH ?? '').split(delimiter)) {\n if (directory.length > 0) candidates.push(join(directory, 'claude'))\n }\n candidates.push(join(homedir(), '.local', 'bin', 'claude'), '/opt/homebrew/bin/claude', '/usr/local/bin/claude')\n }\n for (const candidate of [...new Set(candidates)]) {\n if (!isAbsolute(candidate)) continue\n try {\n await access(candidate, constants.X_OK)\n return candidate\n } catch {\n // Continue to the next documented candidate.\n }\n }\n return undefined\n}\n\nfunction run(executablePath: string, args: string[]) {\n return spawnSync(executablePath, args, {\n encoding: 'utf8',\n env: scrubbedParentEnv(),\n timeout: 15_000,\n windowsHide: true,\n })\n}\n\nasync function doctor(): Promise<number> {\n const configured = option('--executable') ?? process.env.DSH_CLAUDE_CODE_EXECUTABLE\n const path = await executable(configured)\n if (path === undefined) {\n process.stdout.write(`${JSON.stringify({\n executable: { status: 'missing', searched: configured === undefined ? ['claude', '~/.local/bin/claude', '/opt/homebrew/bin/claude', '/usr/local/bin/claude'] : [configured] },\n version: { status: 'not-run' },\n authentication: { status: 'not-run' },\n message: 'Set executablePath to an absolute Claude Code CLI path',\n }, null, 2)}\\n`)\n return 1\n }\n const versionProbe = run(path, ['--version'])\n const version = parseClaudeVersion(`${versionProbe.stdout ?? ''}\\n${versionProbe.stderr ?? ''}`)\n const authProbe = run(path, ['auth', 'status', '--json'])\n let authentication: Record<string, unknown> = { status: 'unknown' }\n if (authProbe.status === 0) {\n try {\n const value = JSON.parse(authProbe.stdout) as Record<string, unknown>\n authentication = {\n status: value.loggedIn === true ? 'signed-in' : 'signed-out',\n ...(typeof value.authMethod === 'string' ? { method: value.authMethod } : {}),\n ...(typeof value.apiProvider === 'string' ? { provider: value.apiProvider } : {}),\n ...(typeof value.subscriptionType === 'string' ? { subscription: value.subscriptionType } : {}),\n }\n } catch {\n authentication = { status: 'unknown', message: 'Authentication status was not valid JSON' }\n }\n }\n process.stdout.write(`${JSON.stringify({\n executable: { status: 'found', path },\n version: version === undefined ? { status: 'error' } : { status: 'ok', value: version },\n authentication,\n handshake: 'not-run',\n }, null, 2)}\\n`)\n return version === undefined ? 1 : 0\n}\n\nasync function main(): Promise<number> {\n const command = process.argv[2] ?? 'doctor'\n if (command === 'doctor') return doctor()\n if (command === 'install-preset') {\n process.stdout.write(`${await ensureManagedPreset()}\\n`)\n return 0\n }\n if (command === 'remove-preset') {\n process.stdout.write(`${await removeManagedPreset()}\\n`)\n return 0\n }\n process.stderr.write(`Usage: dsh-claude [doctor [--executable PATH] | install-preset | remove-preset]\\n`)\n return 2\n}\n\ntry {\n process.exitCode = await main()\n} catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`)\n process.exitCode = 1\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bin.mjs","names":[],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\nimport { access } from 'node:fs/promises'\r\nimport { constants } from 'node:fs'\r\nimport { homedir } from 'node:os'\r\nimport { delimiter, isAbsolute, join } from 'node:path'\r\nimport { spawnSync } from 'node:child_process'\r\nimport { scrubbedParentEnv } from '@deepseek-ai/dsh-subprocess'\r\nimport { parseClaudeVersion } from './executable.ts'\r\nimport { ensureManagedPreset, removeManagedPreset } from './preset-installer.ts'\r\n\r\nfunction option(name: string): string | undefined {\r\n const index = process.argv.indexOf(name)\r\n return index < 0 ? undefined : process.argv[index + 1]\r\n}\r\n\r\nasync function executable(configured?: string): Promise<string | undefined> {\r\n const candidates: string[] = []\r\n if (configured !== undefined) candidates.push(configured)\r\n else {\r\n for (const directory of (process.env.PATH ?? '').split(delimiter)) {\r\n if (directory.length > 0) candidates.push(join(directory, 'claude'))\r\n }\r\n candidates.push(join(homedir(), '.local', 'bin', 'claude'), '/opt/homebrew/bin/claude', '/usr/local/bin/claude')\r\n }\r\n for (const candidate of [...new Set(candidates)]) {\r\n if (!isAbsolute(candidate)) continue\r\n try {\r\n await access(candidate, constants.X_OK)\r\n return candidate\r\n } catch {\r\n // Continue to the next documented candidate.\r\n }\r\n }\r\n return undefined\r\n}\r\n\r\nfunction run(executablePath: string, args: string[]) {\r\n return spawnSync(executablePath, args, {\r\n encoding: 'utf8',\r\n env: scrubbedParentEnv(),\r\n timeout: 15_000,\r\n windowsHide: true,\r\n })\r\n}\r\n\r\nasync function doctor(): Promise<number> {\r\n const configured = option('--executable') ?? process.env.DSH_CLAUDE_CODE_EXECUTABLE\r\n const path = await executable(configured)\r\n if (path === undefined) {\r\n process.stdout.write(`${JSON.stringify({\r\n executable: { status: 'missing', searched: configured === undefined ? ['claude', '~/.local/bin/claude', '/opt/homebrew/bin/claude', '/usr/local/bin/claude'] : [configured] },\r\n version: { status: 'not-run' },\r\n authentication: { status: 'not-run' },\r\n message: 'Set executablePath to an absolute Claude Code CLI path',\r\n }, null, 2)}\\n`)\r\n return 1\r\n }\r\n const versionProbe = run(path, ['--version'])\r\n const version = parseClaudeVersion(`${versionProbe.stdout ?? ''}\\n${versionProbe.stderr ?? ''}`)\r\n const authProbe = run(path, ['auth', 'status', '--json'])\r\n let authentication: Record<string, unknown> = { status: 'unknown' }\r\n if (authProbe.status === 0) {\r\n try {\r\n const value = JSON.parse(authProbe.stdout) as Record<string, unknown>\r\n authentication = {\r\n status: value.loggedIn === true ? 'signed-in' : 'signed-out',\r\n ...(typeof value.authMethod === 'string' ? { method: value.authMethod } : {}),\r\n ...(typeof value.apiProvider === 'string' ? { provider: value.apiProvider } : {}),\r\n ...(typeof value.subscriptionType === 'string' ? { subscription: value.subscriptionType } : {}),\r\n }\r\n } catch {\r\n authentication = { status: 'unknown', message: 'Authentication status was not valid JSON' }\r\n }\r\n }\r\n process.stdout.write(`${JSON.stringify({\r\n executable: { status: 'found', path },\r\n version: version === undefined ? { status: 'error' } : { status: 'ok', value: version },\r\n authentication,\r\n handshake: 'not-run',\r\n }, null, 2)}\\n`)\r\n return version === undefined ? 1 : 0\r\n}\r\n\r\nasync function main(): Promise<number> {\r\n const command = process.argv[2] ?? 'doctor'\r\n if (command === 'doctor') return doctor()\r\n if (command === 'install-preset') {\r\n process.stdout.write(`${await ensureManagedPreset()}\\n`)\r\n return 0\r\n }\r\n if (command === 'remove-preset') {\r\n process.stdout.write(`${await removeManagedPreset()}\\n`)\r\n return 0\r\n }\r\n process.stderr.write(`Usage: dsh-claude [doctor [--executable PATH] | install-preset | remove-preset]\\n`)\r\n return 2\r\n}\r\n\r\ntry {\r\n process.exitCode = await main()\r\n} catch (error) {\r\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`)\r\n process.exitCode = 1\r\n}\r\n"],"mappings":"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"}
|