ChatGPTClaudeGrok / X / CursorGemini

dsh headless one-shot tasks: stdout, stderr and exit codes

Configuration & UsagePublished 2026-10-21Author: DeepSeek Plugin Market
DeepSeek HarnessheadlessCIexit codesstdout
dsh headless runs one task and exits: stdout is the final text, reasoning goes to stderr, and only a completed turn returns 0. No port or browser client.

dsh headless is a one-shot mode: start a fresh agent, submit the task, wait until it is fully settled, flush the session, then print the final text to stdout and reasoning to stderr. No port is opened and no browser client is mounted, which makes it a natural fit for CI and scripts. The contract is the important part: stdout is the answer, stderr is the process, and the exit code is the verdict.

DeepSeek Harness: Where it sits next to web and sdk

headless is not “web without a UI”; it is a separate one-shot execution path. Compare:(source)

ModeLifetimeListening portTypical use
dsh webLong-runningYes, 3080 by defaultHuman interaction
dsh --profile headlessOne task, then exitNoCI, scripts, batch jobs
dsh --profile sdkControlled by clientNo, stdioEmbedding in code
dsh --profile sdk-minimalControlled by clientNo, stdioMinimal SDK runtime

headless mounts no browser connection, HTTP server, Web runtime, or browser client. Port conflicts cannot break it, and it does not leave a service to stop later.

DeepSeek Harness: What happens during one run

The order is fixed: create agent → submit task → wait for settle → flush → derive the result from persisted events. In detail:(source)

  1. Create a fresh agent — the core registry creates a persistent agent. Expected: the task gets its own session, not the previous conversation.
  2. Submit the task — the positional argument is the task text. Expected: the agent starts a normal turn.
  3. Wait until fully settled — not just “the model stopped streaming”, but the agent lifecycle reaches idle. Expected: tool calls and subagents finish.
  4. Flush the session — persistence buffers are written. Expected: a later read sees a complete event range.
  5. Derive the result — take the last non-empty assistant text and the last turn/end reason. Expected: stdout gets the answer, the exit code reflects the reason.

This also explains apparent hangs: the model may be done but the agent is still waiting for a tool or subagent to settle. headless does not emit a half-finished result as final.

DeepSeek Harness: The stdout, stderr, and exit-code contract

stdout is the answer, stderr is the process, and the exit code is the verdict; do not mix them. The contract:(source)

ChannelContentRecommended use
stdoutLast non-empty assistant textRedirect to a file or pipe
stderrReasoning under dsh: reasoning:Keep as a log, not an answer
exit 0turn/end reason is completedTreat as success
exit 1Other terminal reasons or failureTreat as failure and keep stderr

Example:

sh
dsh --profile headless "run the tests and summarize failures" \
  > /tmp/dsh-answer.txt \
  2> /tmp/dsh-reasoning.log
  1. Read the exit code first — echo $?. Expected: continue only on 0; inspect stderr on 1.
  2. Read stdout second — take only the final text. Expected: no reasoning heading, tool logs, or progress bars.
  3. Read stderr last — reasoning and errors live here. Expected: distinguish “the model thought for a while” from “a tool failed”.

Do not merge streams with 2>&1 and then parse; once merged, stdout is no longer a clean answer channel.

DeepSeek Harness: Signals, exit, and resource release

On SIGINT or SIGTERM, headless disposes the mounted root before exiting rather than being killed abruptly. This matters for graceful cancellation:(source)

  1. Send SIGTERM — let the process release resources and finish in-flight tool calls. Expected: it exits and the session remains flushed up to the last checkpoint.
  2. Do not jump straight to SIGKILL — a hard kill can leave an unflushed session tail. Expected: give SIGTERM a window first.
  3. Treat signal exits as failure or incomplete — they are usually not 0. Expected: scripts do not mistake cancellation for success.

headless mounts no HTTP server or browser client, so there is no port to release; what it releases is session persistence and tool subprocesses.

