description: "The model-facing bash tool for users and maintainers choosing, configuring, or debugging one-shot command execution, background jobs, and sandbox escalation."
English | 中文
dsh-tool-bash gives the agent a bash tool that runs commands through the mounted shell executor and returns stdout, stderr, and exit markers. Each call runs in a fresh shell — no cwd, variables, or functions survive — and run_in_background turns long-running commands into background jobs the agent collects with job_output and stops with job_kill. Every call runs with the managed DSH_* environment from dsh-shell-env, and under a sandboxing executor a denied command may be retried once with a wider sandbox_permissions mode plus a justification through user approval. Non-zero exits are reported, not failed, so the agent decides how to react. Mount it together with an executor provider such as dsh-bash-local or dsh-bash-sandbox and the dsh-shell-env plugin.
Load this plugin in any composition where the agent should run bash commands: it registers the bash tool once an executor provider and the dsh-shell-env registry are mounted, and stays pending until the tools, shell, systemPrompt, and shellEnv services exist.
The common path is an executor provider, the environment registry, and this tool; add the job runtime when the agent may run commands in the background.
- name: '@deepseek-ai/dsh-bash-local'
- name: '@deepseek-ai/dsh-shell-env'
- name: '@deepseek-ai/dsh-tool-bash'
# Optional: background jobs
- name: '@deepseek-ai/dsh-jobs-local'
- name: '@deepseek-ai/dsh-tool-jobs'
The single config field toggles background support.
| Field | Default | Meaning |
|---|---|---|
enableRunInBackground |
true |
Expose run_in_background; when false, forced background calls are rejected |
The generated configuration catalog is the exhaustive source for every accepted field and its JSDoc; the generated tool catalog carries the full argument schema.
The tool executes bash -c <command> and returns the combined output. Commands run in a fresh shell every call, so state never persists — pass workdir instead of cd. A non-zero exit is reported as [exit code: N] for the agent to interpret, not surfaced as a tool error. A description in active voice (5–10 words) labels the call in the UI; timeoutMs overrides the executor's default and cap. Output beyond the executor's stream caps is truncated to its tail, with the full output saved to a spill file whose path is reported.
Passing run_in_background: true returns a job id immediately and no timeout applies; the command keeps running while the agent works on something else. The agent reads its output with job_output (non-blocking unless wait: true), lists jobs with job_list, and stops it with job_kill; a finished job notifies the owning agent in-session. Background support needs the generic job runtime (dsh-jobs-local) and its control tools (dsh-tool-jobs) mounted.
When the mounted executor confines commands (for example dsh-bash-sandbox), a blocked file operation is reported as [sandbox: file access denied under <mode> mode] — a policy denial, not a command failure. The model may then retry the exact same command once in the same turn with sandbox_permissions (the narrowest wider mode that suffices) and a one-sentence justification; the approval prompt raised by that retry is how the user consents. Escalation is never speculative: a request with no real prior denial, or one that is not strictly wider than the current mode, fails closed without running anything, and a rejected escalation is final for that command.
A composition with no executor provider never activates the tool. Background calls without the job runtime fail with background jobs unavailable: load @deepseek-ai/dsh-jobs and @deepseek-ai/dsh-tool-jobs, and sandbox_permissions without a sandboxing executor fails with sandbox_permissions is not available in this composition (no sandboxing executor to escalate). enableRunInBackground: false removes the parameter and rejects a forced background call at execution time.
Read these pages when the package-level contract is not enough. They move from the shell family to the executor seam, the job runtime, and the decision notes behind the behavior.
DSH_* environment every call receives.job_output, job_list, and job_kill controls for background runs.bash argument schema.Every request in this plugin's registration scope contains the bash guidance below at first-party order 1000. The policy owner contributes current sandbox state through its cache-safe runtime context rather than changing this section. Scoped tool restrictions can hide the schema without removing this independently registered section.
Check the [exit code: N] marker on every bash result; investigate failures before moving on.
Small fixed input cost per request while the plugin is active, unchanged by sandbox mode or mode switches.
Prefix-stable while the registration scope and prompt text are unchanged. Plugin activation or disposal may invalidate reuse from this prompt section; sandbox mode switches do not.
The model sees the generated bash schema. run_in_background appears only when this producer enables it; sandbox_permissions and justification appear only when the mounted executor advertises sandboxing. Agent-scoped tool restrictions can remove the definition for that agent.
Fixed schema cost on every request where the tools are visible; sandbox support adds the escalation fields and its conditional description paragraph.
Prefix-stable while visibility, background support, and executor sandbox capabilities are unchanged. A restriction, config change, or executor change may invalidate reuse from the first changed tool definition.
The renderer emits the data-dependent stdout tail, then optional [stderr] and the stderr tail. With no output it emits exactly (no output). Conditional lines are exactly [output truncated; full output: <path-or-(unavailable)>], [sandbox: file access denied under <mode> mode], [timed out after <timeoutMs>ms], [killed by signal: <signal>], and [exit code: <exitCode>]; the sandbox escalation and runner-failure lines are quoted in dsh-bash-sandbox.
Zero result tokens before a call. Output is bounded per stream, while each emitted line remains in history until compaction.
Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.
Start returns exactly started background job <jobId>. This producer supplies incremental process output, optional [some output was dropped from memory; full output: <paths-or-(unavailable)>], sandbox facts, and terminal detail such as exit code: <exitCode> or signal: <signal> to the generic job runtime. dsh-tool-jobs owns the visible status line, completion notice, listing, and cancellation response.
The start acknowledgement is small and retained; collected output is data-dependent and bounded by the executor's stream buffers. Consuming reads do not repeat prior output.
Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.
Validation and policy failures are normalized as Error: <message>. This package's stable messages are invalid command: expected a non-empty string, invalid description: expected a non-empty string, invalid timeoutMs: expected a positive number, got <value>, the escalation pairing failures, run_in_background is disabled for this deployment (enableRunInBackground: false), background jobs unavailable: load @deepseek-ai/dsh-jobs and @deepseek-ai/dsh-tool-jobs, sandbox_permissions is not available in this composition (no sandboxing executor to escalate), the approval availability/rejection/cancellation variants, and tool call aborted.
Only the failing call adds these retained tokens; a rejected escalation does not add command output because the command does not run.
Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.
These limits define when the tool is a poor fit or needs special care. They are current package constraints, not a task backlog.
[exit code: N] / [killed by signal: …] shows a wrong pill on session replay and loses that line from the card body, because the parse treats it as the marker it consumes; a display-only known residual.bash tool opts out of timeout-policy budgets — it keeps the executor-owned BASH_TIMEOUT path, per the tool-call timeout-policy Agent Note.job_kill, or rely on owner/service disposal, when work no longer matters.