DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Helper Plugin Command Ask — DeepSeek Harness 插件(DSH Plugin)
← Plugins
H

dsh-helper-plugin-command-ask

Helper Plugin Command Ask

dsh 插件:为 DeepSeek Harness (dsh) 提供类似 Cursor 的 /ask 模式——单轮只读问答,强制使用只读工具保护,并根据 /ask 命令记录整合持久状态。通过 link: 或 github: 安装。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:x102201/dsh-helper-plugin-command-ask#b6f9970c28af15273e1f0a54e27920575afa9124
README兼容性版本
The dsh-helper workbench: /ask answers a question read-only and refuses to write, then the next message without /ask creates the file

兼容性与来源证明

Helper Plugin Command Ask 以 dsh-helper-plugin-command-ask 发布,当前版本为 0.2.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
any
发布来源
github
Registry 更新时间
2026/9/20

版本

0.2.0stable
2026/9/20

相关插件

正在加载相关插件…

最新版
0.2.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
any
许可证
MIT
发布源
github
GitHub
★ 0
周下载
0
最近提交
2026/9/20
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录

相关插件

继续浏览 developer-tools 分类下经过校验的插件。

Better Sidebardsh-better-sidebarDSH web 插件:类似 VSCode 的右侧边栏(资源管理器 / 编辑器 / 终端 / git / 浏览器),按对话会话隔离。提供服务,供其他插件注册侧边栏标签页和文件查看器。Find Plugindsh-find-plugin在代理中查找 DeepSeek Harness 插件——实时搜索 GitHub 上的 dsh-plugin 主题,并按星标数排序。DSCODE@toddzheng024/dscode-bundle完整的 DeepSeek 编码代理,支持持久化 shell、Ultra 协作和自动权限审查。Plugindsh-pluginDeepSeek Harness 社区插件市场,遵循官方插件规范——无需离开应用即可浏览、搜索并安装 9000+ 个由人工精选的社区插件。· DeepSeek Harness 社区插件市场(遵循官方开发规范):9000+ 人工精选社区插件,每日更新。

README

dsh-helper-plugin-command-ask

English | 中文

An /ask mode for DeepSeek Harness (dsh), modeled on the shipped /plan mode and on Cursor's Ask mode: a read-only Q&A answer for the turn the question belongs to.

Why it exists: a normal dsh session edits files as it works. Sometimes you only want an answer — where is this configured, why is this retrying, what breaks if I change it — without the agent touching anything. In an ask turn it may look but not change, and a tool guard makes that true even when the model forgets.

How it feels: /ask <question> answers that one question read-only — cited, no edits — and the mode ends with its turn, so a later message without /ask is ordinary work again. Ask something, then just say "do it". /ask off only cancels early.

/ask why is the retry budget 3?    answer this read-only, then back to normal
/ask                              arm ask mode for the next turn
/ask off                          cancel early (never required)

Install (one line):

dsh plugin --profile web add link:/absolute/path/to/dsh-helper-plugin-command-ask
dsh plugin --profile web add github:x102201/dsh-helper-plugin-command-ask

What it does

PieceBehavior
/ask commandArms ask mode, optionally with the trailing question (images/files allowed). <scope: turn> covers one turn; session (config) keeps the /plan-like standing stance until /ask off.
Turn boundaryA turn-scoped mode is released by the harness's own turn/end event, so the next request is assembled without it — no /ask off needed.
ask:policy prompt sectionRenders the deployment's guidance on every request while the mode is active, and nothing while it is off.
Durable stateThe ask projection folds the /ask command/run/command/done records and turn/end out of the session log. The plugin writes no session-event vocabulary of its own, and each switch is checkpointed through ctx.sessions.flush() so it survives a restart.
Read-only guardOn by default: a monotonic ctx.tools.guard() denies the configured mutating tools while ask mode is active, and tells the model to answer from what it can inspect.
Plan-mode handoffOnly with scope: session: entering a standing ask mode leaves plan mode, so two contradictory stances are never active at once.
Programmatic controlProvides ctx.askMode with get(agent), set(agent, active) (dispatches the real command), isActive(session).

