Auto-approval agent for DSH permission requests: rule layer (denyAlways/allowlist) plus Hermes Pro semantic adjudication with quick-fail retries, fail-closed to human when Hermes is unavailable, rejection feedback returned to the requesting session, and approve tasks enqueued into the task queue with a shared busy mutex.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:nicecx/dsh-auto-approver
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
Configurable auto-approval for DeepSeek Harness. Intercepts
approval/request(and optionallyask_user_question) and answers by policy — rule layer, an optional Hermes Pro semantic verdict, or the human. Every decision is audit-logged.
Why
DeepSeek Harness asks for approval before privileged operations (file writes, command execution, danger-full-access, …). In a trusted, autonomous setup — or for a known-safe subset of tools — those prompts are pure noise. This host plugin intercepts every approval request before the relay/UI push and settles it, with a full audit log and an interactive reject loop (the agent is told why it was rejected and can retry).
It is the mirror image of dsh-reset-handoff: that plugin delegates restarts to an external ops agent; this one delegates approvals to a local policy and/or Hermes.
How it works
agent requests permission
→ 'approval/request' event (host emits)
→ dsh-auto-approver (prepend, before relay/UI)
│
├─ denyAlways hit → 'rejected' (never prompts; Hermes cannot override)
├─ mode=allow-all → 'allowed-once' (never prompts)
├─ mode=allowlist → hit → 'allowed-once'; miss → next() (human asked)
├─ mode=hermes → allowlist hit → 'allowed-once'
│ else → Hermes Pro semantic verdict
│ (deepseek-v4-pro, 90s timeout, fail-closed → human)
└─ mode=off → next() (all to human, plugin inert)
→ every decision is appended to the audit log
→ 'rejected' also follows up the reason to the requesting session
Registering with { prepend: true, global: true } makes the plugin answer before dsh-relay pushes the prompt to iMessage/Web — an auto-settled request never disturbs the human.
QnA takeover (optional)
With qnaMode: 'hermes', ask_user_question is also answered by Hermes Pro instead of interrupting the human. Hermes sees the question and its options (or free-form) and returns a choice per the relay answer format; if Hermes is unavailable it falls back to the human.
Install
dsh plugin --profile <profile> add github:nicecx/dsh-auto-approver
Configuration
Override in your profile patch (cordis.patch.yml):
- id: dsh-auto-approver
name: 'dsh-auto-approver'
config:
mode: 'hermes' # allow-all | allowlist | hermes | off (default: allow-all)
allowlist: [] # tools auto-approved (rule layer; hermes mode: direct pass)
denyAlways: [] # tools always rejected (highest priority, Hermes cannot override)
denyReasons: {} # tool → reject reason text fed back to the agent
hermesModel: 'deepseek-v4-pro' # verdict model (Pro = highest capability)
hermesTimeoutSecs: 90 # verdict timeout; on failure → human (fail-closed)
feedbackOnReject: true # followup the reject reason to the requesting session
qnaMode: 'off' # 'hermes' = ask_user_question answered by Hermes Pro; 'off' = human
userGranted: [] # endorsement signal (NOT a bypass card) — see below
logPath: '' # audit log path (default ~/.dsh/auto-approver.log)
| mode | behavior |
|---|---|
allow-all |
auto-approve everything (incl. danger-full-access). Trusted environments only. |
allowlist |
auto-approve only listed tools; everything else asks the human. |
hermes |
rule layer (denyAlways / allowlist) + Hermes Pro semantic verdict for the rest. |
off |
plugin inert; everything goes to the human. |
userGranted — endorsement signal, not a bypass card
userGranted is a soft endorsement passed into the Hermes verdict prompt ("the user explicitly authorized this tool — lean toward approval when the operation is reasonable and carries no data-destruction / credential-exfiltration risk"). It is not a hard allow:
denyAlwaysstill wins over everything.- Hermes still rejects dangerous operations (data destruction, credential exfiltration, irreversible deletes).
- Keep it empty by default — adding broad tools (
bash,write) conflicts with the least-privilege principle. Only list capabilities the user explicitly named.
Interactive reject loop
When the policy (or Hermes) rejects, the plugin follows the reason back into the requesting session, so the agent knows what was wrong and can retry with a corrected request (e.g. narrower permission, concrete path, specific command). Manual approval on iMessage/Web always wins.
Audit log
Every decision is appended (JSON lines) to ~/.dsh/auto-approver.log:
{"ts":"...","sessionId":"...","toolName":"bash","reason":"...","callId":"...","decision":"allowed-once"}
Hermes verdicts also carry the reason in note (e.g. hermes: ...).
Safety notes
allow-allauto-grants everything, including full-access commands. Preferallowlist/hermesin anything less than a fully trusted single-user box.hermesmode is fail-closed: if Hermes is unavailable or times out, the request goes to the human — never silently granted.- The relay/Web double-track is untouched: when the policy says
ask, the human still decides on iMessage or the Web UI; manual approvals always win. - The audit log is the complete record of auto-decisions — keep it.
License
MIT
Links
More in this category
yjh051108/dsh-routing-suite★ 7022
One repository, three parts: a runtime injector for DSH plugin packages (inject, hot-reload, unload, promote a dev staging tool to the front, route self-heal, plus a settings-page plugin manager that lists, unloads and drags folders in to internalize), a task-aware reasoning-mode router agent preset (router-standard / router-spec / router-react), and a graded two-level task protocol whose six tools (commit_star, lock_stage, revise_do, edit_plan, mark_task, redteam_verdict) pin task state to disk. The injector implementation ships in-tree, so the install carries its own behaviour rather than a dependency list.
strukto-ai/mirage#dsh★ 3691
Swaps the filesystem and bash providers for a mirage virtual workspace: file tools and shell commands run over mounted resources (RAM, S3, Redis, Slack, Gmail, Notion, Postgres) instead of the host disk, with per-mount read/write/exec modes, per-command sandbox routing (monty, pyodide, quickjs in process; docker, e2b, daytona remote), and installed CLIs (git, gh, slack, linear, ntn, gws, or one you register) as head words in the virtual terminal.
hust-open-atom-club/oh-dsh★ 322
Community distribution: TUI, desktop, and Web UI as one bundle with layered installation.
weijiafu14/pi2dsh★ 216
Pi Host ABI compatibility engine: after one install, unmodified Pi extensions from npm mount as native DSH plugins with `dsh plugin add <pi-package>`. Verified end to end on stock DSH with pi-mcp-adapter (full MCP manager: OAuth, resources, prompts, MCP Apps, elicitation, sampling), @tintinweb/pi-subagents, pi-code, pi-hermes-memory and pi-background-tasks; `pi2dsh inspect` reports a package's compatibility before installing.
Fishquito7/dsh-skill-mcp-panel★ 202
Manages DSH skills and MCP servers from the web settings: skill cards with hot enable/disable, workspace scopes, groups, batch migration and drag-and-drop import, plus stdio/HTTP MCP CRUD with connection tests, secret redaction and the unified dsh-panel CLI.
lire1131/dsh-undo-savepoint★ 181
Undo/redo & rollback system for DSH: every config change is auto-snapshotted; undo/redo/restore to any version from the WebUI or the offline CLI/GUI tools (works even when DSH fails to boot).
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.