Repository navigation
Releases
0.7.1
0.7.1 — 2026-11-02
Three refinements from a live session screenshot, all about respecting the
screen the reader actually has.
The command a tool ran is no longer cut twice
A tool card's summary truncated its command to a fixed 60 columns and then
fitted it to the card, so a 100-column window still showed at most 60. The card
now asks for exactly the room it has, and the width rides through the argument
recursion (where a first fix silently dropped it).
Consecutive tool cards pack together
A run of tool calls is one operation being scanned, not a list of separate
ones: no blank row between consecutive cards, the way a shell transcript packs
its commands. Every other kind boundary keeps its air.
The composer is multi-line, the way Claude Code's is
The box edits a buffer with explicit newlines, soft-wrapped at the window edge:
- Enter submits;
\+Enter breaks the line (Alt+Enter and Shift+Enter too),
and a paste keeps its breaks. - The block grows with the content up to 40% of the pane, then scrolls
inside itself with↑n/↓nmarkers — a long draft never shoves the
transcript off the screen. - Up/Down walk the display rows while the buffer spans more than one —
wrapped or broken alike — and fall through to the history while it does not,
so the common case is unchanged. - The readline keys went line-wise (Home/End, Ctrl+A/E, Ctrl+U/K, Ctrl+W):
on a single line every one coincides with the old whole-buffer behaviour, so
nothing anyone already types changed; on a broken line they act on the line
the caret is on, and Ctrl+W no longer eats the break. - The hardware cursor follows the caret onto its display row, and a click
places the caret by row and column.
Verified at L0 (829 tests, 34 new), L1 (the 18-scenario pty sweep, zero
defects), and a live terminal session that typed a two-line draft through
\+Enter, watched the block grow, and submitted both lines.
0.7.0
0.7.0 — 2026-11-02
Three strands asked for together — adapt to the installed dsh, bring the
text output closer to the web profile, and support the superagent ecosystem —
plus two fixes that only a real shell could surface.
Adapted to dsh 0.2.1-rc.5 — and to every 0.2.x at once
- The pins move to
0.2.1-rc.5with zero code change; the API surface the
desktop touches did not move between rc.2 and rc.5. Verified on the full
ladder: L0 (795 tests), L2 (mount), L3 (all 23 wire checks). - One build passes the plugin gate on every 0.2.x runtime. A stale shell
on this machine resolves dsh 0.2.1-rc.2 while a fresh one resolves rc.5, and
the rc.5 pins made the older runtime's gate refuse the plugin outright. The
gate readsengines.dshfirst and, when that field exists, decides alone —
soengines.dsh: ">=0.2.1-rc.2 <0.3.0"passes both runtimes without the
exact-version exemption this profile once needed. engines.noderelaxes to>=22.18. The^22.19floor was inherited
from the upstream TUI lineage, not required by us; the demo and the full
suite run on 22.18.
Markdown parity with the web transcript
The web renders assistant prose as full GFM; a construct-by-construct survey
against tvision's renderer found the real gaps. Fixed — each pinned by a test
named for what the web does with the same source:
- Setext headings.
Sub+---rendered as prose followed by a stray
horizontal rule; it is an h2 now, as GFM and the web read it. - Images render as a named
[img: alt]placeholder instead of the
source's literal bang and destination — the terminal's honest stand-in for a
picture. - Link titles are dropped; labels parse their own markdown
([**bold**](url)bolds) while the shown URL is never re-parsed as
emphasis. - Reference links (full and shortcut) resolve against definitions
collected document-wide; unresolved ones stay literal and self-heal — the
same streaming deviation the web's incremental renderer documents. - Autolinks drop their angle brackets; hard breaks (two spaces or a
backslash above the break) break. - Deliberate deviations, both recorded in DESIGN.md §5½: footnotes and raw
HTML stay literal. - CJK strong before punctuation already worked — our scanner is deliberately
looser than CommonMark, which is the same problem the web ships a micromark
extension for.
dsh-superagent support
dsh-session-superagent is a
tools-only plugin that wakes a live session with a user-role followup, so no
new seam was needed — but the round trip is now pinned:
tests/golden/superagent.jsonl records the documented wake shape (the
【主理鱼】 marker, watch_start registration, the idle gap, the wake turn,
watch_ack settling the item) and the replay asserts each stage renders.
README (EN+zh) explains how to run one against tvision.
Fixed — found by running verify:all in a real shell
- The goodbye printed twice on quit.
requestExitcalls the mount
disposer directly, and disposing the root fiber then runs the same disposer
again; the host's dispose had no guard, so the resume hint was written on
each pass. - verify:wire was silent for five minutes and looked stuck; it now prints
boot 1 of 2/boot 2 of 2up front with the expected silence, and the
byte counts before the checks. - The verification ladder stopped minting sessions in the real
~/.dsh.
Every boot creates a session in the home it uses; the rungs now default to a
repo-local sandbox home, built on demand with the profile linked to the
checkout — the same shapedsh plugin addof a local path produces.
--real-homeboots the real home deliberately. - pty-wire passed
--dsh-homeas a launcher flag, whichdshhands to
the app, whose commander rejected it and exited before drawing — the rung
reported every check missing when nothing was wrong with the app.
0.6.0
0.6.0 — 2026-10-17
Adapted to DeepSeek Harness 0.2.1. The API surface the desktop touches
survived intact — the jobs seam, the four-argument execute, every
waterfall, and the session-event map (which only gained the log-only
job/registered/job/settled pair) — so this adaptation is mostly the peer
gate plus two pieces of ecosystem cleanup.
The dsh 0.2.1 adaptation
- The peer gate. Every
@deepseek-ai/*pin moves to0.2.1-rc.2, so the
plugin loads on its own compatibility again (the 0.2.0 pins were denied by
the runtime's exact-version check). - The persona, actually applied. dsh 0.2.0 renamed the system-prompt row's
personakey topersonaPrefix; the old key composed into the config tree
but was silently dropped by the schema, so the desktop's custom persona has
been absent from every prompt since the 0.2.0 adaptation. The patch now uses
personaPrefix—{{model}}still resolves (the agent loop provides it),
and an unknown variable would fail the turn loudly, which the wire rung
covers. - The invariants companion is gone. dsh 0.2.1 removed the cross-package
invariants mechanism entirely (thedsh-invariantspackage and every
sibling'sinvariant.*): the dependency, thesrc/invariant.tsplaceholder,
and its bundle entry are removed.
0.5.0
0.5.0 — 2026-10-06
Adapted to DeepSeek Harness 0.2.0. The break surface was small and is
now verified: the session-event map, the Messages wire, and the four-argument
execute are byte-identical between 0.1.7 and 0.2.0, so the fold, the golden
fixtures, and the mock endpoint are untouched.
The dsh 0.2.0 adaptation
- The peer gate. dsh 0.2.0 checks every
@deepseek-ai/dsh-*peer of a
plugin against the running dsh and refuses to load it on mismatch (with
dsh plugin allow-versionas the explicit escape hatch). Every pin —
dependencies, devDependencies, peerDependencies — moves to0.2.0-rc.2,
so the plugin loads on its own compatibility again. - The jobs seam. dsh-jobs 0.2.0 rewrote the registry:
list/killnow
take the owner's id (typedSessionIdin the API; producers register
with the owning agent's id) instead of the Agent object, the
onJobsChangedvisible-set listener is gone in favour of a per-commit
events.subscribe, andJobSnapshotbecameJobView(a structural
superset of what the roster reads, so rows still pass through unmapped).
The Jobs window re-lists on the lifecycle commits it renders —
registered,stopping,settled,removed— and skipsoutputand
progress, which fire far more often than the roster changes. - The wire rung's job scenario now also kills the background job from the
Jobs window, covering the newkillcaller end to end — and writing it
exposed two latent bugs: the scenario's menu walk never opened the View
menu (rightmoves along the bar without opening; adownwas missing,
and the old check passed vacuously on the transcript card's text plus the
Project tree's▸), and the scripted job slept five seconds, settling
long before the roster ever showed it. The job now sleeps past the whole
script and the checks assert the running row and the killed row by their
roster detail text.
0.4.0 — the Messages wire, update awareness, and the workspace as a tree
Adapted to DeepSeek Harness 0.1.7, which changed the wire under the desktop twice over — and the desktop now tells you when it is out of date.
The dsh 0.1.7 adaptation
The DeepSeek adapter moved from OpenAI-style /chat/completions to the DeepSeek Messages API (/v1/messages, Anthropic-style SSE with content_block events). The mock endpoint — the wire rung's scripted model — speaks the new protocol frame for frame, and the wire rung tells the whole story on the new stack: 22 checks green. The bash tool's required description argument, agent/created becoming a waterfall, and the session log's v3→v4 bump all landed without moving a single golden fixture — the fold's shapes are unchanged.
Update awareness
The desktop checks GitHub once a day at boot — a status cell (↑0.5.0) and a one-per-version notice appear when a newer release is out. /update confirms, hands the terminal to the update command (a git checkout is pulled and rebuilt in place; a registry install goes through dsh plugin up), and restarts into the same session. A failed update restarts the current version — a dirty exit never leaves a dead screen.
The workspace as a tree
The Project window shows the index as a folded tree: directories first with ▸/▾ markers, files after them, two spaces of indent per depth, collated case-insensitively. Enter opens a directory or references a file into the composer; a mid-session refresh keeps your own folds.
Full notes: CHANGELOG.md
0.3.0 — every seam has a surface
The interactive seams close: every way the harness asks a human something — or a human asks the harness — now has a first-class character-cell surface.
Subagents, visible
A delegated child is a window, not a buried tool card. The Subagents window lists the catalog; Enter opens the child's own transcript — the parent's conversation and the child's in overlapping framed windows at once, the thing a line renderer cannot do. Running markers flip live; a child that ran before this boot loads lazily. And Escape dismisses a raised panel, the Borland reflex, never the desktop itself.
Plan mode, end to end
The review dialog renders the plan as the markdown it is. Questions take free-text answers (Other… — the custom field the contract always carried), so "keep planning, and here is why" finally has a why. The prompt reads dsh plan> across turns, and the Plan window keeps the approved plan readable for the whole execution that follows.
Skills and cross-session references
The workspace's skill catalog is browsable and callable: a Skills window, /-completion over it, and a /name line that injects the canonical skill-invocation message — the official semantics, which no in-process host was providing. @-mentions reference other sessions: candidates labelled by their titles, a canonical mention inserted, and the harness attaches a bounded read-only snapshot the transcript folds in as Recall — never in the user's voice.
Under the hood
The wire rung tells the whole story — twelve scripted turns through the real harness, 22 checks, including delegation, plan review with typed feedback, and a resume boot that must show its history on screen. The startup grammar and the fold's diff readers gain unit pins, and BRIEF's risk table says what is true today.
Full notes: CHANGELOG.md
0.2.0 — tables, breakpoints, and the seams in between
The transcript stops being a printout and starts being a terminal worth reading, and the desktop claims two of the harness's decision seams.
Markdown that carries meaning
- GFM tables render aligned — columns measured to their widest cell, alignment read off the delimiter row, a dim
│between columns — and stack asheader: valuecards when the measure cannot hold them. - Inline code wears the palette's code colour instead of an inverse bar; the
markeddependency is gone — the renderer is hand-written and streaming-safe. - Headings render as a colour ladder on a new
headingpalette role:##underlines as a section,###stands plain, deeper levels dim. The literal###never reaches the screen. - Bare BMP emoji cost one column, not two — a
☔column no longer shears its table.
Breakpoints
/breakpoint bash(rm *), Ctrl+B, a Breakpoints window, and a hold/run/deny dialog: the desktop claims tools/pre-execute, so a matching tool call stops before it runs.
The harness contract, honoured further
- The status bar reads the token-meter projection — the same replay compaction reads — gaining the cache column (⇄) and the provider-reported context pressure.
/attachcarries files to the model as durable attachments — content-addressed, byte-exact, riding exactly one message. The model receives the file, not a path it has to be trusted to open.- A resumed session boots with its history on screen —
dsh --profile tvision --resume <id>and the Sessions window both land on the persisted transcript, not an empty one. /quitleaves through the same door Ctrl+Q uses.
Under the hood
The recording pipeline (the README gif and the five skin stills) no longer tears frames, splits CJK glyphs across chunk boundaries, or loses 1px borders to pre-scaling. A four-angle review consolidated the local-command registry into one table, narrowed the projection snapshot to the two units it consumes, and switched /attach to the store's byte-level commit.
Full notes: CHANGELOG.md