They differ by exactly one bundle. web stacks dsh-web-app on dsh-base and serves a browser UI at 127.0.0.1:3080; headless stacks dsh-headless and runs one session, prints the result and exits. Use web to work interactively, headless for anything scripted, and keep them as separate profiles so their plugin sets stay independent.
The two shipped profiles look like different products and are not. They differ by exactly one bundle, and understanding that is the fastest way to stop treating "headless mode" as a lesser version of the real thing.
The actual difference
web | headless | |
|---|---|---|
| Bundles | dsh-base + dsh-web-app | dsh-base + dsh-headless |
| Interface | Browser UI at 127.0.0.1:3080 | stdout |
| Lifetime | Runs until you stop it | One session, then exits |
| Server | Yes | No |
| Invocation | dsh web | dsh --profile headless "job" |
Everything in dsh-base — model adapters, tools, persistence, sandbox and approval policy,
settings, credentials, telemetry — is present in both. You are choosing the shell around the agent,
not the agent's capabilities.
What the web profile is for
Working, and more importantly, watching.
The web profile is where the session log becomes legible. Everything the model sees is recorded in an append-only log, and resume, fork, search and replay all operate on that event stream — with a trajectory view for inspecting a session by source. Reading that while an agent works is how you build an accurate model of what it actually does, as opposed to what you assume it does.
That is not a beginner's crutch. When an orchestration goes wrong — a sub-agent that looped, a workflow stage that silently produced nothing — the trajectory is where you find out why.
What the headless profile is for
Anything you would put in a script.
dsh --profile headless "summarise why the test suite is failing"One session, result on stdout, exit. No port, nothing to clean up. And crucially: invalid commands,
options belonging to another mode, configuration errors and boot failures all exit nonzero —
which is what makes it safe to put behind an if in a pipeline.
The natural home for this is CI, a cron job, or a git hook. It is also the right choice for a one-shot question you do not want a browser tab for.
Run both
The two are not alternatives, and treating them as such costs you something real.
Plugins install into the profile's own node_modules, and patch layers are per profile. So
separate profiles give you, for free:
- Different plugin sets. Your interactive profile can carry experimental plugins; the automated one carries only what the job needs.
- Different approval policy. Approval and sandbox policy are rows from
dsh-baseand therefore patchable. An interactive agent you are watching and an unattended agent in CI should not have the same permissions, and with separate profiles they need not. - Different blast radius. An experiment that breaks your local profile leaves the pipeline alone.
Verify what each one composes
dsh --profile web --dump-config
dsh --profile headless --dump-configDiffing those two outputs is the most direct way to see what dsh-web-app and dsh-headless
actually contribute — and to confirm that a policy you tightened in one profile is not quietly stock
in the other.
Picking, in one line each
Use web when a human is in the loop, when you are learning what the agent does, or when you need the trajectory view to debug an orchestration.
Use headless when nothing is watching: CI, cron, hooks, or a scripted one-shot whose exit code you intend to check.
Frequently asked
Is headless less capable than web?
No. Both stack dsh-base, which brings model adapters, tools, persistence, sandbox and approval policy, credentials and telemetry. The difference is the shell around the agent, not the agent.
Can one profile do both?
You would be fighting the design. Profiles are cheap and isolated, and plugins install per profile — keeping them separate gives you independent plugin sets and independent approval policy for free.
Which should I start with?
web. Seeing the trajectory view while you learn what the agent does is worth more than the convenience of scripting something you do not yet understand.