Each ask turn is a fresh, self-contained stance: the guidance is present exactly in the requests it governs, and the log records every switch as an ordinary /ask command record.

Upgrading from 0.1.x

0.1.x persisted the mode as its own session event type, ask/mode. An out-of-tree plugin cannot add to the harness vocabulary — Session.append() cannot set the envelope's ignorable marker, so the persistence reader refuses a log containing such an event ("unknown to this harness and not marked ignorable; refusing to interpret the log") and every session that had ever run /ask became unloadable. 0.2.0 writes no such event, and scripts/repair-ask-mode-logs.mjs marks the leftover records ignorable in place (dropping them would break the log's required dense seq numbering):

node scripts/repair-ask-mode-logs.mjs --sessions <DSH_HOME>/sessions                # dry run
node scripts/repair-ask-mode-logs.mjs --sessions <DSH_HOME>/sessions --apply --backup <dir>

The projection's stateVersion moved to 2, so a cached row from 0.1.x is discarded and the state is refolded from the command records — no further migration is needed.

Install

Both installation styles are supported. The package ships plain ESM (no build step, no runtime dependencies), so nothing has to be compiled or allowlisted by pnpm at install time.

Prerequisite: dsh plugin forwards its arguments to pnpm, so pnpm must be on PATH (corepack enable pnpm provides it). Without it the CLI prints pnpm not found on PATH and exits 127.

1. From a local checkout (link:)

