GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing computingforgeeks.com — Install DeepSeek Harness (dsh) on Ubuntu & Linux | ComputingForGeeks The thing DeepSeek open sourced on 13 August is not a model. DeepSeek Harness, or That distinction is where most people lose the first five minutes. Installing DeepSeek Harness gets you a harness you can rewire: point it at DeepSeek, at Anthropic or at your own Ollama box, and keep every session on your own disk. This guide covers what dsh is, how a task moves through it, the Node 24 floor, and a first agent run that edits a real file. We first ran it on Ubuntu 26.04 in August 2026, then on 12 November 2026 reinstalled dsh 0.2.2-rc.1 on fresh Ubuntu 26.04 and 24.04 VMs, on archive Node 18 and 22 and on NodeSource Node 24, because this release raised the Node requirement. What DeepSeek Harness actually isDeepSeek Harness is an MIT-licensed agent harness: the code between a language model and your filesystem. It ships the pieces a coding agent needs and leaves each one swappable, because the whole thing is built on the Cordis plugin framework and the organising rule is that everything is a plugin. The model route is a plugin row. The bash tool is a plugin row. The permission policy that decides whether that bash tool may write to The repository went public on 13 August 2026 alongside the V4-Pro launch and passed 167,000 stars inside a week, which is the fastest ramp of anything we have covered here. It is still labelled a developer preview, and the project says so in capital letters: expect compatibility-breaking changes between release candidates. Pin the version you tested. ![]() What you get in the box, on top of that plugin tree: a Web UI, a one-shot headless mode, a Python SDK that bundles its own Node runtime, an MCP bridge, an Agent Client Protocol server, an LSP tool, a PTY terminal, subagents, workflows, plan and goal state, context compaction, and a hooks bridge that maps the supported subset of an existing Claude Code How a task moves through dshNothing the model asks for runs directly. Every turn follows the same path, and knowing that path is what makes the permission modes and the session log make sense later. ![]() Your prompt goes to the runtime, the runtime assembles the system prompt plus the tool list plus the session so far and sends one request to whichever model route you configured. The model replies with a tool call, not with an action. The runtime is what turns that request into a real process, wraps the argv in a sandbox, runs it, and hands back stdout, stderr and the exit code. Every one of those steps is appended to the session log before the answer reaches your screen. The run stats are visible at the bottom of the UI, and they are worth reading once. Fixing a one-line bug in a 15-line Python file cost this much:
32,600 input tokens for a task that needed 572 output tokens. That is the standing cost of the system prompt, the tool schemas and the runtime context injection, and it is the same shape of overhead we measured when digging into context engineering for AI agents. Prompt caching absorbed 75% of it here, which is why the turn still finished in seven and a half seconds. The session itself lands under
The file is
Resume, fork, search and replay all read that same stream, so there is no second database to keep in sync. What dsh needs before you install itOne hard requirement and one soft one. The hard requirement is Node 24.9.0 or newer. The published 0.2.2-rc.1 package declares it in its own manifest, so you can read the floor straight from the registry before installing anything:
The answer is a single range, and Node 22 is outside it:
That is a change from earlier builds. The August ones documented
Until this release candidate, 26.04 was the one Ubuntu where the archive Node just worked. That is over: both releases now need Node 24 from NodeSource, and the archive npm WARN EBADENGINE Unsupported engineThis is what the archive Node 22 on Ubuntu 26.04 gives you, and it is easy to scroll past. npm treats
A script or Ansible task that checks only the exit code reports success. In our run, ![]() The exit status of 0 at the bottom is the trap. Nothing in the pipeline stops, so the warning has to be read by a person. SyntaxError: The requested module ‘node:util’ does not provide an export named ‘parseEnv’This is what Node 18 produces, and it is worth recognising because the message never mentions Node versions. On the Ubuntu 24.04 archive Node 18.19.1, npm printed EBADENGINE for dsh and for several of its dependencies, added 651 packages and still exited 0. The first
Install Node.js and the dsh packageThe same steps work on Ubuntu 26.04 and 24.04, and they replace the
Run it with
The last lines confirm the repository and tell you what to install next:
Install Node.js from that repository:
Confirm the runtime clears the floor before going any further:
Anything from v24.9.0 up is fine. Both VMs got Node v24.22.3 with npm 11.19.1, and on 26.04
Now the harness itself. A global install puts
It is a big dependency tree, and it keeps growing between release candidates. On a 4 vCPU VM with Node 24 the install pulled 654 packages in 42 seconds, with no EBADENGINE block this time:
The npm 11.19.1 that NodeSource ships adds one new message here: Check what you actually got, because release candidates land every few days and an unpinned install takes whatever
On both November runs it reported this:
The dist-tags show where each channel points. On 12 November
The output names all three channels:
Pin it with If you would rather not install anything, Whichever route you take, the subcommand is not optional. The launcher exits with ![]() That is the whole install. The binary is on PATH and the server answers on loopback, which is everything the next step needs. On Node 24 we rechecked the install and the Web UI start on both releases. The first task, its run stats and the sandbox refusal below come from the August run of a 0.1.x build on Node 22. The session log header and launcher path come from an 11 November install of 0.2.2-rc.1 on Node 22.22.1, which is below that release’s floor. If you plan to point dsh at a local Ollama model instead of the DeepSeek API, the DeepSeek Harness local model guide picks up from here and covers the Start the Web UI and give it a modelStart the server from the directory you intend to work in, because the invoking directory becomes the default workspace root:
It prints one line and stays in the foreground:
The token in that URL is the login, so open the full link: a plain request to the port without it gets a 401. Drop
Loopback only, which is the correct default for a process holding an API key and holding write access to your source tree. On Node 24 the process shows up as
Running it on a lab box? Forward the port. Moving the bind is not really an option anyway, because the web app rejects
First load throws up a notice that the project is in testing for harness developers. Read it and click Continue; it does not come back. ![]() Now the model. Open Settings then Models, paste a key from platform.deepseek.com into the DeepSeek card and save. The route becomes usable on the next request with no restart. Keys are write-only in the UI: the page gets a redacted descriptor back, never the secret, and the value lands in ![]() For a headless box or a CI runner there is no page to click, so hand the key in through the launching environment. That layer sits at the top of the credential order and is visibly read-only, so it beats anything stored on disk, which is exactly what a per-run override should do:
Get the direction right, because it is counter-intuitive. A key in Add provider covers Anthropic, OpenAI, Bedrock, Vertex, Azure and Codex from the shipped catalog. Add a custom provider is the one that matters for a self-hosted setup: give it a lowercase provider ID, a base URL such as Pick a workspace and run the first taskThe composer stays locked until a workspace is selected, which trips people up on a fresh install. Click Choose workspace, add the directory you started dsh in, select it, and the input box comes alive. The test project was deliberately broken. A port parser with the classic Python range mistake, on line 9 of a 15-line file:
The task was to fix the off-by-one so that a range like 80-83 includes 83, then run the script to prove it. Four steps later the agent had read the file, patched line 9, executed the script and reported back with the output inline. ![]() Each tool row expands in place, so the Bash row shows the working directory, the command and its output without leaving the conversation. The file on disk changed the way you would want a colleague to change it:
Running it by hand afterwards confirms the same result the agent claimed, which is the only verification that counts:
83 is now in the list:
Total elapsed from prompt to patched file was seven and a half seconds, and the diff is four characters. Read the trajectory when the agent does something oddThe Chat tab is the polite view. The Trajectory tab next to it is the one to reach for when a run goes sideways, and it is the part of the web UI worth learning before you need it. It lays the turn out as a timeline with input, model and tool lanes across the top, then every message in order: the system prompt, your prompt, the runtime context injection, each assistant turn, and each tool call with its raw JSON arguments and the raw result. ![]() Seeing the exact The four built-in agent presetsA preset is the plugin composition a session runs: its tools, its prompt, its capabilities. Four ship with the package and you switch between them per session, or duplicate one and edit it.
![]() PTC mode is the interesting one for anyone watching token budgets. Collapsing a multi-step operation into a single generated TypeScript program cuts the round trips, which is the same lever behind the tooling in our guide on reducing agent token usage. Minimal mode carries a sharp edge that is easy to miss. Its persistent bash goes through the sandbox policy, but its Run one task without the browserThe headless profile answers a single question in a fresh persisted session, prints the final answer and exits. No UI, no daemon:
Standard output is the answer and nothing else, which makes it pipe-friendly:
The session still lands in What the sandbox actually blocksThree permission presets ship, and each one binds a sandbox mode to an approval policy. The default for a new session is the middle one.
Note what the third row really says. Turning the sandbox off also turns the approval prompts off, so there is no second line of defence behind it. Set the mode per session in the composer, or per process with an environment variable:
Enforcement is real rather than advisory. On Linux dsh reaches for
The package was renamed since launch. On 0.2.2-rc.1 the launcher sits in
The same November VM also shows the v4 session log next to that launcher: ![]() If a script of yours still points at the old addon path, the binary is gone from there and the script fails before the sandbox ever starts. Asking a workspace-write session to write outside its workspace produces a kernel-level refusal, not a polite decline from the model:
The agent gets one sanctioned escalation attempt, and it has to name the narrowest mode that would work plus a justification, which then goes to you as a prompt. In headless mode there is nobody to prompt, so it fails closed with “no approval channel is available” and the file is never created. That is the behaviour you want in CI. ![]() If neither backend is usable the harness raises Where dsh is rough right nowWorth knowing before you wire it into anything that matters. The version story is the first snag: release candidates have shipped every few days since launch, the The runtime floor moved the same way, from Node 22 to 24.9.0 between candidates, and npm only warns about it. Before every upgrade, read the engines field of the version you are about to install rather than trusting the box that ran the last one. Two smaller things are worth knowing up front. A bare None of that is unusual for a preview that is a week old. The pieces that matter are already solid: the sandbox refuses correctly, the session log is honest, and swapping the model route is a config change rather than a fork. Next in this series we put dsh side by side with Claude Code on the seams that actually differ, then wire it to a local model so no prompt leaves the box, which pairs naturally with running DeepSeek V4 Flash locally and with the tool-plumbing tradeoffs covered in MCP vs RAG vs agent skills.
Josphat Mutai
Founder of Computingforgeeks. Senior Systems Engineer with over a decade of hands-on experience building and managing production infrastructure. Core expertise in Linux/UNIX administration, cloud platforms (AWS, GCP, Azure), and Kubernetes ecosystems (EKS, GKE, OpenShift). Deep experience with virtualization (KVM, Proxmox, OpenStack), infrastructure as code (Terraform, Terragrunt, Ansible, Crossplane), GitOps workflows (ArgoCD, FluxCD), Nix/NixOS, and container orchestration at scale. Currently focused on integrating AI and LLMs into DevOps and platform engineering workflows. Every guide on this site is tested on real systems before publishing. Keep reading
AI
Ollama Models Cheat Sheet: Best Models by VRAM, Tested (PDF)
AI
Open Source LLM Comparison Table (2026)
AI
Claude Code Cheat Sheet: Commands, Shortcuts and Flags (PDF)
AI
DeepSeek Harness Cheat Sheet: dsh Commands, Config, Errors (PDF)
AI
DeepSeek Harness With Ollama: Local Model Setup, vLLM, llama.cpp
AI
Gemini CLI Cheat Sheet: Commands, Slash Commands and Flags (PDF)
Leave a Comment Cancel reply
| ||||||||||||||||||||||||||||||||||||||||||||||
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |