dsh-cc-permissions
v0.7.1
Published
Enforce Claude Code permission rules (.claude/settings.json allow/deny/ask, deny>ask>allow) in DSH via a tools/pre-execute gate; CC allow rules auto-answer the approval/request seam (incl. sandbox escalation). Reads CC settings as a read-only source; DSH-
Maintainers
Readme
dsh-cc-permissions
[!IMPORTANT] Only upgrade to the
v0.3.xline when upgrading DSH to0.1.5-rc.2or later. It binds to the 0.1.5 host contracts (snapshotEvents()/eventAt(),^0.1.5-rc.2peer ranges) and does not work on older DSH. If your DSH is still0.1.0-rc.7–0.1.1-rc.2, do not upgrade — stay onv0.2.x. The two lines are mutually exclusive.
Enforce Claude Code permission rules in DSH.
Reads .claude/settings.json (user ~/.claude, project, and settings.local.json)
through the shared dsh-cc-loader parse layer and folds the rules
deny → ask → allow on every tool call, exactly like Claude Code:
Toolbare deny removes the tool from the model's context (per-agent hide)Tool(spec)scoped rules match commands, paths, domains, params, MCP tools- Bash compound commands are split; wrappers (
timeout,nice,nohup…) and leading env assignments are stripped before matching - Read deny rules also gate Edit/Write tools and Bash file commands
(
cat,head,tail,sed…) askrules route through DSH's approval serviceallowrules answer the approval seam automatically (see below)
Allow = run without asking (approval seam)
In Claude Code an allow rule is the complete gate: the command runs without
any further question. DSH has a second layer below the permission fold — the
file sandbox. When workspace-write denies a file effect and the model retries
with sandbox_permissions, an approval/request is raised for the escalation;
without a bridge, that request would still hit the human answerer even though
the user already allowed the exact command.
dsh-cc-permissions bridges this: an approval/request (permission ask or
sandbox escalation) whose underlying tool call matches a CC allow rule is
answered allowed-once automatically — one-shot, rule-scoped, and read from
the real tool arguments in the session log (tool/call by callId, never
the model-written reason), mirroring the pattern of
dsh-auto-approval-plugin.
Bash(pytest:*)→ the exactpytest …command may run outside the sandbox when escalated (CC semantics restored)- deny/ask rules and unmatched calls always defer to the human answerer; the module only ever auto-grants, never auto-denies
enableAllProjectMcpServers: truealso covers project MCP tools (mcp__<server>__<tool>, notmcp__plugin_…)
Disable with autoApproveAllowed: false in the plugin config.
Read-only bridge
CC settings.json is a read-only source. DSH-side approvals ("don't ask
again") are stored in DSH's own config and are never written back to
.claude/settings.local.json — CC, Codex and DSH have different permission
semantics, so cross-tool permission sync is intentionally out of scope
(community agents / cc-suite do not sync permissions either).
Install
The version is pinned deliberately: pnpm 11 withholds releases younger than 24 h, so a bare package name silently installs an older one and still reports success. See why the version is pinned.
dsh plugin --profile <name> add [email protected]Config
| Key | Default | Meaning |
| --- | --- | --- |
| enabled | true | Master switch |
| hideDeniedTools | true | Bare-name deny → per-agent ctx.tools.restrict |
| enableDefaultMode | true | defaultMode=dontAsk → approval policy never |
| autoApproveAllowed | true | allow rules auto-answer approval/request (incl. sandbox escalation) |
| homeDir | <home> | Home dir for ~/.claude/settings.json |
.mcp.json servers are default-open
Claude Code refuses tools from a project-scope MCP server until the user
approves it, and prompts for that approval interactively. DSH has no such
prompt, so copying the gate would leave every server a project .mcp.json
declares permanently unusable — listed in the panel, dead on every call, with no
way to say yes. The policy is therefore inverted: a project MCP tool runs unless
settings explicitly reject it.
| .claude/settings.json | Effect on a project-scope MCP tool |
|---|---|
| disabledMcpjsonServers: ["<server>"] | the call is refused |
| enabledMcpjsonServers / enableAllProjectMcpServers | read and reported, but they no longer decide anything |
| neither | the call runs |
User-, local- and plugin-scope MCP servers are never touched by this. The
approval/request seam above keeps the stricter reading: an approval raised
for an MCP tool (a sandbox escalation, say) is answered automatically only when
the server is explicitly approved — otherwise it reaches you.
License
MIT.
