# DeepSeek Harness
URL: https://docs.munito.ai/sandboxes/cloud-agents/deepseek-harness

For files on your computer, use the [local desktop and CLI guide](https://docs.munito.ai/agents/deepseek-harness).

## Install the CLI [#install-the-cli]

```bash
npm install -g @munitoai/cli
```

The command is `munito`. See [the command line tool](https://docs.munito.ai/cli).

## One command [#one-command]

```bash
munito agent dsh "fix the failing test"
```

It creates the sandbox, runs the task and applies the patch back. The `agent`
[template](https://docs.munito.ai/sandboxes/templates) carries DeepSeek Harness, pointed at Munito AI.

```bash
munito agent dsh --model deepseek-ai/deepseek-v4.1-flash-1017 "fix the failing test"
```

See [Regions](https://docs.munito.ai/regions) for the EU host.

## Through the API [#through-the-api]

```bash
SANDBOX=$(
  curl -sS --fail-with-body https://api.munito.ai/sandboxes/v1/sandboxes \
    -H "Authorization: Bearer $MUNITO_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"template": "agent", "agent": "dsh", "internet": true, "persistent": true,
         "env": {"MUNITO_API_KEY": "'"$MUNITO_API_KEY"'"}}' |
  jq -er '.id'
)
export SANDBOX
```

`"agent": "dsh"` writes the provider profile and puts the key where Harness reads it. Add `"model"` to select
another model. Then run a task:

```bash
curl -sS --fail-with-body "https://api.munito.ai/sandboxes/v1/sandboxes/$SANDBOX/exec" \
  -H "Authorization: Bearer $MUNITO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"command": "dsh headless \"Add a test for the empty case\"", "cwd": "/workspace", "timeout": 1800}' |
  jq -er 'if .exit_code == 0 then .stdout else error(.stderr) end'
```

- `dsh headless` runs one task and exits.
- Upload your project through the [files API](https://docs.munito.ai/sandboxes), or clone it into `/workspace`.
- For a task over 30 minutes, use a
  [background command](https://docs.munito.ai/sandboxes/commands#start-a-background-command).

## The remote Web UI [#the-remote-web-ui]

The Web UI runs in the sandbox, and your browser reaches it through an SSH tunnel. Port 3080 stays private.

Start the server. The provider is at `/root/.dsh/cordis.patch.yml`, which every surface of Harness reads, so the
Web UI needs no setup of its own:

```bash
DSH_COMMAND=$(
  curl -sS --fail-with-body "https://api.munito.ai/sandboxes/v1/sandboxes/$SANDBOX/commands" \
    -H "Authorization: Bearer $MUNITO_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"command": "dsh web --no-open --port 3080", "cwd": "/workspace", "timeout": 3600}' |
  jq -er '.id'
)
export DSH_COMMAND
```

1. Open the tunnel: `munito ssh $SANDBOX -- -N -L 3080:127.0.0.1:3080`.
2. Read the launch URL of the Web UI:

```bash
curl -sS --fail-with-body \
  "https://api.munito.ai/sandboxes/v1/sandboxes/$SANDBOX/commands/$DSH_COMMAND" \
  -H "Authorization: Bearer $MUNITO_API_KEY" | jq -r '.stdout'
```

3. Open that whole `http://127.0.0.1:3080/...` URL in your browser, including its authentication part.

The launch URL is a credential. Keep it private. If the output is still empty, Harness is starting: read the
command again. If local port 3080 is taken, tunnel `3081:127.0.0.1:3080` and change the port in the URL.

Every surface shares one Harness home, so the Web UI can reopen the session of a headless task. A
[pause](https://docs.munito.ai/sandboxes/persistence#pause-and-resume) keeps the files and ends the Web UI, so start it again
after a resume.

## The Web UI on a sandbox desktop [#the-web-ui-on-a-sandbox-desktop]

A [desktop](https://docs.munito.ai/sandboxes/desktop) sandbox has its own Firefox, so the Web UI needs no tunnel and the
launch URL never leaves the sandbox. Create it with `"template": "desktop"`, then copy the profile and start
the server as above. Open the launch URL on the desktop:

```bash
DSH_URL=$(
  curl -sS --fail-with-body \
    "https://api.munito.ai/sandboxes/v1/sandboxes/$SANDBOX/commands/$DSH_COMMAND" \
    -H "Authorization: Bearer $MUNITO_API_KEY" |
  jq -r '.stdout' | grep -o 'http://127.0.0.1:3080/[^ ]*' | head -1
)

curl -sS --fail-with-body "https://api.munito.ai/sandboxes/v1/sandboxes/$SANDBOX/exec" \
  -H "Authorization: Bearer $MUNITO_API_KEY" -H "Content-Type: application/json" \
  -d "$(jq -n --arg u "$DSH_URL" '{command: ("DISPLAY=:0 setsid firefox \"" + $u + "\" >/dev/null 2>&1 &")}')"
```

Watch and use the desktop with `munito open $SANDBOX`. A desktop needs 2 vCPUs and 4 GiB at least, and it adds
$0.10 for each hour that it runs.
