Running DeepSeek Harness in a Team
How to run DeepSeek Harness across a team: permission presets, sandbox backends, telemetry env vars, shared config layers, and a plugin approval policy.
DeepSeek Harness (dsh) doesn't ship a multi-tenant server mode or an admin console — running it across a team means running individual local (or per-user cloud) instances, each configured toward a shared policy rather than a single shared deployment. This guide covers the specific settings worth standardizing on: network exposure, sandbox and permission defaults, telemetry, config layering, and plugin approval.
Don't try to make it a shared server
The Web UI explicitly refuses --host 0.0.0.0. The dsh documentation is blunt about why: it's "intentionally not supported yet for safety" — a Web UI reachable from the network is remote code execution exposed to anyone who can reach it. Community attempts to work around this with port forwarding or socat still hit downstream issues with workspace loading and file selection, so there's no clean bypass, only workarounds with rough edges.
The practical implication: dsh is a per-person local tool, not something you stand up once and point a team at. Each team member runs their own instance against 127.0.0.1. If you need genuinely centralized, multi-user infrastructure, the closer fit is dsh's headless mode or its SDKs (TypeScript and Python) driven from your own service layer, rather than trying to multiplex the Web UI.
Standardize config with a machine-level patch layer
dsh layers configuration in a fixed order, and the layer most relevant to teams is $DSH_HOME/cordis.patch.yml — a patch file that applies to every profile on that machine, and sits above each profile's own cordis.patch.yml in priority:
- Each bundle's own patch, in the order listed in the profile's
dsh.profile.bundles - The profile's own
cordis.patch.yml $DSH_HOME/cordis.patch.yml— machine-level, shared across all profiles- Any
--patch <path>flags passed on the command line
A team can ship a standard cordis.patch.yml for engineers to drop into $DSH_HOME on their own machines — baking in a consistent MCP server list, a disabled dangerous permission preset, or organization-wide defaults — without touching each profile's individual config. Because a patch replaces the entire config block for a matched id rather than deep-merging, document exactly what your standard layer overrides so engineers aren't surprised when their own profile-level customization gets replaced rather than merged.
Set permission defaults deliberately
dsh's permission model combines a sandbox mode with an approval policy into a named preset. Two presets exist by default:
| Preset | Sandbox mode | Approval policy |
|---|---|---|
workspace-write (default for new sessions) | Writes confined to the session workspace and platform temp dirs; network and process visibility unrestricted | ask |
danger-full-access | No sandboxing at all | never (nothing prompts) |
For a team, the operative decision is whether danger-full-access should be reachable at all in your standard config, or restricted to specific, deliberate use cases (a disposable CI container, for instance). You can define additional custom presets beyond these two defaults (the name custom itself is reserved, so pick something else), which is the mechanism for encoding an org-specific middle ground — for example, a preset that keeps ask approval but widens what's writable. Our permissions and sandbox guide covers how the sandbox backends underneath these presets differ by platform.
Match sandbox expectations to your platform mix
The sandbox mode a preset selects is enforced differently depending on OS:
- Linux: bwrap or Landlock
- macOS: Seatbelt
- Windows: a restricted-token ACL approach
- E2B: a cloud sandbox backend, as an alternative to enforcing isolation on the local machine at all
Older Landlock kernel ABI versions and the Windows ACL backend can only achieve "partial" enforcement strength rather than "full" — the docs explicitly call out that consumers of the sandbox subsystem need to distinguish between these two levels. On a team with a mixed Linux/macOS/Windows fleet, this means the same permission preset name doesn't guarantee identical real-world enforcement across every machine. If that gap matters for your threat model, the E2B cloud sandbox backend is worth evaluating as a way to get consistent enforcement independent of each engineer's local OS.
Turn on telemetry deliberately, or turn it off explicitly
By default, dsh doesn't report session data anywhere. Three environment variables control this:
DSH_TELEMETRY_MODE=FULL # or FEEDBACK_ONLY
DSH_TELEMETRY_OTLP_URL=https://your-collector.example/v1/traces
DSH_TELEMETRY_DISABLED=1 # hard override, takes priority over the above
FULL reports every session event as OTLP/HTTP logs to your collector; FEEDBACK_ONLY reports a session log only when a user explicitly submits feedback. DSH_TELEMETRY_DISABLED overrides both and can't be re-enabled by the other two variables — set it explicitly if your team has data-handling requirements that rule out any transmission, rather than relying on the unset default.
Publishing internal plugins privately
Because dsh plugin add is a thin wrapper over pnpm add, standard pnpm/npm registry configuration applies — a team can point installs at a private registry (via a scoped .npmrc) to distribute internal plugins the same way they'd distribute any other internal package, without those plugins ever touching the public npm registry or needing a public GitHub repository. This keeps proprietary tooling, prompts, or business logic packaged as a plugin out of the public dsh-plugin GitHub topic and any awesome-list indexing entirely.
Set a plugin approval policy
Because installing a plugin runs its code on the installing machine — at build time via allowBuilds if it's GitHub-sourced, and every time apply() runs afterward — a team benefits from a lightweight, explicit policy rather than "install whatever looks useful." A reasonable baseline, building on our plugin security checklist:
- Maintain an internal allowlist of reviewed plugins (which can live in your shared private registry above), rather than relying on individual engineers each re-evaluating the same public GitHub plugin independently.
- Require a commit pin (
github:owner/repo#<sha>) for any plugin installed from a source outside that allowlist, so a later upstream push can't silently change what's running. - Default new/experimental plugin trials to a throwaway profile under
workspace-write, not the profile someone does daily work in. - Treat
allowBuilds: trueon an unreviewed package as something that requires the same sign-off as any other "run this code on a company machine" request — not a prompt to click through.
FAQ
Can multiple people share one dsh instance?
Not in any officially supported way — the Web UI is explicitly local-only (127.0.0.1), and there's no multi-tenant or multi-user mode. Each person runs their own local instance, or a per-user instance in your own cloud environment.
What's the safest way to give remote access to dsh's Web UI without violating the 0.0.0.0 restriction?
Keep dsh bound to 127.0.0.1 and put your own authenticated layer (a VPN, an SSH tunnel, or a reverse proxy with its own access control) in front of it, rather than trying to work around the restriction directly — community attempts to do so via port forwarding still ran into workspace and file-picker errors.
Where should org-wide config live so every engineer gets it automatically?
$DSH_HOME/cordis.patch.yml is the highest-priority layer that still applies across every profile on a given machine. It has to be present on each engineer's machine individually — there's no mechanism to push it from a central server.
Does dsh support SSO or centralized user management?
Not that's documented as part of the core project — dsh's model is per-machine, per-profile configuration rather than centralized account management. Model provider credentials are configured per machine via $DSH_HOME/.credentials.yaml or environment variables.
Should we default everyone to danger-full-access to reduce approval friction?
That trades safety for convenience in a way that's hard to reverse after the fact — danger-full-access removes sandboxing and approval prompts entirely, including for actions a plugin's own code might take. Consider a custom permission preset that keeps ask approval but widens what's writable, rather than jumping straight to no sandboxing at all.
Next steps
Read the plugin security checklist before defining your team's plugin approval policy in detail. For a deeper look at the sandbox backends and permission presets referenced here, see permissions and sandbox in DeepSeek Harness. If plugins are being installed from GitHub rather than a private registry, installing plugins from GitHub covers the allowBuilds decision your policy needs to account for.