Terminal-native · open source · MIT
An agent in your terminal — not instead of it.
dshline is a terminal-native frontend for the DeepSeek Harness plugin ecosystem. Finished output is printed into your terminal’s own scroll history, so scrolling back, selecting text and piping to a file all still work. Only the input line and the status line ever redraw.
Install
npm install -g @deepseek-ai/dsh @dshline/dshline
dshlineA bordered input line labelled dshline on the left and the workspace name on the right, showing the placeholder “ask anything · / menu”. Beneath it a status line reads: ready, the active model, token counters at zero, the context window reading, and the keys for a newline, the output pager and quitting.
01
One session, start to finish
Every frame below is what dshline actually prints — the same banner, the same input line, the same status segments, the same overlays. Scroll to move through the session; the transcript grows the way it does when you use it.
Open
dshline starts in the terminal you are already in. The banner names the workspace and the route the active Harness profile registered — dshline ships no provider list and no model list of its own.
Terminal transcript: A terminal session opens. A bordered banner shows dshline and its version, the workspace path, and the active model route. Below it, an input line labelled with the workspace name reads "ask anything". A status line beneath that reads "ready", followed by the model name, token counters at zero, and the key hints for a newline, the output pager, and quitting.
Ask
A finished row is printed into your terminal’s own scroll history and never touched again. Only the bottom region — the reply still arriving, the input line, the status line — is redrawn in place. Scrolling, selecting and copying keep working, because nothing has replaced your terminal.
Terminal transcript: A prompt is submitted: "why does the token refresh drop the retry header?". The model’s reasoning appears first in dim italics, then a committed answer naming the file and line responsible. The status line has flipped to "working", showing elapsed time, tokens sent and received, a running cost, and a context-window reading.
Delegate
Delegation belongs to Harness: dshline observes a provider-neutral subagent lifecycle rather than running an engine of its own. What it adds is that the row says what the worker is doing and which model is powering it, and the status line counts the ones in flight.
Terminal transcript: A subagent tool call is committed to the transcript, showing the delegated description. The status line now also reports one agent in flight alongside the elapsed time and cost.
Inspect
/work is the composer’s own frame seen expanded — same anchor, same width, navigation help inside the bottom border. There is no alternate screen and no full-screen takeover: the transcript above is still your scrollback, and closing the view leaves it exactly where it was.
Terminal transcript: The /work view opens over the input line as a bordered panel titled Work. It lists subagents and background jobs: one subagent running with what it is currently reading and which model powers it, one finished, and one queued job. Navigation help inside the bottom border offers moving the selection, interrupting, and closing.
Discover
Type / and the list is whatever the active Harness profile mounted. dshline does not carry a feature list to keep in step with upstream: a profile without a service starts anyway, and its view is simply unavailable rather than a boot failure.
Terminal transcript: Typing a slash opens the command palette below the input line. It lists commands with the program’s own one-line summaries — inspecting workflows and subagents, browsing and resuming sessions, configuring providers through Harness, and browsing the running agent’s plugin composition — with a counter and the completion keys beneath.
02
Your terminal stays a terminal
Most terminal applications take the whole screen and rebuild it. Your scrollback stops being yours: the transcript lives inside the program, and scrolling back, selecting a stack trace with the mouse, or piping the run to a file are things the program has to reimplement — or simply does not do.
Finished output is written once
A committed row goes into your terminal’s scroll history and is never rewritten, moved or virtualized. That is what makes the scrollback above it real scrollback: your terminal emulator owns it, so its search, its selection and its copy behave exactly as they do for every other command.
Only a bounded region redraws
The reply still arriving, the input line, the status line and any open view are the live region, and it is always the last thing on screen. Everything above it is settled. A redraw touches a known number of rows rather than the whole display, which is why a long session does not get slower to look at.
No alternate screen, ever
dshline never switches your terminal to the alternate screen and never enables a mouse protocol. Both are deliberate: the moment it captures the mouse, your terminal’s own text selection stops working. Closing a view leaves your scrollback exactly where it was.
The renderer knows nothing about agents
The part that handles display widths, CJK and emoji, escape sanitising, key decoding and safe redraws is a separate package with no dependencies and no knowledge of Harness. It can be tested against a fake screen with no terminal, no model and no plugin context — and it is, by feeding real output through a headless terminal emulator and asserting the rows and the per-cell colour a person would actually see.
Design: the terminal invariants03
Built on DeepSeek Harness
DeepSeek Harness is an open-source agent harness from DeepSeek, built so that every part of it — the model adapter, the tool registry, the session log, the agent loop itself — is a plugin you can replace from configuration. dshline is one of those plugins. It runs in the same process as the agent loop and reads the capabilities the active profile mounted.
deepseek-ai/deepseek-harnessHarness owns
Lifecycle, state, persistence, provider selection, authority and policy. dshline reads the narrowest authoritative surface for each and reimplements none of them.
- Agents, sessions and the append-only event log
- Models and provider adapters
- Tools and their execution pipeline
- Permissions, approvals and credential storage
- Delegation: subagents, background jobs, workflows
- Session persistence, search and resume
- Token accounting and context-window folds
- Agent composition: plugins, presets, profiles
dshline owns
How every one of those becomes something you can read, drive and trust from a terminal — and the terminal correctness that has to be right for any of it to work.
- The terminal presentation surfaces the rest of the interface is built from
- Real scrollback, and a live region with a known height
- The composer: history, undo, reverse search, queue or steer
- Pickers, inspectors and overlays, all sharing one frame
- A status line that drops whole segments instead of cutting them
- Display width, CJK and emoji, escape sanitising, key decoding
- Colour by role, five palettes, and a 16-colour form for every one
- Making Harness capabilities discoverable by typing a slash
It integrates through capabilities, not through providers
dshline ships no provider list and no login protocol. Its connect view offers whatever the mounted adapters declare configurable and runs whatever authorization flows Harness has registered, over one settings document and one credential store — the same ones the official Web UI writes. A provider that arrives in Harness is reachable from the terminal without a dshline release.
One adopted generation at a time
Harness describes itself as a developer preview that will make compatibility-breaking changes, and it ships every few days. dshline tracks it aggressively and supports it narrowly: one adopted generation, pinned exactly rather than by range, with obsolete assumptions deleted rather than carried behind a compatibility layer. Continuous integration checks out that exact upstream revision from source and blocks the merge if dshline does not build against it.
Architecture: the capability model04
Five views onto a running agent
Each of these is an overlay over the input line, drawn in the same frame, closed with the same key, leaving your scrollback untouched. Every one of them reads a Harness capability rather than keeping its own copy of the answer.
/workWatch delegated work
Subagents, background jobs and workflow runs in one view. A row says what the worker is currently doing and which model is powering it, so a delegation that has quietly stalled looks different from one that is thinking.
ReadsHarness’s subagent, jobs and workflow services. dshline observes a provider-neutral lifecycle; it runs no engine of its own, and it holds no run handle — cancelling a job stays where Harness put it.
A panel titled Work lists two subagents and one job. The first subagent is running, showing the file it is currently reading, its model and its elapsed time; the second has completed. Below them, one background job is queued. The bottom border offers moving the selection, interrupting, and closing.
/sessionsGet back into a session
Browse, filter and full-text search every session Harness has kept, follow the lineage between a session and the children it spawned, rename one, and reopen it where you left it. Picker first, inspector second: you find the session, then you look at it.
ReadsHarness’s session query service, which resolves one consistent observation across live and persisted sessions. dshline does not build a second database, and it does not index anything itself.
A panel titled Sessions shows a search box and a list of recent sessions. Each row carries a title, its workspace, and when it was last active. The bottom border offers moving the selection, searching inside session contents, filters, opening the details of the selected one, reopening it, and closing.
/connectConfigure a provider
Every provider route the mounted adapters declare configurable, with what each one still needs before it will answer, and the sign-in flows Harness has registered. Request headers can be curated per route. There is no provider list to wait for: whatever Harness gained is here.
ReadsHarness’s model, settings, credentials and authorization services. dshline asks whether a secret is configured and writable; it never holds the value, and it ships no login protocol of its own.
A panel titled Connect shows a search box, then a group of provider routes and a group of sign-ins. One route is active and reports where its key comes from; another is dormant; a third is active but reports its environment variable unset. Under sign-ins, one flow is not signed in. The bottom border offers moving the selection, refreshing, configuring the selected row, and closing.
/usageSee what the session has spent
What the session has consumed, and how much of the input the provider served from its own cache. A companion view, /context, shows what is currently occupying the model’s context. The status line carries a one-glance reading of the same figures, and it drops whole segments as the terminal narrows rather than showing you half a word.
ReadsHarness’s own session projections — the constant-time folds it publishes for context pressure, composition and token usage. dshline never counts tokens and never tokenizes; a composition figure is presented as an approximation because that is what Harness says it is.
A panel titled Usage lists input tokens broken into uncached, cache-read and cache-write, then output tokens, the cache-read share as a percentage, and the accumulated cost. A performance group follows with turn and step counts, average time to first token, average output rate, and time spent in the model and in tools.
/pluginsSee what the agent is made of
Harness is built so that every part of it is a plugin — including the tool registry and the agent loop. This view browses and searches the composition the running agent is using, switches between presets, and shows which rows are on. A companion view does the same for the profiles on the machine.
ReadsHarness’s agent-preset registry, and its own home-path service for the profile roster. Every change is forwarded to Harness’s plugin command rather than written into a profile manifest by dshline.
A panel titled Plugins names the preset in use and the default preset, then shows a search box and the matching composition rows. Each row gives a plugin name and the package it comes from, with a mark showing whether it is on. The bottom border offers navigating, searching, toggling a row, switching presets, setting the default, and closing.
05
Install
Two packages: DeepSeek Harness, and this interface. Then run it from any folder you want to work in.
npm install -g @deepseek-ai/dsh @dshline/dshline # the harness, and this interface
dshline # from any folder, on any machineWhat the first run does
It asks once — and only once — whether Harness may create a profile for dshline and install this package into it, then carries on into whatever you originally typed. It will not run without a terminal to ask on, it never repairs an existing profile, and it does nothing at all if you named a profile yourself. A fresh install with no model configured opens on the setup view rather than on an input line that cannot send.
Other ways in
Install without being asked
For scripts, retries and source checkouts.
dshline --setupInstall into a profile yourself
The same thing, through Harness directly.
dsh plugin --profile dshline add @dshline/dshline
dsh --profile dshlineFrom source
The repository is a workspace of two packages, so a git-URL install is not supported.
git clone https://github.com/riesbri/dshline && cd dshline
pnpm install && pnpm build
dsh plugin --profile dshline add ./packages/dshlineCheck it worked
A banner, an input line and a ready status line means you are done.
dshline --version # the version a bug report asks for
dshline --dump-config # look for a "# == dshline" section06
Read it, run it, break it
dshline is MIT-licensed and the architecture and design documents are the same ones its contributors work from — not a summary written for a website. Contributions are especially welcome on generic capability adapters, terminal robustness, cross-platform verification and CJK correctness.