Repository navigation
Releases: vritser/dsh-emacs
Release list
dsh-emacs 0.7.0
Compatible with dsh 0.2.1-rc.2, the latest upstream release as of 2026-10-18 (npm next; npm latest still points to 0.2.0-rc.2). The minimum supported Emacs version is now 28.1.
Breaking changes
- Emacs 28.1 is now the minimum; 27.1 support is removed. CI runs the gate on 28.1 and a current stable release.
- Removed Lisp helpers (no aliases):
dsh-emacs-modeline-set-cwd,dsh-emacs-modeline-set-branch,dsh-emacs-modeline-teardown,dsh-emacs-usage-p. Mode-line cwd and branch use the chat'sdefault-directoryand cached Git detection. - Removed inactive transcript options:
dsh-emacs-group-consecutive-tools,dsh-emacs-assistant-divider.
Opening sessions
- Complete rounds on open: a fresh chat buffer completes the latest round, paging back for a long round without moving the draft cursor or delaying the live stream.
C-c C-ocancels a pending load and then loads earlier rounds (three by default). - Cheaper tool-heavy history: live and replayed tool cards format their terminal, read, diff and generic result bodies only when expanded, and repeated expansion reuses the formatted body. Expanded cards still update as results arrive.
Transcript
- Web-style task and activity disclosures: settled thinking and tool cards fold into independent summaries between visible replies; a successful turn without mid-turn input folds its whole process under a muted Completed in … row.
RETtoggles each disclosure; setdsh-emacs-fold-work-detailstoniland reopen to flatten the transcript. - Stopped and interleaved turns match Web: Failed/Stopped rows no longer hide the process, mid-turn input keeps the turn open, and automatic compaction folds with its activity without contributing a tool count.
- No duplicate replies while opening: reentrant WebSocket reads queue behind the active snapshot consumer, so thinking, tools and final answers no longer render twice around the reply footer.
- No flash of expanded work: snapshots and older pages redraw only after reply footers and task folds are reconciled; completed work first appears collapsed.
- Copy and navigation details: copy-line/region drops the hidden prompt and transcript properties,
C-areaches the first authored character, and the blank line below a question survives the first streamed chunk.
Markdown and links
- Links keep their colour when the label is inline code, bold, italic or struck through.
- Emphasis and inline code no longer rewrite link/image targets, including incomplete streamed ones; linked images open the enclosing link.
- Local paths decode URI escapes once, support workspace-relative targets and one-based line/column positions; invalid targets no longer launch a browser, and unsafe schemes are rejected.
- File links with line ranges (
file.el#L10-L20,file.el:10-20) open in Emacs at the first line. - Bracketed local image destinations such as
render; images inside inline or fenced code stay literal. - Multi-backtick inline code is literal, and partial streamed bare image paths wait for their boundary.
Appearance and mode line
- Image attachments use a web-style thumbnail gallery in wrapping rows:
RETormouse-1opens the original, anddsh-emacs-render-image-thumbnail-linessets the height. - Clearer conversation grouping: a three-pixel teal rail instead of a full-width highlight, with Copy, Fork and tokens together on the left in configured order.
- Next Message above the Goal Row, and a visible gap between the collapsed goal notice's icon and label.
- Running-subagent icon and count pulse together with Motion Line; native mode lines show plain
DSH; header separator colours follow the adjacent label. - Idle session indicators inherit
shadow, and every chat window keeps its own draft cursor while output follows.
Sessions, state and robustness
- Switching to an already-open session reuses its live buffer without clearing transcript, draft, cursor position or event stream;
C-c C-rremains the explicit resync. - The model indicator stays in sync with live selections, including switches made in another client.
- Running status survives
C-c C-r, and a completed turn is not revived by a stale session-list flag. - RPC and WebSocket bodies keep required booleans, nulls, arrays and empty objects regardless of user
json.elencoding settings. - Workspace regrouping no longer trips the Emacs transposition crash or corrupts multibyte row text.
- Desktop notifications fall back without D-Bus, and a question or approval whose prompt cannot open is declined instead of leaving the host waiting.
- Chat startup no longer prints internal integration flags; Emacs 28 keeps goal objectives in the help buffer and leaves unchanged cards untouched.
Upgrade
- Emacs 28.1+ is required.
- Remove calls to
dsh-emacs-modeline-set-cwd,dsh-emacs-modeline-set-branch,dsh-emacs-modeline-teardownanddsh-emacs-usage-p, and settings fordsh-emacs-group-consecutive-tools/dsh-emacs-assistant-divider. - Change
dsh-emacs-default-presetfrom"code"to"ptc". - Restart Emacs after updating.
Validation
scripts/verify.sh: passed — syntax checks, byte compilation (free-variable warnings fail), 1,235 unit tests with and without Motion Line, clean load, whitespace and junk scans.- Real-server RPC and event-stream suite against dsh 0.2.1-rc.2: 31 passed, 0 failed (2026-10-23).
- Optional model-driven subagent and running-status scenarios were not enabled in this release run.
dsh-emacs 0.6.1
Compatible with dsh 0.2.1-rc.2, the latest upstream release as of 2026-10-18. This version is published under npm next; npm latest still points to 0.2.0-rc.2. Emacs 27.1+ remains supported.
Compatibility fixes
- Use server-assigned session IDs when activating drafts, preserving draft text and retry state.
- Surface migration-required projection reads as errors instead of accepting them as session state.
- Keep external subagents visible while preventing unsupported local navigation and interruption.
- Update the RPC reference for the dsh 0.2.1 protocol. Existing browser-cookie authentication remains supported;
/connectmigration is not required.
Transcript feedback
- Show retries once in the transcript, removing the duplicate mode-line Retry/Retrying label.
- Distinguish scheduled/started retries, failed replies, cancellation, and recovery retries confirmed by a later response in the same step.
- Give retry and error events a consistent compact layout and status dot: orange for retries, red for failures, grey for cancellation or unknown outcomes. Model error codes appear as muted metadata, with explanations visible below.
- Preserve expandable partial output and folding when outcomes arrive, including through older-history pages. Release outcome caches when the corresponding transcript content is trimmed.
Upgrade
Restart Emacs after updating to load the changed protocol structs and remove old mode-line definitions.
Validation
scripts/verify.sh: passed, including syntax checks, byte compilation, unit tests with and without Motion Line, and clean load.- Real-server RPC and event-stream suite against dsh 0.2.1-rc.2: 28 passed, 0 failed.
- Retry classification regressions cover live events, history replay, older-page insertion, step boundaries, and cache pruning.
- Optional model-driven running-status, subagent, plan-review, and timed-question scenarios were not enabled in this release run.
dsh-emacs 0.6.0
An expanded Emacs client for the dsh 0.2.0 protocol, with subagent conversations, plan review, staged attachments, and smoother history and completion. Emacs 27.1 remains the minimum; Motion Line is optional.
Upgrade notes
- Attachments are staged before sending.
C-c C-aadds one file; repeat to add more, then send everything withC-c C-c. Drag-and-drop also stages files. Lisp callers use(dsh-emacs-attach-file file); the caption argument has been removed. - Queue and job counts have left the mode line. Use the Composer preview and
C-c C-qfor pending input, and tool rows orC-c C-jfor jobs. Remove customizations of the deleteddsh-emacs-modeline-queue-face,dsh-emacs-jobs-modeline-face, anddsh-emacs-jobs-map. - Composer rows use the buffer background. Remove references to
dsh-emacs-input-box-face,dsh-emacs-color-input-bg, anddsh-emacs-color-input-bg-dark. - Restart Emacs after upgrading to replace removed definitions and changed protocol structs. The protocol reference records the audited dsh
0.2.0-rc.2baseline; this release does not promise full compatibility with older servers.
Highlights
- Browse subagent conversations from the session tree or minibuffer, send follow-ups to continuable children, and return to the parent through xref.
- Enter plan mode with
/plan, review submitted plans in a document buffer, and approve execution or request changes. Timed questions support late answers, and approval reasons can follow your locale. - Attach arbitrary files, paste clipboard images, and review the staged set before sending.
- Load complete earlier rounds with
C-c C-o, return to the draft withC-c >, fork from an assistant reply, and use configurable reply actions and usage statistics. - Start typing while a session is created. Discover
@references asynchronously, with live Corfu refresh and session-list visibility filtering. - Follow goal activity and automatic compaction in the transcript and Composer. Optional Motion Line integration adds an animated whale and elapsed clock.
- Add providers and select reasoning effort from Emacs; reload local source with
M-x dsh-emacs-reloadwhile preserving chats and drafts. - Rendering, session-list updates, and JSON decoding receive performance improvements. The README now focuses on setup and everyday use, with detailed guides linked separately.
Full changelog · Getting started · Compare with 0.5.0
Validation
scripts/verify.sh: passed, including the unit suite with Motion Line.- GUI display regression suite: 2 passed.
- Real-server transport smoke suite: 28 passed. Optional model-driven subagent, running-status, plan-review, and timed-question scenarios were not enabled in this release run.
dsh-emacs 0.5.0
Emacs client for DeepSeek Harness
(dsh): streaming replies, tool cards, thinking blocks, slash commands, and
session/workspace management — Emacs 27.1+, no third-party dependencies.
Requires a dsh server on the 0.1.6 wire protocol (0.1.6-alpha.1 or
newer). Seedocs/rpc.mdfor the protocol reference.
Highlights
- Paste a clipboard image into the next message —
C-c C-vstages a
screenshot or copied picture in a Composer row above the input;C-c C-c
sends text and image together.C-c C-ddiscards the staged images,s-v
does the same whenever the clipboard holds an image (and stays a text yank
otherwise), andM-x yank-mediaworks on Emacs 29+. - Opening the session list lands on the session you are in — cursor and
hl-linemove to the current session's row (unfolding its group and clearing
a hiding filter if needed) instead of parking on the first row. - Undo/redo scoped to the input area —
C-/,C-_andC-x uundo input
editing,C-g C-/redoes it; the rendered transcript is never undone. - Ask rows record the decision — an
ask_user_questioncall collapses to
Ask question · waiting/2/2 answeredand expands into the questionnaire
with the chosen options checked, instead of dumping raw JSON. - Restore an archived session without leaving Emacs —
M-x dsh-emacs-unarchive-session, oruin*dsh-sessions*, the inverse thed
archive action never had. - Failed tool rows explain themselves — a settled
tool/resultshows
dsh 0.1.6's user-facingerror.reason(✗ failed — …) rather than a bare
failure. - See and switch the session's permission preset — a shield-icon mode-line
segment shows the current sandbox/approval preset, andM-x dsh-emacs-set-permissionoffers the host's preset catalog.
Changed
- Opening the session list no longer re-fetches or reconnects. The list
stays live from the event stream, soM-x dsh-emacs/C-c C-lreuses the
cached rows;gstill refreshes on demand. TABcompletes ordinary words and local file paths in the chat input.
Words already in the draft or transcript complete nearest-first; a token with
a separator (docs/rp,./src/,~/…, an absolute path) completes through
the stock file-name completer against the session workspace.- Generic tool cards line up and say what happened. Variant-less tools
expand into one alignedIN/OUTblock underTool Call · <tool name>,
and a clean success no longer prints a bogus✓ exit 0. - Ask option descriptions read as one face, with the bare description
instead of a bracketed suffix, matching the transcript's ask card.
Fixed
Streaming and rendering
- Streamed blocks stay separate through finalization and retry, and a finished
reply no longer gains a duplicate Think row. - Reconnect restores the complete in-progress reply once; live replies recover
from restarted counters and missing frames instead of leaving truncated text. - Thinking no longer rewrites the transcript while it streams, and a streamed
code block no longer rearranges what is already on screen. - Streamed replies and live Think output are read-only from the first chunk;
typing no longer stalls a block transition. - Markdown after a code fence renders in the same chunk; interleaved answers
keep their order when finalized. - File diffs distinguish unchanged context from edits: only added/removed lines
get red/green prefixes and count toward the footer totals.
Session list
- A refresh no longer scrolls the list or drops a second window back to the
top; opening the list still moves to the current session. - Re-opening the list no longer resets folded groups, the workspace filter, or
the live-stream binding.
Sending and queueing
- Sent messages show up the moment the input clears; a rejected prompt removes
the optimistic echo and restores the draft. - An idle
C-c C-cis no longer queued as if the session were running, and no
longer flashes the blue Next Message row (first send in a new session
included). M-pno longer recalls the host's own injected messages
(<system-reminder>prose, runtime-context snapshots, notices).- Undo immediately after sending restores the draft.
Server and input
- A slow first server start waits the configured grace period instead of
reading as a failure, and says whether the process it started exited. - Wire booleans (
isDefault,authorable,hasDocument,attachments,
sessionrunning) are normalized where they cross into the protocol structs,
so a new session no longer pre-selects the wrong agent preset. M-<backspace>/M-DELclears punctuation at the input start (~/,../).
Full detail: CHANGELOG.md
dsh-emacs 0.4.1
dsh-emacs 0.4.0
dsh-emacs 0.3.0
dsh-emacs 0.3.0 — Emacs client for DeepSeek Harness (dsh), 46 commits
since v0.2.0.
This release migrates the client to the dsh 0.1.2 wire protocol — which
also introduces browser-session authentication, so it needs a server of
0.1.2-rc.1 or newer — and lands goals (Goal Row with pause/resume/edit/clear
actions), a Next Message row in the Composer, web-style @ references, local
!command shell execution, a bash terminal card, collapsible workspace groups
in the session list, and a deep pass of streaming-performance work.
Breaking changes
- dsh 0.1.2 wire protocol migration: the realtime surfaces move from the
per-session mux plus host stream to a single/api/remote.muxWebSocket
multiplexing logical streams — a chat opens asession/followstream whose
snapshot seeds the transcript, and the session list keeps a core connection
(session/control+workspace/follow+$events). RPC endpoints use the
two-segment slash form (session/list,session/create, …) with bodies
wrapped aspayload = {args: …}; questions and approvals arrive as$events
waterfall frames and are answered through$events/result. Workspace state
now comes fromworkspace/followinstead of aworkspace.listRPC, and
dsh-emacs-history-refetch-max-roundsis gone (reconnects reseed from a
fresh snapshot). Saved customizations of the removed option are dropped on
upgrade. - Slash-command and
@auto-pop go through your own completion
front-end: dsh-emacs no longer runs its own content-driven trigger to force
a popup for stock*Completions*/ vertico / ivy (and no longer
buffer-locally force-enablescorfu-auto). It is a completion backend
now — it registerscompletion-at-point-functionsand contributes/to a
front-end's auto trigger only when that front-end's own auto mode is already
on (corfu, company viacompany-capf). Stock*Completions*/ vertico /
icomplete stayTAB-only.dsh-emacs-slash-auto-complete(defaultt)
controls whether the/trigger is contributed at all. - Fragment extension API:
dsh-emacs-ui-find-blockand
dsh-emacs-ui-delete-fragmentnow take separatenamespace-id/block-id
arguments (joined ids and keyword deletion arguments are rejected), and
dsh-emacs-ui-update-fragmenttakes a complete snapshot — nil clears a field
and it returns(START . END). Theappendupdate argument, the unused
group andhide-label-on-collapseconstructor arguments, the
:color-keyargument (renamed:status; it never applied colors —:face
does) and several unused helper functions and faces are removed. No
compatibility shims are retained.
Added
- Realtime live chat and session list: an open chat keeps a
session/followstream on the shared mux socket, so replies stream in live
and a drop reseeds from a fresh snapshot instead of needing a manual refresh;
the session list keeps a core connection, so workspace, session and archive
changes from any client — including dsh web — repaint it in place, with live
queue/context projections. - Goal Row and goal actions: while a session has an active goal, a
read-only row pinned above the input shows a dartboard icon with the
objective and phase (never sent to the model, hidden for a completed goal),
andC-c C-gis a goal prefix —ppause,rresume,eedit (pre-filled
in the minibuffer),dclear,atoggle the inline SVG action icons,
?full objective and blocked reason. Actions are CAS calls on the live goal
ref, guarded against double-fire, and update optimistically. !commandlocal shell commands: a line starting with!and without
attachments runs the full input locally with Emacs'sshell-file-name
in the session's workspace — it works offline and while the model is busy,
becomes an expanded, collapsible transcript row with its exit status, and is
never sent to the model or saved in server history.C-c C-!stops the
tracked process. New options:dsh-emacs-shell-require-confirm,
-max-output,-null-stdin,-timeout
(see docs/shell-commands.md).@file/session references: typing@opens a combined completion menu
— files and directories from the session workspace first, then sessions —
with flexible (flex-style) matching across the whole path,@"path with spaces"quoting and host-side snapshots mirroring dsh web. Completed
mentions become atomic chips in the composer (backspace removes the whole
mention, RET opens a session or file), and mentions echoed in the transcript
render as clickable links instead of raw text —
@[label](dsh-session:…)shows as just@label. See
docs/reference.md.- Next Message row in the Composer: pending input gets its own read-only
row between the goal and the❯prompt, with a width-adaptive preview and a
full-text tooltip; steering items take priority over queued messages. - Bash tool rows expand into a terminal card: a bash/pwsh call opens into
dsh web'sBashRowshape — a code-block-style background band, a single$
prompt line, a divider, raw output, and a state-colored footer only on
failure or interrupt (a clean exit ends bare). Other tool variants keep the
IN/OUT ioCard. - Workspace folding in the session list: workspace and
Ungroupedheaders
show an expanded/collapsed indicator and fold withTABorRET; fold state
survives refreshes.dsh-emacs-workspaces-collapsed-by-default,
dsh-emacs-collapse-workspacesanddsh-emacs-expand-workspacescontrol it. - Browser-session authentication for dsh 0.1.2-rc.1+: dsh-emacs performs
the launch-token →dsh-auth-*cookie exchange itself, reading the token
from the managed server's output, fromdsh-emacs-server-auth-token, or from
a?token=indsh-emacs-base-url(stripped before requests are built, so
pasting the URL dsh prints just works), and sends the cookie on RPC posts, the
mux WebSocket handshakes and thedsh webURL. A401now reports an
actionable hint, and pointing at an external server prompts once for the
token instead of opening a Basic username/password prompt — the token is
remembered.
Changed
- Much less CPU while replies stream: socket reads coalesce over 50 ms, the
first chunk still appears immediately, Markdown scan state persists across
refreshes, mode-line segments rebuild only when their inputs change, and
transcript edits and history reads skip redundant redisplay work.
Following respects real line heights and multiline drafts. A streamed table
now renders in one pass when it ends instead of row by row (unfinished code
fences keep showing raw source as before). - Faster
@detection in long drafts and faster table wrapping: reference
completion inspects the buffer and copies only the active token, and each
cell character's display width is measured once and reused. - The model picker names the current provider:
C-c C-mprompts
Select model (current <provider>/<model>):, so ids shared by several
providers are unambiguous. - Session-list keys are clearer: archiving a session is
d(wasD) and
deleting a workspace isD(wasu), matching the other workspace keys
(W/R/M); the/text search anddsh-emacs-session-searchwere
removed as duplicates of the workspace filter and the session switchers.
Fixed
- Connecting to any real server works: client WebSocket frames are forced
to true unibyte UTF-8 before masking, so a multibyte payload no longer dies
on connect, and the browser-session cookie is actually minted — the exchange
now reads the first response's headers directly instead of following dsh's
303redirect into a401, which was surfacing as an unusable Basic
username/password prompt. A stale cookie self-heals instead of 401-looping,
session/listsends the wire_requestparameter again, and sending
non-ASCII (Chinese) messages works again. - The session list is grouped by workspace again (the
workspace/follow
stream is applied correctly), andgno longer opens a second live
workspace/followconnection. - Questions and approvals answered in another client are dismissed here
instead of staying pending. C-u C-c C-cconsistently steers, and a busy submit no longer falls back
to an optimistic send.- The mode-line
presetsegment works again: the wire migration moved
agentPresetinto a session projection, but the client kept reading the old
top-level row field, so a real server row produced no preset. - Composer editing:
C-kon an@chip removes the whole chip while
C-kelsewhere keeps standardkill-linesemantics, a forward delete at the
input's end no longer drops the cursor below the input, and goal editing
preserves the source text. - Tables: header styling stays above the reply base face, widths follow the
destination font and are no longer capped at the window edge, and width
probes preserve draft and undo history — deferred tables now finish on
Emacs 27–30. - Tool card IN/OUT labels keep their bold weight (
dsh-emacs-tool-io-face
declares it separately from its inheritance). - …plus many more fragment, streaming and rendering fixes — see the full
changelog below.
Full changelog: https://github.com/vritser/dsh-emacs/blob/v0.3.0/CHANGELOG.md
dsh-emacs 0.2.0
dsh-emacs 0.2.0 — Emacs client for DeepSeek Harness (dsh), 51 commits since v0.1.0.
This release renames the status bar to a mode-line, drops the HTTP polling
fallback, and lands queueing/steering of input while a turn runs, session
switching, project-aware session creation, interactive approval prompts,
notifications, inline image attachments and more.
Breaking changes
- Status bar "footer" renamed to "mode-line": customize group
dsh-emacs-footer→dsh-emacs-modeline, with options, commands and faces
renamed accordingly (-enabled/-format-spec/-branch-refresh-interval
→dsh-emacs-modeline-*). No compatibility aliases are retained — saved
customizations must be renamed to keep working. - Manual context-window options removed (
dsh-emacs-footer-context-window
/-alist): the ctx% segment is driven exclusively by the server's
session/projectioncontext window. - HTTP polling fallback removed (
dsh-emacs-poll-*): the WebSocket event
stream is the only automatic reply channel; recovery happens via stream
reconnect or manual refresh (C-c C-r).
Added
- Queue and steer while a turn runs:
C-c C-cno longer only interrupts —
perdsh-emacs-busy-enter-behavior(queue / steer / stop) input is queued as
the next turn or wakes the running agent;C-c C-qmanages the queue
(dsh-emacs-list-queue:eedit,ssteer,ddelete,RETsend now,
xclear all),C-c C-binterrupts, a[Q2 S1]mode-line indicator and a
next-input preview at the prompt mirror the server'ssession/queueframes. - Session switching:
dsh-emacs-switch-workspace-session(C-c C-s)
within the current workspace,dsh-emacs-switch-session(C-u C-c C-s)
across all workspaces; candidates match exactly what dsh web shows. - Project-aware session creation: new sessions inherit the current buffer's
directory, auto-detect the project root (project.el / VC root /.gitwalk)
and land in that project's workspace, created idempotently on first use. - Interactive approval prompts:
approval/requestedframes answered in the
minibuffer via/api/respond, serialized withaskquestions. - Notifications: run-finished and interaction (question/approval)
notifications when the chat buffer is not visible
(dsh-emacs-enable-notifications). - Filter-free question chooser:
1–9(0= 10th) pick an option
immediately,tswitches to free text; per-question skip key (s). - Per-session input history:
dsh-emacs-input-history-cross-session
choosesM-p/M-nscope; history seeded from the transcript, never lost on
toggle. - Inline image attachments rendered in the chat transcript.
- Remote dsh servers first-class: non-loopback / HTTPS URLs probed and used
directly (5s cap), userinfo/basic auth on probe, WebSocket and RPC, no local
CLI spawn. - Mode-line: opt-in provider segment, segment tooltips and hover
highlight. - Contributor tooling:
scripts/verify.shaggregates every
machine-checkable verification step into one exit-code gate.
Changed
scripts/verify.shnow gates byte-compilation (Errorfails the gate,
warnings stay allowed).scripts/check-lisp.elbecame diagnostics-only (ordered root-cause report
instead of an auto-fixer).
Fixed
- Stream reconnect no longer doubles the transcript (replayed mux frames gated
by seq anchor; reconnection itself no longer fails on a reused events buffer). - A fast second submit can no longer double-send; failed sends restore the
draft. - Mode-line spinner reliably stops at
turn/endeven when a very fast run
finishes before the prompt callback fires. M-p/M-nrecall works on first entry of a session.- Collapsed blocks no longer crash with
void-variable old-bodywhen new
chunks stream in. C-gon a question abandons the whole group like dsh web (protocol
cancelledreceipt); replayed questions are never asked twice.- ctx% reflects the server and survives failed runs, zero-sample re-submits
and incomplete session rows. C-c C-rrenders history into the issuing chat buffer; prompt images reach
the model as content parts; cursor stays on the input line and never rests on
the prompt icon; sending with an empty queue no longer flashesqueued:
feedback.
Full changelog: https://github.com/vritser/dsh-emacs/blob/v0.2.0/CHANGELOG.md