@codebam/dsh-tool-nu
v0.1.0
Published
Model-facing Nushell (nu) tool for the DeepSeek Harness: structured pipelines over the existing ctx.shell sandbox world, alongside bash.
Maintainers
Readme
@codebam/dsh-tool-nu
A model-facing nu (Nushell) tool for the
DeepSeek Harness.
Each call runs nu --no-config-file --no-history -c <source> in a fresh process
and returns stdout/stderr with the same [exit code: N], [stderr],
truncation, timeout, and sandbox markers as the stock bash tool. The plugin is
a consumer of the existing ctx.shell seam, not a new shell provider: the
stock bash tool, its executor, and its sandbox world stay mounted and
untouched, and nu simply joins the tool catalog beside bash.
Why a trampoline
dsh composes exactly one provider of ctx.shell; a second registration fails
loud. A nu executor package mirroring dsh-bash-sandbox would therefore
replace bash, not accompany it. This plugin instead:
- sends the Nu source as the ordinary
NU_TOOL_SOURCEenvironment entry on an existing shell request, and - runs
<executable> --no-config-file --no-history -c "$NU_TOOL_SOURCE".
Bash expands the quoted variable and does not re-scan the result, so quotes,
backticks, $(…), and newlines in the source stay data. The request travels
through the mounted executor, so sandbox policy, approval/escalation, timeouts,
output caps, spill files, and ctx.jobs background handles are inherited from
the world dsh already uses — including the @codebam/dsh-opensandbox profile
world.
Install
Add a row to the profile patch (~/.dsh/profiles/<profile>/cordis.patch.yml):
- insert:
- id: tool-nu
name: '@codebam/dsh-tool-nu' # or an absolute path to index.mjs
config:
executable: nu # prefer an absolute path in deployment
enableRunInBackground: trueNode resolves this plugin's @deepseek-ai/* peers from the profile's
node_modules. dsh populates $DSH_HOME/profiles/node_modules for its own
install closure; when loading by file path instead, provide that resolution next
to index.mjs (the NixOS route below symlinks it). No bash-sandbox,
tool-bash, or terminal row needs disabling.
Configuration
| Field | Default | Meaning |
|---|---|---|
| executable | nu | Nu executable. Deployments should pin an absolute path such as ${pkgs.nushell}/bin/nu so it resolves inside the execution world. |
| enableRunInBackground | true | Expose run_in_background; when false, the field is removed and forced background calls are rejected. |
Tool arguments
The schema mirrors the bash tool call-for-call, so model habits and presenter cards transfer:
| Argument | Required | Meaning |
|---|---|---|
| command | yes | The Nu source to execute (Nushell pipeline syntax, not bash). |
| description | yes | Active-voice UI label, 5–10 words. |
| timeoutMs | no | Overrides the executor default; the executor caps it and kills on expiry. |
| workdir | no | Per-call working directory; relative paths resolve against the session workspace. |
| run_in_background | no | When enabled: return a nu-… job id immediately; collect with job_output, stop with job_kill. |
| sandbox_permissions + justification | no | Advertised only when the mounted executor confines; identical one-shot, approval-backed escalation path as the bash tool. |
Model-facing behavior
- The system-prompt section says: check
[exit code: N]on every nu result. - The description teaches Nu's structured-data workflow: end data pipelines
with
| to nuonor| to json -r, and prefix externals with^. - Non-zero exits are results, not tool errors; only infrastructure failures
(spawn errors, aborts) are errors.
result.abortedthrowsAbortError. - Background jobs are registered with kind
nu; their outcome/detail and incremental output go through the genericctx.jobsruntime andjob_output. - Managed harness facts are available to Nu as
$env.DSH_*.
Deployment (NixOS profile)
This repository carries a staged module for the NixOS profile that pins this
plugin and copies it into $DSH_HOME:
packaging/nixos/dsh-tool-nu.nix— thefetchFromGitHubderivation (replacelib.fakeHashwith the hash Nix reports on the first build).packaging/nixos/default.nix.snippet— thepkgs/default.nixcallPackage line.packaging/nixos/agents.nix.snippet— thehome/agents.nixcopy block and profile-patch row, modeled on the existingdshOpenSandboxblock.packaging/README.md— placement and build steps.
Development
npm run peers # link node_modules/@deepseek-ai to the installed dsh closure
npm test # node --test (mock-ctx + renderer suites)
npm run test:local # peers + test in one shot
npm run check # syntax-check every ESM source
npm run pack:check # npm pack --dry-runnpm test uses the real @deepseek-ai/* packages from the installed dsh
closure (not mocks of dsh), so it runs the same defineTool schema validation,
approveEscalation logic, and shell renderer contract dsh will use at runtime.
Verified
Against dsh 0.1.6-alpha.1 and Nushell 0.115.1:
- loaded into a real
acpcomposition through the profile patch and a probe tool;applycompleted withtools,shell,systemPrompt, andshellEnvinjected; 40 + 2 | to nuonreturned42through the realbash-sandboxexecutor (exitCode: 0, sandboxworkspace-write/full, no denial);- background
sleep 300ms; 7 | to nuonregistered asnu-1, completed withexit code: 0, and read back7; - source containing shell command substitution and backticks executed as literal Nu data, and did not touch the files those substitutions named.
Known limitations
- Windows: the
pwshexecutor does not expand$NU_TOOL_SOURCEthe way bash does. Disable the row on win32 (disabled: !!js process.platform === 'win32', as the snippets do) until a PowerShell-flavored invocation exists. - Source travels in the environment: model commands are small, but
multi-megabyte scripts can exceed the OS per-entry limit. A later iteration
can stage the script through
ctx.fsornu … /dev/stdin. - Structured output is a convention: the tool does not auto-append
| to nuon, because a trailing comment or multi-statement script would break. The description instructs the model instead. - Fresh process per call: cwd, variables, functions, and history never
persist; pass
workdirinstead ofcd. - Executor-owned output semantics: truncation tail, spill paths, timeout caps, and background lifetime match the mounted executor (shared with bash).
- Replay exit pills parse from result text exactly like the bash tool, with the same known residual for output whose final line is itself a marker.
License
MIT. Portions are adapted from @deepseek-ai/dsh-tool-bash
(Copyright (c) 2026 DeepSeek, MIT); see LICENSE.