dsh plugin --profile web add link:/absolute/path/to/dsh-helper-plugin-command-ask
  • The path must be absolute, or relative to the directory you run the command from (the CLI anchors relative link:/file: specs to your invoking directory, not to the profile).
  • link: symlinks the checkout, so edits to index.js/lib/*.js take effect on the next dsh web restart with no reinstall.

2. From a Git host (github:)

dsh plugin --profile web add github:<owner>/<repo>
  • The repository root must be this package (the directory holding package.json and cordis.patch.yml).
  • Pin a revision when you want reproducibility: github:<owner>/<repo>#<tag-or-commit>.
  • Because there is no prepare/postinstall script, pnpm never asks you to allowlist a build.

What happens underneath

dsh plugin ... add forwards to pnpm inside $DSH_HOME/profiles/web, then reconciles the profile manifest: because this package declares dsh.bundle.patch, its name is appended to dsh.profile.bundles automatically. On the next boot that bundle's patch layer adds one host row:

- insert:
    - id: command-ask
      name: ./index.js      # anchored to the patch file, so any install layout works

Restart the profile to mount it:

dsh web            # alias of: dsh --profile web

Try it without installing

examples/standalone.patch.yml anchors ../index.js to the patch file, so a bare checkout runs as-is:

dsh --profile web --patch <checkout>/examples/standalone.patch.yml

That is the fastest loop while editing index.js/lib/*.js; no install and no profile edit.

Verify the install

# The composed tree should list a command-ask row:
dsh --profile web --dump-config | grep -A2 command-ask

Then, in the Web UI composer, type /ask — the slash menu lists /ask Enter or leave ask mode (read-only Q&A), and the command result says Ask mode on (read-only). Use /ask off to leave. Ask a question, and try asking for an edit: the model should explain the change instead of making it, and a denied tool call reports ask mode is read-only.

To check a running instance without a browser, point the live script at the URL dsh web printed:

node scripts/verify-live.mjs --url "http://127.0.0.1:PORT/?token=TOKEN" --workspace <dir>
node scripts/verify-live.mjs --url "..." --workspace <dir> --model-turns

It drives the same HTTP RPC the browser uses (a live session is created, then commanded), asserting the /ask registration, the command results, the live ask projection value, and the durable ask/mode events. --model-turns adds two real turns — one in ask mode asking for a file to be created, one after /ask off — and asserts the file appears only in the second.

Uninstall

dsh plugin --profile web remove dsh-helper-plugin-command-ask

The reconciler drops the bundle from dsh.profile.bundles when the dependency is gone. The session log keeps the ask/mode events it already recorded; they simply have no reader afterwards.

Configuration

Every key is optional; a bare row gets the defaults. Config is validated at load — an unknown key, a wrong type, or a blank section fails the boot instead of silently doing nothing.

- id: command-ask
  config:
    scope: turn          # one turn per /ask (default) …
    enforce: false
    blockedTools: [write, edit, pwsh]
# … or scope: session for the /plan-like standing mode
KeyTypeDefaultMeaning
scopeturn | sessionturnturn: ask mode covers the turn it was entered for and is logged off at that turn's boundary. session: it stands until /ask off, like /plan.
sectionstringbuilt-in guidance for the chosen scope (see lib/config.js)Text rendered as the ask:policy prompt section while the mode is active.
enforcebooleantrueRegister the read-only tool guard. false keeps the mode advisory: guidance only.
blockedToolsstring[]the 22 mutating tools listed belowTool names denied while ask mode is active. Replaces the default list.
allowedToolsstring[][]Names that always pass, checked before blockedTools.
supersedePlanModebooleanfalse for scope: turn, true for sessionLog plan mode off when ask mode is entered. A one-turn mode leaves the modes around it alone.
narratebooleanfalse for scope: turn, true for sessionInject a one-line "the user switched this session to ask mode" notice when the switch happens between turns. A one-turn mode has nothing to narrate: the guidance is simply present in the turn it governs and gone afterwards.

Explicit values always win: scope: turn with narrate: true is a legal (if chatty) combination.

Where to put an override: the profile's own cordis.patch.yml ($DSH_HOME/profiles/web/cordis.patch.yml), a --patch overlay applied after the bundle, or examples/profile-patch.yml as a starting point. A patch replaces the targeted row's whole config, and every omitted key falls back to the plugin default, so restate only what you change.

The default deny list, by intent:

  • File mutation — write, edit, str_replace_editor, apply_patch, multi_edit, notebook_edit
  • Shells (dual-use, but anything can be written through them) — pwsh, bash, terminal, shell
  • Work tracking and objectives — todo_write, create_goal, update_goal
  • Delegation and orchestration (children do not inherit the mode's promise) — subagent, subagent_fork, subagent_codex, subagent_claude_code, workflow, ralph, send_message, interrupt_agent
  • Background-work control — job_kill

It is a deny list on purpose: an unknown tool — a deployment's MCP tool, another plugin's tool — stays callable rather than being blocked by an allowlist this plugin cannot know about. Readers (read, glob, grep, job_list, job_output, web_search, web_fetch, skill, ask_user_question, present, …) are untouched.

How it works

/ask ──► ctx.commands.register('ask')  ──► session.append('command/run' | 'command/done')
                                                        │
                                                        ▼
                                    ctx.sessionProjections unit 'ask'
                                    folds /ask records + turn/end  ──►  view { active, pending }
                                                        │
                          ┌─────────────────────────────┴──────────────────────────┐
                          ▼                                                        ▼
       ctx.systemPrompt.section('ask:policy')                  ctx.tools.guard(read-only)
       (guidance on every request while active)                (deny mutating tools while active)
  • The durable state is the command record. /ask is a command, and the command registry already logs command/run + command/done for it — the mode is a pure fold over those records plus the harness's turn/end and request/header events. Resume, fork, and compaction recover the mode by replaying the log, and there is no live mirror to keep in sync.
  • No vocabulary of its own. A plugin outside the harness repository cannot add a session event type: Session.append() cannot set the envelope's ignorable marker, and the persistence read path refuses an unknown type that lacks it. Everything here is expressed in events the harness already knows, so a session log stays readable by any harness — with or without this plugin loaded. test/plugin.test.mjs asserts the log holds nothing else.
  • Immediate durability. The projection's change feed calls ctx.sessions.flush(session) (the harness's own checkpoint entry point) so a switch reaches disk in well under a second instead of waiting for the next model request.
  • Turn-scoped release. With the default scope: turn, the harness's own turn/end record ends the mode; the next request is assembled with no ask:policy section and no guard. That is what makes "ask a question, then say 'do it'" work without /ask off.
  • Prompt stability. The section is registered once and returns '' while the mode is off, so entering or leaving a mode never changes the request's tool catalog. This is why the mode can be enforced by a guard instead of by hiding tools.
  • Narration (scope: session only). When the last request/header described a different mode than the one now in effect, one plugin-sourced notice rides the next admitted step, so the model is not left reasoning under the old stance. A one-turn mode needs none: the guidance is present exactly in the turn it governs.
  • Enforcement seam. ctx.tools.guard() is monotonic and runs after the tools/pre-execute waterfall: a denial cannot be overridden by another listener, and it covers nested run_code sub-dispatches too (the tool registry propagates the calling agent into sub-dispatches).
  • Plan-mode handoff (scope: session only): a standing ask mode is strictly narrower than plan mode, so entering one leaves the other. The plugin writes plan mode's own known plan/mode event rather than calling a service: no realm crossing, and the fold recovers the result like any other switch. With plan mode not composed, the check reads an absent projection and does nothing.

Differences from /plan

/plan/ask (default)/ask (scope: session)
Purposedesign, then execute after approvalanswer this question, change nothinganswer, change nothing, until asked otherwise
Lifetimeuntil exit_plan_mode//plan offone turnuntil /ask off
Exitexit_plan_mode with a user review, or /plan offautomatic at the turn boundary/ask off
Enforcementguidance only (deployment owns sandbox/approval)guidance plus a deny-list tool guard (enforce)same
Other modesowns the session stanceleaves plan mode alonelogs plan mode off
Browser UIcomposer "Plan" chip over the plan projectionnone — command result textnone — plus the switch notice
Mount planeper agent preset, in an entry-local realmone host row, global for every agentsame

Where ask mode is not a boundary

  • The guard is a deny list, so a mutating tool whose name the plugin does not know (a deployment-specific tool) stays callable. Add it to blockedTools.
  • The hard boundary stays where it belongs: DSH's sandbox mode and approval policy. Ask mode narrows what the agent may do by tool name; it does not change filesystem or process permissions. A read-only deployment is sandbox: read-only, independent of this plugin.
  • The model can still answer incorrectly. The guidance demands cited evidence and explicit uncertainty, and nothing more than that.
  • With scope: turn, everything the user sends while that turn runs is inside the turn and therefore still read-only; the mode is released when the turn ends, not per message. Queue a new message to get ordinary work back.
  • A pending selection is process-local until its boundary append. If the process exits before the next accepted pre-step, that in-flight selection is lost and the UI must reapply it — the same property /plan has.

Compatibility

Written against dsh 0.1.5-rc.2. Services and seams used, all host-plane:

SeamPurpose
ctx.commands.register() (optional injection — a UI-less profile still gets the mode)the /ask command, whose records are the durable state
ctx.systemPrompt.section() + getSectionOrder('PLAN_POLICY')the ask:policy section
ctx.sessionProjections.register() / stateOf() / onChanged()the ask unit, the plan/turnBoundary reads, and the checkpoint trigger
ctx.sessions.flush()making a switch durable immediately
ctx.tools.guard()the read-only denial
ctx.on('agent/pre-step'), agent.steer()the scope: session switch notice, and steering the trailing question
session.append() (only plan/mode), ctx.provide('askMode')the plan handoff and programmatic control
projection stateSchema/viewSchemaa tiny parse-compatible validator, not zod

Two deliberate soft spots, so that a missing shoulder does not break a boot: an absent ask/plan projection reads as "off", and an absent turnBoundary projection means "no open turn" (with one warning). The plugin also imports no bare specifier at all — that is what makes link: and github: installs behave identically (Node resolves a linked package's imports from its real path, outside the profile's node_modules). test/package.test.mjs enforces that property.

Mounting the plugin inside an agent preset instead of the host plane is possible; see examples/agent-preset-mount.yml.

Tests

npm test              # node --test
npm run test:direct   # one process instead (for sandboxes that block the runner's child processes)

82 tests cover the config validation (including the scope defaults), the projection fold and its schemas, the read-side mode helpers and the plan handoff, the guard, the package's installability properties, and the plugin's wiring over a fake Cordis tree — including ask turns that end on their own, several in a row, the immediate checkpoint on a switch, the ctx.askMode.set path through the real command, and a replay of the mode after a resume.

Verification status

Every layer below was run; the live ones used a scratch $DSH_HOME and an isolated dsh environment (env_001ca237), never the profile serving the authoring session. Full command transcripts and raw output: VERIFICATION.md.

  1. Behavior — 82 unit/integration tests drive the real index.js/lib/*.js against a faithful stand-in for the Cordis seams (test-support/harness.mjs).

  2. Package shape — static tests pin the property both install methods depend on: the runtime imports no bare specifier (a link: install cannot resolve one, because Node resolves a linked package's imports from its real path) and the package ships no install-time script pnpm would have to allowlist.

  3. The install commands — against scratch profiles, with dsh 0.1.5-rc.2 and pnpm 12.5.1:

    • dsh plugin --profile web add link:<absolute checkout> → initialized the profile, linked the checkout, and the reconciler appended dsh-helper-plugin-command-ask to dsh.profile.bundles on its own.
    • pnpm pack → 24 files, then dsh plugin --profile web add <tarball> → the same reconciliation and the same composed row.
    • git clone --bare of this repository, then dsh plugin --profile web add git+file://<bare repo> → same reconciliation, same row. This is pnpm's git fetcher, i.e. the github: code path with a local transport. In every case --dump-config composed id: command-ask with the name anchored inside the installed copy, and --port 0 --no-open activated and served the UI.
  4. Activation in a real tree — scripts/verify-profile.ps1 -Probe prints markers from inside apply(): the row reached the active state (dsh fails loudly on any entry that does not), and apply() ran with commands, tools, systemPrompt, sessionProjections, and sessions all resolved, so the ctx.inject(['commands'], …) callback that registers /ask executed.

  5. Live behavior, including real model turns — scripts/verify-live.mjs --model-turns against a running web instance, on the turn-scoped default: 22/22 checks passed, including "every event in the log belongs to the harness vocabulary (no plugin-defined types)", "ask mode ended with its turn, with no /ask off" and "the next message without /ask created the file".

  6. Restart and resume — the same environment was restarted (hard kill included) with sessions that had run : they load again ( returns their records) and the mode is recovered from the log. An armed-but-unrun also survives a hard restart, because the switch is checkpointed on the spot:

Not covered: the Web composer round-trip through a browser (there is no client half — feedback is the command result text and, for scope: session, the switch notice). Everything the command surface can reach is covered above.

Layout

index.js                     Cordis plugin: wiring, the /ask command handler
cordis.patch.yml             the bundle patch (dsh.bundle.patch): one host row
lib/config.js                config schema, defaults, the built-in guidance text
lib/controller.js            mode state machine (commit / queue / cancel, narration, plan handoff)
lib/projection.js            the `ask` session-projection unit
lib/guard.js                 the read-only tool guard
lib/message.js               dependency-free createUserMessage / notice
lib/schema.js                tiny parse-compatible schemas (no zod)
examples/                    profile patch, portable --patch overlay, agent-preset mount
scripts/run-tests.mjs        single-process test runner
scripts/verify-profile.ps1   scratch-profile verification against a real dsh (--dump-config + boot + -Probe)
scripts/verify-live.mjs      live verification against a running instance (HTTP RPC; --model-turns)
scripts/repair-ask-mode-logs.mjs    repairs logs written by 0.1.x (marks the stray records ignorable)
test/                        the suite (config, projection, controller, guard, wiring, package shape)
test-support/harness.mjs     the fake-Cordis tree the wiring tests drive
README.md / README.zh.md     the reference in English and Chinese
VERIFICATION.md / .zh.md     what was actually run, with raw output

License

MIT.

/ask
session/page
/ask
session-8d4ba696 … : 6 renderable records after the restart
  seq 3 command/run name=ask args=""
  seq 4 command/done kind=success
ask before paging : {"active":true,"pending":false}