DeepSeek Harness: Three CI patterns

headless fits “one input, one output, one exit code”; different jobs only change the wrapper. Three patterns:(source)

  1. Direct command — dsh --profile headless "$PROMPT". Expected: simple jobs with a shell exit-code check.
  2. Wrapper script — pin the workspace and DSH_HOME, write stdout as an artifact. Expected: jobs do not share profiles or sessions.
  3. Scheduled trigger — cron or a CI scheduler starts a new session each time. Expected: context does not grow across unrelated runs.

If a task must continue a previous conversation, headless is the wrong entry point; it creates a fresh agent each time. Use the SDK or an explicit session-reuse mode.

DeepSeek Harness: Common traps

Most headless failures are contract misreads, not a model that refuses to work. Four traps:(source)

  1. Parsing stderr as the answer — reasoning deltas live there too. Expected: read only stdout.
  2. Ignoring the exit code — text can exist while the turn is cancelled or failed. Expected: non-zero means failure.
  3. Empty task text — no positional argument is a usage error. Expected: validate the variable before invoking.
  4. Sharing one home across jobs — profiles, plugins, and sessions leak between runs. Expected: set DSH_HOME explicitly in CI.

Debug in this order: exit code, the end of stderr, then stdout. Reversing the order lets a plausible-looking answer hide a failed run.

DeepSeek Harness FAQ

Can headless open the Web UI port? No. It mounts no HTTP server and opens no listening port; use dsh web when you need an interface.

Does one headless run leave session files? Yes. It creates a persistent agent and flushes the session, so $DSH_HOME/sessions contains a record; apply your normal retention policy.

Can I use headless as a long-running headless service? Not really. It is one-shot and exits when the task finishes; a long-running service should use web or an SDK client.

The short version: headless is valuable because the contract is crisp—stdout is the answer, stderr is the process, exit code is the verdict.

ChatGPTClaudeGrok / X / CursorGemini

FAQ

What is the difference between dsh headless and dsh web?

DeepSeek Harness: dsh headless creates a fresh persistent agent, submits one task, waits until it is fully settled, flushes the session, and exits. It mounts no browser connection, HTTP server, or Web runtime and opens no listening port. dsh web is the long-running Web UI.

What goes to stdout and stderr in dsh headless?

DeepSeek Harness: stdout carries only the final assistant text. Non-empty provider reasoning deltas go to stderr under the dsh: reasoning: heading. A successful response with no reasoning leaves stderr empty.

Why does dsh headless return exit code 1 even though it printed an answer?

DeepSeek Harness: the exit code reflects the final turn/end reason, not whether text exists. Only completed returns 0; cancellation, errors, and other terminal reasons return 1 even when partial output was printed. Check the code and stdout together.

What happens if I omit the task text?

DeepSeek Harness: it is a usage error. The task text is a positional argument for headless; without it the invocation is invalid. It does not enter an interactive prompt or read a default file.

Is dsh headless suitable for CI?

DeepSeek Harness: yes. It opens no port, prints only the final answer, and expresses completion through an exit code. Each run creates a persistent agent session, so isolate workspaces and DSH_HOME across jobs.

Related Terms

headless
headless is the one-shot DeepSeek Harness profile started with dsh --profile headless <task>. It runs a fresh persistent agent, waits for it to settle, flushes the session, and exits.— DeepSeek Harness reference - dsh CLI behavior
turn/end
turn/end is the persistent session event that closes a turn with a terminal reason. headless uses the last turn/end reason to choose its process exit code.— DeepSeek Harness reference - dsh CLI behavior
flush
flush writes session logs and persistence buffers to disk. headless flushes the session before exiting so the final text comes from a persisted event range.— DeepSeek Harness reference - dsh CLI behavior
reasoning delta
A reasoning delta is a streaming chunk of model thinking, separate from the final visible text. headless writes these chunks to stderr so stdout stays a clean answer channel.— DeepSeek Harness reference - dsh CLI behavior

Sources