dsh-remote 0.8.34 → 0.8.35
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.en.md +72 -153
- package/README.md +57 -135
- package/lib/client.js +13 -3
- package/lib/ignore.js +33 -0
- package/lib/index.js +109 -21
- package/lib/pool.js +124 -53
- package/lib/search.js +53 -8
- package/lib/update.js +30 -7
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -22,169 +22,98 @@ The harness Web UI intentionally binds `127.0.0.1` (the CLI rejects `--host 0.0.
|
|
|
22
22
|
|
|
23
23
|
## Data collection / telemetry
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
One anonymous heartbeat per launch (at least 6 hours apart), used only to measure usage: **de-duplicated daily active installs, the version actually running, and platform distribution**. npm download counts are release-driven and include mirrors/crawlers, and GitHub clones include CI, so neither can answer that.
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Exactly five fields are sent: `idHash` (a pseudonym, `HMAC-SHA256('dsh-remote/telemetry/v1', installId)`), `version`, `platform`, `arch`, `node`. **Not sent:** hostnames, usernames, paths, IPs, SSH hosts/ports/keys, your machine list, session content. The raw `installId` (`<DSH_HOME>/.dsh-remote-install-id`) never leaves your machine — only its HMAC is transmitted.
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|---|---|---|
|
|
31
|
-
| `idHash` | `872bd8cf…` (32 hex) | `HMAC-SHA256('dsh-remote/telemetry/v1', installId)` — a pseudonym for this install |
|
|
32
|
-
| `version` | `0.8.24` | which version is actually running |
|
|
33
|
-
| `platform` | `win32` / `darwin` / `linux` | platform distribution |
|
|
34
|
-
| `arch` | `x64` / `arm64` | architecture |
|
|
35
|
-
| `node` | `24.14.0` | Node version |
|
|
36
|
-
|
|
37
|
-
**What is never sent** — hostnames, usernames, file paths, IP addresses, SSH hosts/ports/keys, your machine list, conversation content, or anything from your remote sessions. The original `installId` **never leaves your machine**: only its HMAC is transmitted, so the server cannot correlate it with anything else and cannot reverse it.
|
|
38
|
-
|
|
39
|
-
**Where the identity lives** — a random UUID in `<DSH_HOME>/.dsh-remote-install-id` (e.g. `~/.dsh/`). It is deliberately **not** stored in the plugin directory, which npm/pnpm overwrites on every upgrade; keeping it in `DSH_HOME` means an upgrade does not make you look like a new user. Delete that file to reset the identity.
|
|
40
|
-
|
|
41
|
-
The heartbeat is **fire-and-forget**: it never blocks loading, never logs noise, and any failure (offline, blocked, endpoint change) is swallowed silently — it can never affect any plugin feature.
|
|
29
|
+
The heartbeat is fire-and-forget: it never blocks loading and failures are ignored.
|
|
42
30
|
|
|
43
31
|
[live usage stats](https://flymysql.github.io/dsh-remote/stats/) · [plugin homepage](https://flymysql.github.io/dsh-remote/)
|
|
44
32
|
|
|
45
33
|
## Screen previews
|
|
46
34
|
|
|
47
|
-
Settings →
|
|
35
|
+
**Settings → 远程工作区** — machine list, advanced config (key / jump host / agent), connection check, port forwarding, audit log, update:
|
|
48
36
|
|
|
49
|
-
<img src="docs/
|
|
37
|
+
<img src="docs/shots/settings-panel.png" alt="dsh-remote settings: machine list, advanced config, port forwarding, audit log, update" width="640"/>
|
|
50
38
|
|
|
51
|
-
The native **"Add workspace"
|
|
39
|
+
The native **"Add workspace"** flow — a centered modal with two tabs, opening on Local; here switched to **Remote**:
|
|
52
40
|
|
|
53
|
-
|
|
41
|
+
<img src="docs/shots/picker-dialog.png" alt="The 远程 (remote) tab of the workspace picker: machine select, recent workspaces, browse, set-as-remote-workspace" width="632"/>
|
|
54
42
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<img src="docs/ui-picker-panel.png" alt="dsh-remote workspace picker — real dialog; 本机 (local) tab; 远程 machine select + prefilled root path + autocomplete" width="720"/>
|
|
43
|
+
- The path field autocompletes live; on Windows hosts the root shows a multi-drive view; the floating browser fills the field without committing.
|
|
44
|
+
- On confirm a **real local mirror** is created and adopted by the harness, kept in sync over SFTP; the choice persists on the machine.
|
|
58
45
|
|
|
59
46
|
---
|
|
60
47
|
|
|
61
48
|
## Features
|
|
62
49
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
- **
|
|
81
|
-
- **
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
- **Data lives under the harness home** — machines + mirrors follow `$DSH_HOME`; pre-0.6 data under `~/.dsh/remote-workspaces` is migrated automatically on first run.
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
The image above is the overview. What follows is only what the image does not make obvious.
|
|
53
|
+
|
|
54
|
+
**Workspace picker** (fills the native "Add workspace" flow) — Local uses the system folder chooser; Remote browses inside the modal:
|
|
55
|
+
|
|
56
|
+
<img src="docs/shots/picker-dialog.png" alt="The 远程 (remote) tab of the workspace picker: machine select, recent workspaces, browse, set-as-remote-workspace" width="632"/>
|
|
57
|
+
|
|
58
|
+
- The path field autocompletes live; on Windows hosts the root shows a multi-drive view; the floating browser fills the field without committing.
|
|
59
|
+
- On confirm a **real local mirror** is created and adopted by the harness, kept in sync over SFTP; the choice persists on the machine.
|
|
60
|
+
|
|
61
|
+
**Settings** (machine list, connection check, port forwarding, audit log, update mode):
|
|
62
|
+
|
|
63
|
+
<img src="docs/shots/settings-panel.png" alt="dsh-remote settings: machine list, advanced config, port forwarding, audit log, update" width="640"/>
|
|
64
|
+
|
|
65
|
+
The rest:
|
|
66
|
+
|
|
67
|
+
- **20 model tools** (listed so they can be copied or searched): `rw_info`, `rw_connect`, `rw_pick_workspace`, `rw_list_dir`, `rw_stat`, `rw_read_file`, `rw_write_file`, `rw_edit`, `rw_append`, `rw_mkdir`, `rw_remove`, `rw_move`, `rw_exec`, `rw_search`, `rw_download`, `rw_upload`, `rw_sync`, `rw_push`, `rw_forward`, `rw_disconnect`.
|
|
68
|
+
- **Cross-platform remotes** — all file access is SFTP-protocol-level (no POSIX shell), so Linux/macOS/Windows remotes all work.
|
|
69
|
+
- **Windows remotes** — the platform is auto-detected and commands go through `bash -s` over stdin, so quoting and backslash escaping are never an issue (`config.shell` can pin a path or `native` disables wrapping); `C:\Users\dev` and `/c/Users/dev` are both accepted.
|
|
70
|
+
- **Async long tasks** — `rw_sync`/`rw_push` with `async: true` return a `taskId` with progress/result/cancel.
|
|
71
|
+
- **Data lives under the harness home** — machines and mirrors follow `$DSH_HOME`; pre-0.6 data migrates automatically on first run.
|
|
72
|
+
- **No `dsh-workspace` core changes** — everything ships as a normal plugin.
|
|
87
73
|
|
|
88
74
|
## Install
|
|
89
75
|
|
|
90
76
|
### DSH version compatibility
|
|
91
77
|
|
|
92
|
-
|
|
93
|
-
`@deepseek-ai/dsh-*` peer range is a cross-line interval (`>=0.1.0-rc.6 <0.3.0`, with the
|
|
94
|
-
three `dsh-client-*` peers keeping their `>=0.1.2-rc.1` lower bound) instead of a caret.
|
|
95
|
-
|
|
96
|
-
This matters because DSH validates each `@deepseek-ai/dsh` / `@deepseek-ai/dsh-*` peer
|
|
97
|
-
range against the single runtime version *before* importing a bundle, and **drops the whole
|
|
98
|
-
bundle** when any range does not match:
|
|
78
|
+
Runs on **both** the `0.1.x` and `0.2.x` DSH lines. DSH validates every `@deepseek-ai/dsh-*` peer range *before* importing a bundle and **drops the whole bundle** when any range does not match (no settings panel, no `rw_*` tools):
|
|
99
79
|
|
|
100
80
|
```
|
|
101
81
|
dsh: skipping profile bundle "dsh-remote": Error: Plugin dsh-remote@… is incompatible …
|
|
102
82
|
```
|
|
103
83
|
|
|
104
|
-
A caret on
|
|
105
|
-
`0.2.x` runtime — and `^0.2.0-rc.1` can never admit a `0.1.x` one. If you are on a version
|
|
106
|
-
**older than 0.8.29**, upgrade; if your plugin disappeared entirely after a DSH upgrade,
|
|
107
|
-
this is why. `test/compat.test.js` pins the ranges against DSH's own predicate so a caret
|
|
108
|
-
cannot creep back in.
|
|
109
|
-
|
|
110
|
-
### Official Desktop compatibility (experimental, unreleased)
|
|
111
|
-
|
|
112
|
-
This branch adds a compatibility path for the **official**
|
|
113
|
-
[DeepSeek Harness Desktop](https://github.com/deepseek-ai/deepseek-harness),
|
|
114
|
-
tested against the `0.1.5-rc.2` Host transport. It does not replace the Harness
|
|
115
|
-
core or require a listening Web server:
|
|
116
|
-
|
|
117
|
-
- The SSH settings and directory picker use `/api/dsh-remote/*` over the
|
|
118
|
-
Desktop's `dsh-app:` carrier. Exact Fetch routes are registered on
|
|
119
|
-
`ctx.connection.fetch`; the carrier retains ownership of authentication.
|
|
120
|
-
- A native **Remote Files** entry uses `sidebarRightTabs` and the keyed
|
|
121
|
-
`sidebar.right.pane.tab` seat. It reuses the existing explorer/editor and
|
|
122
|
-
gives remote files their own session-scoped resource addresses, rather than
|
|
123
|
-
sending remote paths to the local Files viewer.
|
|
124
|
-
- `dsh-better-sidebar` is not bundled. Web hosts may install it separately;
|
|
125
|
-
official Desktop uses the native right-sidebar integration instead.
|
|
126
|
-
|
|
127
|
-
Since **v0.8.19**, sidebar `/ls` `/read` `/write` `/fs` resolve the session's
|
|
128
|
-
mirror binding (same path as `rw_*`) when the client sends `sessionId`. Two
|
|
129
|
-
sessions on different hosts no longer share the active-machine pool for file
|
|
130
|
-
ops. Host-side tests cover that routing plus the editor 409/re-read/save path.
|
|
131
|
-
|
|
132
|
-
Official Desktop's native file-tab GUI, failed/cancelled dialogs, non-macOS
|
|
133
|
-
hosts, and a full legacy Web UI pass are still experimental. Desktop's package
|
|
134
|
-
installer may also require an explicit policy for the optional `ssh2` /
|
|
135
|
-
`cpu-features` build scripts. The isolated transport test disabled those
|
|
136
|
-
optional scripts; this change does not loosen an application's build allowlist
|
|
137
|
-
or automatically approve dependency scripts.
|
|
84
|
+
A caret on `0.x` is locked to that minor line (`^0.1.x` cannot admit `0.2.x`, and vice versa), so since **0.8.29** the ranges are cross-line intervals: `>=0.1.0-rc.6 <0.3.0`. **If you are below 0.8.29, upgrade the plugin before you upgrade DSH.**
|
|
138
85
|
|
|
139
|
-
###
|
|
86
|
+
### Official Desktop compatibility (experimental)
|
|
140
87
|
|
|
141
|
-
|
|
142
|
-
dsh plugin add dsh-remote # add the bundle
|
|
143
|
-
```
|
|
88
|
+
A compatibility path for the [official DeepSeek Harness Desktop](https://github.com/deepseek-ai/deepseek-harness), tested against the `0.1.5-rc.2` Host transport; it does not replace the harness core or require a listening Web server:
|
|
144
89
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
keeps the SSH tools and settings UI independent from a particular sidebar
|
|
149
|
-
implementation.
|
|
90
|
+
- SSH settings and the directory picker use `/api/dsh-remote/*` over the Desktop's `dsh-app:` carrier (registered on `ctx.connection.fetch`).
|
|
91
|
+
- A native Remote Files entry uses `sidebarRightTabs`, giving remote files session-scoped resource addresses instead of sending remote paths to the local Files viewer.
|
|
92
|
+
- `dsh-better-sidebar` is not bundled; official Desktop uses the native right sidebar.
|
|
150
93
|
|
|
151
|
-
|
|
94
|
+
Verified: host startup, IPC requests, real SSH read-only connect/list/read, and per-session routing (sidebar `/ls` `/read` `/write` `/fs` with `sessionId`). The native file-tab GUI, failed/cancelled dialogs and non-macOS hosts remain experimental. The Desktop installer may need an explicit policy for the optional `ssh2` / `cpu-features` build scripts.
|
|
95
|
+
|
|
96
|
+
### Published Web bundle
|
|
152
97
|
|
|
153
98
|
```bash
|
|
154
99
|
dsh plugin add dsh-remote
|
|
155
|
-
dsh plugin add dsh-better-sidebar
|
|
156
100
|
```
|
|
157
101
|
|
|
158
|
-
|
|
159
|
-
dynamically and registers its remote explorer/editor tabs. Without it, all
|
|
160
|
-
`rw_*` tools, the settings UI, sync, audit log, and port forwarding continue to
|
|
161
|
-
work. Official Desktop uses its native right-sidebar seats and does not need
|
|
162
|
-
`dsh-better-sidebar`.
|
|
102
|
+
Since **v0.8.18** it installs and mounts only itself; the Web sidebar ([dsh-better-sidebar](https://www.npmjs.com/package/dsh-better-sidebar)) is optional. Install it separately if you want the Web remote file explorer/editor — without it the `rw_*` tools, settings UI, sync, audit log and port forwarding all still work.
|
|
163
103
|
|
|
164
|
-
> **Upgrading from 0.7.2–0.8.17:**
|
|
165
|
-
> sidebar dependency and mount. Install `dsh-better-sidebar` separately only if
|
|
166
|
-
> you still want that Web UI. Any old profile override for
|
|
167
|
-
> `id: dsh-remote-sidebar` can be removed because that row no longer exists.
|
|
104
|
+
> **Upgrading from 0.7.2–0.8.17:** the embedded sidebar goes away; any old profile override for `id: dsh-remote-sidebar` can be removed.
|
|
168
105
|
|
|
169
106
|
(or `npm install dsh-remote` + add `- id: dsh-remote / name: dsh-remote` in `cordis.patch.yml`).
|
|
170
107
|
|
|
171
108
|
## Quick start
|
|
172
109
|
|
|
173
|
-
1. **Add a machine** — Settings → 远程工作区 →
|
|
110
|
+
1. **Add a machine** — Settings → 远程工作区 → host/port/user + key or password → set it current.
|
|
174
111
|
2. **Open a workspace** — click **Add workspace** in the sidebar / conversation:
|
|
175
|
-
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
3. **Work with the agent** — treat it like any workspace:
|
|
181
|
-
- `rw_list_dir(path?)`/`rw_read_file` — inspect remote files
|
|
182
|
-
- `rw_write_file(path, content)` / `rw_edit(path, old, new)` — create / patch a remote file directly
|
|
183
|
-
- `rw_stat(path)` / `rw_mkdir(path)` / `rw_remove(path, recursive?)` / `rw_move(path, dest)` — manage remote paths
|
|
184
|
-
- `rw_search(pattern, path?)` — grep remote files (SFTP walk, Windows OK)
|
|
185
|
-
- `rw_exec(command, cwd?, pty?)` — run remote shell commands (defaults to the workspace dir)
|
|
186
|
-
- `rw_forward(listenPort, targetHost?, targetPort?)` — open an SSH tunnel
|
|
187
|
-
- `rw_sync(dryRun?/force?/async?)` / `rw_push(dryRun?/force?/async?)` — conflict-aware mirror pull/push
|
|
112
|
+
- **Local** → system folder chooser (or type a path) → local workspace. Falls back to the in-app browser when no OS dialog exists.
|
|
113
|
+
- **Remote** → choose the machine → browse to a remote directory (or type `/path`) → "设为远程工作区" ⇒ a local mirror workspace is created and adopted.
|
|
114
|
+
3. **Work with the agent** — treat it like any workspace: `rw_read_file` / `rw_write_file` / `rw_edit` / `rw_exec` / `rw_search` / `rw_sync` / `rw_push` / `rw_forward` (full list above).
|
|
115
|
+
|
|
116
|
+
> **Remote context is session-scoped:** the "Remote workspace" system-prompt section appears only when the current session's workspace is a remote mirror; local sessions are unaffected and the model will not call `rw_*` on its own.
|
|
188
117
|
|
|
189
118
|
## CLI defaults (optional)
|
|
190
119
|
|
|
@@ -232,9 +161,7 @@ After a successful start, `Settings → 远程工作区` appears and the "Add wo
|
|
|
232
161
|
|
|
233
162
|
## Development (sandbox, not product)
|
|
234
163
|
|
|
235
|
-
Iterate
|
|
236
|
-
product profile is re-managed by the plugin manager and reverts hand-deployed
|
|
237
|
-
files on reinstall. Use the helper script:
|
|
164
|
+
Iterate in the sandbox — hand-editing a product profile is reverted by the plugin manager on reinstall:
|
|
238
165
|
|
|
239
166
|
```bash
|
|
240
167
|
scripts/dev-run.sh --restart # start / restart the isolated sandbox
|
|
@@ -242,25 +169,13 @@ scripts/dev-run.sh --stop # stop it
|
|
|
242
169
|
scripts/dev-run.sh --status # is it running?
|
|
243
170
|
```
|
|
244
171
|
|
|
245
|
-
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
- Node ESM resolves dependencies from the importing file's real path, so the
|
|
253
|
-
script **copies** `lib/` (hardlink copy, `cp -al`) into the sandbox profile
|
|
254
|
-
instead of symlinking — a symlink breaks `@deepseek-ai/*` resolution.
|
|
255
|
-
- Run `scripts/check.mjs` (static framework-constraint gate: command-name
|
|
256
|
-
regex, …) before every commit; `scripts/boot-smoke.sh` boots an isolated
|
|
257
|
-
instance to prove the plugin still starts.
|
|
258
|
-
- Full rules live in `scripts/dev-standards.md` (command names, cordis service
|
|
259
|
-
access via `ctx.get()` only, optional framework services may never register,
|
|
260
|
-
verify third-party callback contracts against the real runtime, …).
|
|
261
|
-
|
|
262
|
-
Deploying to a product profile is a separate, explicit action (`./sync.sh`)
|
|
263
|
-
and should be done only when you intend to release.
|
|
172
|
+
- The sandbox runs its own DSH instance (`dev-harness/harness`), serving on `http://127.0.0.1:50599`.
|
|
173
|
+
- **Host-half** (`lib/index.js`) changes need `--restart`; **client-half** (`lib/client.js`) changes need only a page refresh.
|
|
174
|
+
- The script hardlink-copies `lib/` into the sandbox rather than symlinking — a symlink breaks `@deepseek-ai/*` resolution.
|
|
175
|
+
- Before committing: `node check.mjs` (framework-constraint gate) and `npm test`; `scripts/boot-smoke.sh` proves the plugin still starts.
|
|
176
|
+
- Full rules live in `scripts/dev-standards.md`.
|
|
177
|
+
|
|
178
|
+
Deploying to a product profile is a separate, explicit action (`./sync.sh`) for releases only.
|
|
264
179
|
|
|
265
180
|
## Configuration
|
|
266
181
|
|
|
@@ -290,6 +205,8 @@ and should be done only when you intend to release.
|
|
|
290
205
|
| `fileReferenceMaxEntries` | int | `3000` | max entries retained in one remote workspace's `@` index |
|
|
291
206
|
| `fileReferenceExcludedDirectories` | string[] | `[.git, node_modules, dist, build, out, coverage, target, .next, .nuxt, .turbo, .venv, __pycache__, .pytest_cache, .mypy_cache, .gradle]` | directory basenames the remote `@` traversal skips |
|
|
292
207
|
| `fileReferenceTimeoutMs` | int | `4000` | wall-clock budget for one remote `@` index pass (on expiry the partial index answers rather than making the caret wait) |
|
|
208
|
+
| `searchTimeoutMs` | int | `60000` | Cooperative budget (ms) for `rw_search`: declared as the tool's `timeoutMs` for DSH's timeout policy and used as the search's own wall-clock cap; on expiry it returns partial results marked `TRUNCATED` (issue #44). |
|
|
209
|
+
| `searchMaxEntries` | int | `50000` | Max files `rw_search` scans before returning partial results. |
|
|
293
210
|
| `updateMode` | string | `auto` | self-update behaviour: `auto` checks npm on load and every 6h and applies a newer release; `manual` only checks when asked; `off` disables checks. **Default changed to `auto` in 0.8.27** — safe because 0.8.24 added the host-half hot swap |
|
|
294
211
|
| `updateCheckIntervalMs` | int | 21600000 (6h) | how often `auto` mode checks npm (floor 60000) |
|
|
295
212
|
| `updateAutoReload` | bool | `true` | hot-swap the host half after an update lands; `false` defers it to the next process start and the panel reports `pendingReload` |
|
|
@@ -298,27 +215,29 @@ and should be done only when you intend to release.
|
|
|
298
215
|
|
|
299
216
|
## FAQ / troubleshooting
|
|
300
217
|
|
|
301
|
-
**`@` lists remote files but the built-in read tool cannot open them** — the harness's own file tools see the
|
|
218
|
+
**`@` lists remote files but the built-in read tool cannot open them** — the harness's own file tools see the **local mirror**, which stays empty until `rw_sync` downloads it. Read remote files with `rw_read_file` or the sidebar remote tab.
|
|
219
|
+
|
|
220
|
+
**Host key changed** — `/remote forget-key` (or Settings → machine → trust again).
|
|
302
221
|
|
|
303
|
-
**
|
|
222
|
+
**"Authentication failed"** — check the username/password/key path; fill in the passphrase for an encrypted key; enable keyboard-interactive when the host requires OTP.
|
|
304
223
|
|
|
305
|
-
|
|
224
|
+
**Cannot reach an internal machine** — set a jump host (or add the bastion as its own machine first).
|
|
306
225
|
|
|
307
|
-
|
|
226
|
+
**`rw_sync`/`rw_push` reports conflicts** — files changed on both sides are skipped and listed (never silently overwritten); merge manually and retry, or pass `force=true`.
|
|
308
227
|
|
|
309
|
-
**
|
|
228
|
+
**Windows remotes** — everything goes over SFTP, no POSIX shell needed; read Chinese files with `encoding=gbk`.
|
|
310
229
|
|
|
311
|
-
**
|
|
230
|
+
**A directory is missing from the mirror** — the default ignore rules skip `.git`/`node_modules` and similar; adjust `$DSH_HOME/remote-workspaces/.dsh-remote-ignore` (gitignore syntax).
|
|
312
231
|
|
|
313
|
-
|
|
232
|
+
**Saving a remote file returns 409** — the remote file changed after you opened it; re-read and edit again.
|
|
314
233
|
|
|
315
|
-
|
|
234
|
+
**How are passwords stored?** — tick "encrypt password": macOS Keychain / Windows DPAPI / Linux secret-tool (libsecret); falls back to plaintext when unavailable.
|
|
316
235
|
|
|
317
|
-
|
|
236
|
+
**The plugin vanished after a DSH upgrade** — DSH's compatibility check dropped the bundle; upgrade to **0.8.29+** (see "DSH version compatibility" above).
|
|
318
237
|
|
|
319
238
|
## Safety
|
|
320
239
|
|
|
321
|
-
Giving the plugin a machine's credentials lets the agent run **shell commands as your user** on that host
|
|
240
|
+
Giving the plugin a machine's credentials lets the agent run **shell commands as your user** on that host — only add machines you trust. Passwords live in a local file (or the OS keychain); treat them as sensitive. With `auditLog` on, every command is recorded.
|
|
322
241
|
|
|
323
242
|
## License
|
|
324
243
|
|