Adds an Explain button to the approval card: one model call returns exactly three lines reading the pending operation, covering what it does, which files or system state it reads, writes, modifies or executes, and a risky/attention/safe verdict with a one-sentence justification. It also renders the detail area for `write` and `edit` calls, which the shipped renderer leaves blank because it only reads a `command` field.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:Martlet-Tech/dsh-approval-explain
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
中文 | English
Adds an Explain button to DeepSeek Harness approval cards: one click spends one LLM call telling you what the thing you are about to approve actually does.

┌─ ● Waiting for approval ────────────────────────────┐
│ │
│ escalate sandbox to danger-full-access: user … │
│ Set-Content -LiteralPath 'D:\Downloads\notes.md' │
│ …(a very long script body) │
│ │
│ [ 💡Explain ] [ Reject ] [ Allow ] │
│ │
│ What: creates (or overwrites) notes.md under … │
│ Touches: writes D:\Downloads\notes.md; deletes … │
│ Safety: caution — overwrites a same-named file … │
└────────────────────────────────────────────────────┘
Why you need it
The approval card has a "detail" area that shows what you are approving. It is filled by an extractor that only recognizes a command field:
// packages/client/ui-chat/src/client/chat/ApprovalCommand.tsx
return typeof args.command === 'string' ? args.command : undefined
So only tools whose argument happens to be named command — bash, pwsh — can put anything in that area. For tools like write / edit, whose arguments are file_path + content, that area is always empty.
The result: a card saying "escalate sandbox to danger-full-access" while you cannot see what you are actually approving.
This plugin does two things:
- Never leaves it blank — it takes over the detail area and supports all three argument shapes:
command/file_path/path; - Lets the model read it for you — the Explain button makes one LLM call and returns a fixed three-line verdict: What / Touches / Safety.
The Explain button reuses the native button geometry (outline, 36px capsule) so it sits flush with Reject / Allow once, tinted with the DeepSeek family colors (--dsw-static-deepseek-50 / -500) and prefixed with a 💡 icon.
Install
Requires pnpm (dsh plugin is a forwarding shell for pnpm). Enable it if you have not:
corepack enable pnpm # Node ships corepack; recommended
# or
npm i -g pnpm
Then:
dsh plugin --profile web add github:Martlet-Tech/dsh-approval-explain
Restart dsh / DShell after installing — a profile reads its bundle list only at startup.
If it does not take effect
dsh plugin add puts the package into the profile's node_modules and, because this package declares dsh.bundle, appends it to dsh.profile.bundles. If that append does not happen (a pnpm version difference, for example), add the line by hand:
// $DSH_HOME/profiles/web/package.json
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-approval-explain" // ← add this line
]
}
}
Verify with dsh --profile web --dump-config: the output should contain a # == dsh-approval-explain layer.
Why no build authorization is needed
This package ships its build output directly (lib/ is committed), so it runs no prepare script and never triggers the pnpm ≥10 allowBuilds prompt for git dependencies.
Uninstall
dsh plugin --profile web remove dsh-approval-explain
The plugin is additive: it takes over the approval card by priority and disables none of dsh's Loader rows. Uninstalling it, or having it fail to load, restores dsh's original behavior completely.
/explain <content> also works directly in the composer, without the button.
Requirements
- dsh
0.1.5-rc.1or newer - A configured model provider (it reuses your current session's provider/model; no extra configuration)
- Web GUI only (
dsh web)
Finding other plugins
dsh has no plugin store — no official marketplace, no remote registry, and the GUI cannot browse or install. Discovery happens through GitHub topics:
github.com/topics/dsh-plugin— the only channel the official README recommendsawesome-dsh-plugin— a community-curated list
Installs always go through dsh plugin --profile <name> add <spec>, where <spec> may be an npm package name, github:user/repo, a tarball, or a local path.
How it works
The whole path uses mechanisms dsh already has; it adds no remote endpoint:
Browser "Explain" button
└─ ctx.remote.commands.execute(sessionId, '/explain <content>', [])
└─ host-side /explain command handler ← runs on the Host, can reach ctx.llm
└─ ctx.llm.stream({ provider, model, messages, system })
└─ text deltas accumulate → { kind: 'success', text }
└─ the result returns synchronously and expands in place
Two design decisions are worth explaining:
Why a "human command" instead of a custom remote API. ctx.llm is a host-side service with no @Remote, so the browser cannot reach it. A custom @Remote endpoint would need Typert code generation, which only scans packages/ inside the dsh repository. ctx.remote.commands.execute() is already mounted and its command handlers run host-side — the only ready-made channel that needs no changes to dsh. /compact is the existing precedent for this path.
Why the whole file has zero imports. The plugin loads as an out-of-tree package through the profile's junction; Node walks up from the junction's real path looking for node_modules, and there is no @deepseek-ai/* there. So the host half gets its service via ctx.get('llm') and builds messages literally against the Message shape, importing no package at all.
Known limitations
- Every click leaves a trace: the command system records
command/run+command/donelines in the session log. That is auditability, not zero footprint. - Explaining costs tokens: a small request capped at roughly 700 output tokens. dsh has no approval gate on LLM calls, so this step has no second confirmation.
- It takes over the whole approval card: the "Reject / Allow once" row is rendered by dsh itself and exposes no slot, so putting a button on that row means taking over the card. If dsh changes the card structure in the future, this plugin will need to follow.
- It is coupled to
StreamChunkfield names:text-delta/block-end/finishare the current structure; zero dependencies means tracking the version. - For now it only explains. It does not change the approval outcome and does not cache verdicts.
License
MIT
Links
More in this category
kenryu42/cc-safety-net★ 1900
Pre-execution guard that blocks destructive Git and filesystem commands and access to secrets such as SSH keys and .env files before a tool call runs.
ADWMC/helm-d#helmd★ 984
Security-analysis plugin for DeepSeek Harness: 33 tools spanning six security domains, evidence/reporting and toolbox, plus the case lifecycle, routing and tool ledger; a session-bound case workflow with an evidence chain, E-id validation and reproducible findings; 362 on-demand references; three hot-swappable persona profiles; and a four-tab workbench (armor / case / intercept / about) with case-state recovery after context compaction.
toby-bridges/api-relay-audit★ 904
Runs local security audits of AI API relays and LLM proxies from DeepSeek Harness, producing Markdown reports for prompt injection, model substitution signals, tool-call rewriting, error leakage, stream integrity, and profile-gated Web3 risks.
SeaOf0/dsh-redteam-model★ 807
Authorized-security DSH collection: nine work modes (redteam coordinator, pentest, code audit, binary analysis, attack-defense, AV evasion, incident response, cloud security, CTF solving) and fifteen runtime plugins, managed from a settings page with one-click deploy, install, update and uninstall.
howmp/dsh-pentest★ 616
Authorized pentest mode for DeepSeek Harness — exploration chain, assets and findings with a Web view.
PerryLink/dsh-auto-review★ 244
Second-model auto-review on the approval answerer chain: a read-only reviewer subagent returns structured allow/deny verdicts with reasons, fail-closed by default.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.