Your First Afternoon with dsh web and a Bundle Plugin
Get a local Web UI running, install one bundle from a git or npm source, verify it with dump-config, and avoid the three mistakes that waste the first hour.
This is the practical companion to the “everything is a plugin” overview. Goal: in one afternoon you can start DeepSeek Harness’s Web UI, install a single bundle plugin, prove it landed in the config tree, and restart so it actually loads. Commands below follow the public CLI shape from the Harness docs; package names in examples are illustrative—always prefer a source you have read.
If you only remember four steps, remember these: isolate the home directory, start web, install against the same profile you will run, then prove the row with --dump-config before you blame the UI.
Prerequisites and an isolated home
You need a current Node.js toolchain. Before you install anything community-shaped, give Harness its own home directory. Official safety guidance pushes isolation for a reason: plugins run with the privileges of the host process, and mixing experimental agents with your daily shell profile is how accidents happen.
export DSH_HOME="$HOME/.dsh-playground"
mkdir -p "$DSH_HOME"
Keep production API keys out of that environment. If you must authenticate a model provider, use the narrowest credential you can rotate, and assume any installed plugin could eventually see process environment that the agent runtime exposes. A playground that can read your main ~/.ssh or company .env files is not a playground.
Optional but useful: open a fresh shell, export only the variables you intend, and keep a short note of what you installed. Future-you will not remember why a random github source is in the patch file.
Start the Web UI
The shortest path from npm:
npx @deepseek-ai/dsh web
By default the UI listens on http://127.0.0.1:3080 and opens a browser for a local launch. If you start Harness over SSH, the CLI tends to print the host URL and leave port forwarding to your client or editor—pass --no-open when you do not want a browser attempt on the remote side.
npx @deepseek-ai/dsh web --no-open
From a repository checkout the flow is the longer pnpm install && pnpm run build && pnpm dsh web path. Both land you in the same mental model: a profile named web composing base services plus the browser app. Confirm the page loads before you install anything. Separating “Harness boots” from “my plugin boots” saves false debugging.
Bundle install only (repository comes later)
For this afternoon, stay on bundle installs: one distribution unit that carries config rows and code. The CLI shape looks like:
dsh plugin --profile web add "github:owner/repo"
# or an npm-style source your docs support
dsh plugin --profile web add "npm:@scope/dsh-plugin-example"
Pick a small, well-documented community package whose repository you can skim in fifteen minutes. Do not treat a marketplace listing as a trust root. Read the package.json, the Cordis entry, and anything that shells out or opens network sockets. If the README cannot explain why it needs shell access, do not install it into a home directory that matters.
Always pass the profile you intend to run. Installing into a default you are not launching is a classic “it installed, nothing changed” story.
Prove it landed, then restart
Installation that only mutates disk is incomplete until you can see the row:
dsh --profile web --dump-config | less
Search for the plugin id or package name. If the insert is missing, stop—do not keep restarting hoping the UI invents it. Check the CLI exit status, the home directory you exported, and whether the source string resolved. If the row is present but the feature is absent in the browser, restart the web process. Many first-time installs look “broken” only because the running tree was composed before the patch existed.
# stop the old web process, then:
npx @deepseek-ai/dsh web
After restart, exercise one obvious behavior the plugin claims to add. If nothing is obvious, the plugin may be runtime-only; dump-config plus the author’s docs become your acceptance test.
Common pitfalls
| Symptom | Likely cause | What to try |
|---|---|---|
| Bare name fails to resolve | Expecting a magic short id | Use a full github: / npm: source string |
| Install succeeded, UI unchanged | Forgot restart / wrong profile | Restart dsh web; re-check dump-config for web |
| Remove did not clean behavior | Patch row still present | Inspect home cordis.patch.yml; align manually |
| Works in headless, missing in web | Wrong profile | Repeat install with --profile web |
| Strange path permissions | DSH_HOME unset / mixed homes | Echo $DSH_HOME; keep one playground |
One security sentence before you go wild
A successful install is not a security review. Before you add a second and third plugin, skim for filesystem reads, shell execution, and remote code loading. The longer security note on this site covers what recent public audits imply for everyday users; the short version is: Harness is closer to “load native extensions into your agent host” than to “install a phone app from a curated store.”
Checklist to close the afternoon
DSH_HOMEpoints at a playground directory.dsh webserves on 3080 (or your chosen port).- One bundle source is installed against the
webprofile. --dump-configshows the insert.- Web was restarted after the install.
- You can name one behavior you verified.
Next up: when to prefer repository plugins over bundles, and why plugin remove is not the same thing as “the patch forgot this ever happened.”