description: "One-shot task mode for dsh: run a single task from the command line and get the final answer printed, for users scripting or automating dsh."
English | 中文
dsh-headless runs one dsh task from the command line and prints the final answer, then exits — no GUI, no server, no browser. Type dsh --profile headless "run the tests" and the agent works through the task with the same model, tools, and safety defaults as every other surface. It is ideal for scripts, CI, and one-off jobs: the process opens no ports and leaves nothing running behind. The exit code tells you the outcome — 0 when the task completed, 1 when it aborted or errored. The main boundary: one task per invocation, with no interactive follow-up.
Run one task, get the final answer, and exit. The task is the command line itself, so the whole invocation is the smallest working example.
dsh --profile headless "run the tests"
The agent works through the task, streams each non-empty provider reasoning delta to stderr under a dsh: reasoning: heading, then prints the final answer on stdout and exits. Consecutive reasoning deltas stay in one section, and the runner closes that section before later output when the provider supplied no trailing newline. A successful run without reasoning keeps stderr empty; a failure exits 1 and prints dsh: <code>: <message> to stderr. A missing or blank task is rejected before anything runs. The task text is supplied through the single task setting:
| Field | Default | Meaning |
|---|---|---|
task |
required | The task text for the single run |
The generated configuration catalog is the exhaustive source for every accepted field and its JSDoc.
Use headless for scripted or automated dsh runs — CI steps, batch jobs, quick answers from a terminal. Avoid it when you need a multi-turn interactive session or a GUI; the browser surface (dsh-web-app) serves that. The process stays alive only for the run, opens no listening port, and exits on its own, so it fits pipelines that wait on the process.
dsh --profile headless --help prints the command's help text and exits without running anything. A missing or whitespace-only task is a usage error: nothing runs and the process exits 1.
: ` to stderr. A direct driver failure (for example, Agent creation) writes `dsh: ` to stderr and exits 1.
### Source map
| File | Role |
|---|---|
| [`src/index.ts`](src/index.ts) | The `headless-runner` plugin: run flow, output contract, exit mapping |
| [`src/startup.ts`](src/startup.ts) | The `headless-startup` provider: task positional and `--help` |
| [`cordis.patch.yml`](cordis.patch.yml) | The one-shot patch over `dsh-base` |
| — | No runtime invariant companion is published; the runner's observable contract (provider reasoning on stderr, final text on stdout, exit code by turn-end reason) is process-level and owned by the launcher e2e; it registers nothing and holds no mutable relation to audit inside the tree. |
| [`tests/headless.spec.ts`](tests/headless.spec.ts) | Run flow, aggregation, flush, and exit mapping |
| [`tests/startup.spec.ts`](tests/startup.spec.ts) | Command-line parsing over a real Loader tree |
### Invariant ownership
No invariant companion is published because the runner's observable contract (final text on stdout, exit code by turn-end reason) is process-level and owned by the launcher e2e; the plugin registers nothing and holds no mutable relation to audit inside the tree.
Read these pages when you want to go deeper into the shared core, the sibling GUI, or the command-line handoff.
None, as the runner submits the task as an ordinary user message and the composed base and headless rows own the prompts and tools.
The runner adds nothing to the request prefix; it only drives one user message through the composed tree.
These limits tell you when headless does not fit and what it needs from the dsh launcher. They are current package constraints, not a general CLI comparison or a task backlog.
dsh launcher — starting the headless profile another way fails at startup, because only the launcher can request the process exit.