This page looks best with JavaScript enabled

A Handy Helper for Development and Operations - deepseek-harness-remote-node

 ·  โ˜• 9 min read

1. Insufficient Context Is the Key Constraint on AI Agent Adoption

The quality of an Agent’s work depends both on model capability and on the environmental context it can reach.

For development and operations, the harder part is that the environment is often fragmented: logs live on production, docs in a knowledge base, code in a Git repository. If the model cannot read that information, it cannot judge the problem accurately. What we call “insufficient context” is largely not a model window that is too small, but an environment that lies outside the Agent’s reach.

This creates two challenges for us:

  • Developers need to change code and run tests locally, then push back to production for deployment testing
  • Operations needs to run commands and read logs on the machine, then hand the results to the Agent for analysis and troubleshooting

Alternating verification between human and Agent is the common AI workflow today.

2. Handing the Environment Entirely to the AI Agent

The common approaches today are to install an Agent in the environment, or to have a central Agent execute Jobs over SSH or MCP.

The first deploys an Agent on every machine, leaking model access credentials; the second gives the Agent broad access to hosts, with enormous latent risk.

Another idea is to let the Agent run remotely on the environment:

  • Only one super-brain is needed. Model calls, session state, plugins, keys, and auditing all stay centralized in one place
  • Easier to control. Target machines are onboarded through simple configuration, and the Agent is used through a unified entry point
  • Lower cost. Only a lightweight forwarding process runs on the target machine, with minimal resource usage
  • Easier onboarding. A single upstream entry point manages a large fleet of machines

Below is a solution built on deepseek-harness.

3. deepseek-harness-web

deepseek-harness-web packages the dsh web interface into a single container. One command starts an Agent, complete with web UI, model routing, and persistent storage.

Put simply, it answers where the brain lives. My choice is deepseek-harness + container + persistence.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
โ”‚  dsh-web container
โ”‚
โ”‚  entrypoint.sh  โ”€โ”€  PID 1, auto-restart loop
โ”‚    โ”œโ”€ sync-provider.sh   model routing โ†’ settings.yaml
โ”‚    โ”œโ”€ sync-workspace.sh  pull on start + flush on exit
โ”‚    โ”œโ”€ s3-sync.mjs        bidirectional sync daemon
โ”‚    โ””โ”€ dsh web            DeepSeek Harness Web UI
โ”‚
โ”‚  /root  โ‡„  ./home (bind mount)  โ‡„  S3 bucket (optional)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

For remote-node, it is the host machine and the human-facing entry point.

Configuration files are set through environment variables. API_KEY configures the model access credential; BASE_URL and MODEL write a custom model into /root/.dsh/settings.yaml. MODEL accepts a comma-separated list of model ids, the first being the default. Both the workspace and the dsh configuration live under /root (a bind mount of ./home:/root), and once S3 is configured the whole thing syncs to the bucket.

The deepseek harness startup log prints an access URL containing a token; replace it with your real domain or IP to access. If you use a domain, set TRUSTED_HOST to the Host header the browser sends (which may include a port).

4. deepseek-harness-remote-node

deepseek-harness-remote-node turns a remote machine into an execution environment for dsh. The remote machine dials out to the existing dsh web entry point, and the Agent’s file reads and writes, shell commands, terminal, and language server all happen on that machine โ€” while the Agent loop, model calls, session state, and plugins stay on the host.

Normaldeepseek-harness-remote-node
ctx.fs โ€” read, write, editdsh host disknode disk
ctx.subprocess โ€” commands, PTY, LSPdsh host processesnode processes
Agent loop, model calls, session statedsh hostdsh host (unchanged)

Without it, the Agent can only edit files on the host; with it, the Agent edits the machine you specify.

For example, ask the Agent “how much disk space is left on the work machine?” and it runs df on the remote node, not on the host.

4.1 Architecture

The host is still a single dsh process, exposing only one web entry point; a node is a connection dialed in from the target machine.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
โ”‚  dsh host
โ”‚
โ”‚  webServer  :3080
โ”‚    โ”œ /api/remote.mux   โ† browser mux
โ”‚    โ”” /node/v1          โ† node channel
โ”‚
โ”‚  ctx.nodeRegistry โ”€โ”€ remote-node
โ”‚  ctx.fs ........... remote-node/fs
โ”‚  ctx.subprocess ... remote-node/subprocess
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ฒโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
                โ”‚ wss, dialed out by the node
                โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
                โ”‚  Execution environment (Pod / VM / host)
                โ”‚  filesystem ยท processes ยท terminal ยท LSP
                โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

A node can be any form of execution environment, such as a Pod, container, VM, or bare-metal machine.

4.2 How It Works

In the dsh architecture, every environmental operation the Agent performs converges on two interfaces (seams):

InterfaceCoverage
ctx.fsread, write, edit, list, stat
ctx.subprocesscommands, terminal, language server

Higher-level capabilities (the bash tool, PTY, LSP) all compose on top of these two interfaces without naming a concrete implementation. Together, the two interfaces define an execution environment. Replacing these two providers is equivalent to replacing the entire execution environment โ€” not a single line of bash, terminal, or LSP code changes, and the layers above are completely unaware.

The full call chain: user asks a question โ†’ Agent calls the bash tool โ†’ dsh-bash-local calls ctx.subprocess (it never imports child_process) โ†’ this package’s subprocess entry forwards the call across the channel โ†’ the agent on the node executes it.

4.3 Installation

Both the host and the node need a Node 22+ environment.

When github.com is unreachable, the --proxy flag proxies both install scripts:

1
PROXY=  # e.g. https://ghproxy.chenshaowen.com
  • host

Run the script inside the dsh-web container:

1
curl -fsSL "${PROXY:+$PROXY/}https://raw.githubusercontent.com/shaowenchen/deepseek-harness-remote-node/master/scripts/install-host.sh" | sh -s -- --proxy "$PROXY"

You can also set the working directory with --cwd, which defaults to $HOME/.deepseek-harness-remote-node.

1
2
curl -fsSL "${PROXY:+$PROXY/}https://raw.githubusercontent.com/shaowenchen/deepseek-harness-remote-node/master/scripts/install-host.sh" \
  | sh -s -- --cwd /data/.deepseek-harness-remote-node --proxy "$PROXY"

The patch layer explicitly disables the local provider.

Restart dsh after installing. Inside the dsh-web container:

1
dsh-restart
  • node side

Run this on the execution environment:

1
2
curl -fsSL "${PROXY:+$PROXY/}https://raw.githubusercontent.com/shaowenchen/deepseek-harness-remote-node/master/scripts/install-node.sh" \
  | sh -s -- --bin-dir ~/.local/bin --proxy "$PROXY"

wss:// is the address dsh web exposes:

1
2
3
dsh-node --url wss://<host>/node/v1 \
  --credential <value printed by install-host.sh> \
  --cwd ~/.deepseek-harness-remote-node

The credential is randomly generated and printed by the host install script, and also stored in $DSH_HOME/node-credential. dsh-node --describe prints the machine’s identity without connecting.

Only one agent process runs per node. The node id defaults to the machine hostname, and a second agent with the same id is rejected as busy. Check for duplicate processes.

  • uninstall script
1
2
3
4
5
6
7
# host side โ€” remove the plugin symlink and configuration entries
curl -fsSL "${PROXY:+$PROXY/}https://raw.githubusercontent.com/shaowenchen/deepseek-harness-remote-node/master/scripts/uninstall.sh" \
  | sh -s -- --host

# node side โ€” remove the command and cached source
curl -fsSL "${PROXY:+$PROXY/}https://raw.githubusercontent.com/shaowenchen/deepseek-harness-remote-node/master/scripts/uninstall.sh" \
  | sh -s -- --node

4.4 Usage

Once a node is registered, there is nothing to invoke. Talk to the Agent as usual, and its tools run on the remote machine.

How much disk space is left on the node?

Create a file named test.txt in the current directory containing hello world.

Below are some environments I have connected and screenshots of them running.

K8s Pod:

Linux VM:

macOS host:

5. Comparison with Other Approaches

5.1 Installing an Agent Directly

Install Claude Code or dsh separately on each target machine, each working independently. This works functionally โ€” every machine has a complete Agent.

The main problems are:

  • Key sprawl. N machines means N copies of the model key; leak risk multiplies by N, and rotation requires touching all N machines.
  • Fragmented session history. A session history is only stored on the machine that produced it, so cross-machine search means checking machine by machine.
  • Version drift. N machines upgrade independently, behavior diverges, and before troubleshooting you first have to confirm the target machine’s version.
  • Configuration and permissions each go their own way. Unifying them requires introducing an extra layer of configuration management.

If you distribute Agents through a Job platform, the end-to-end path gets even longer, requiring a separate install, start, and reclaim step.

5.2 SSH to the Host

The most intuitive approach is to reuse the existing SSH channel: if a human can SSH to the target machine, so can the Agent. For command-line tools SSH is enough, but for a coding Agent that needs to read code, change code, and run tests, SSH solves only half the problem:

ProblemExplanation
Key securityThe host must hold private keys to N target machines; if the host falls, lateral reach follows
ConnectivityTarget machines must be reachable from the host; the reverse case needs a jump host or tunnel
File read and writeEither stitch commands together with cat / sed, or build a separate file-transfer channel
Terminal and LSPSSH gives you a shell, but PTY semantics and the language server lifecycle are yours to build

5.3 Web IDE

Run a Web IDE on the target machine and let people write code and operate from a browser. This path looks lightweight โ€” the IDE ships with a file tree, terminal, and language services โ€” but the cost of adapting it is high and the resources it needs are many.

It is not just that a large development and operations staff is needed to support the platform; a complete IDE runtime must be maintained on every target machine: file service, terminal gateway, language server process management, user isolation, session persistence โ€” each requiring substantial manpower.

More importantly, a Web IDE solves “how a human accesses a remote environment,” not “how an Agent executes in a remote environment.” It moves the burden of keys, sessions, and permissions to every target machine unchanged โ€” not one of the problems listed above (key sprawl, version drift, scattered configuration) is reduced, and a layer of platform operations is added on top.

Even if you integrate an Agent into the Web IDE, all you get is a set of isolated workspaces. Each environment maintains its own context, shared knowledge cannot accumulate in one place, and cross-machine collaboration still requires a human to carry things over.

6. Summary

Back to the question at the start: if the Agent cannot reach the target environment, the loop of alternating verification between human and Agent does not hold. The approach this article offers is to let the environment connect to the Agent, rather than moving the Agent to the environment.

Concretely:

  • deepseek-harness-web puts the dsh web workspace into a single container, self-hosted with one command, with model calls, session state, and keys all consolidated in one place.
  • deepseek-harness-remote-node lets a remote machine dial out to dsh, taking over the two seams ctx.fs and ctx.subprocess, so that the Agent’s file access, command execution, terminal, and LSP all land on the remote machine.

7. References


ๅพฎไฟกๅ…ฌไผ—ๅท
WRITTEN BY
ๅพฎไฟกๅ…ฌไผ—ๅท