dsh-emacs

August 30, 2026 · View on GitHub

dsh-emacs is an Emacs frontend for DeepSeek Harness (dsh): it talks to a running dsh web service over plain HTTP/WebSocket and renders sessions, streaming replies, tool calls, thinking blocks and slash commands with an Emacs-native UI.

It aims to be the complete, zero-friction client for dsh web — built on nothing but Emacs built-ins (Emacs 27.1+), with zero third-party dependencies.

Quick Start

Requirements: Emacs 27.1+. The dsh CLI is optional — if it is missing, the first server-touching command offers to install it, then starts the server for you. No build step, no manual dsh web.

Install from this repository:

(add-to-list 'load-path "/path/to/dsh-emacs")
(require 'dsh-emacs)

Then M-x dsh-emacs to open the session list. That's it.

A fuller example

This shows a typical setup — server auto-start, defaults, custom keybindings — and how a session lands in the right workspace:

(use-package dsh-emacs
  :load-path "/path/to/dsh-emacs"
  :commands (dsh-emacs dsh-emacs-new-session)
  :custom
  (dsh-emacs-base-url "http://127.0.0.1:3080")   ; point at a remote server instead
  (dsh-emacs-default-model "deepseek-v4-flash")
  (dsh-emacs-default-preset "code")
  (dsh-emacs-server-start-on-init t)             ; eager background start
  :bind (("C-x d" . dsh-emacs)                   ; open the session list
         :map dsh-emacs-mode-map                 ; inside a chat buffer
         ("C-c C-a" . dsh-emacs-attach-file)))

Common keys inside a chat: C-c C-c send — press again to interrupt — C-c C-m switch model, C-c C-a attach an image, C-c C-r refresh, C-c C-s switch session in this workspace (C-c M-s or C-u C-c C-s across all workspaces), C-c C-f toggle the mode-line stats, TAB complete /name. In the session list: RET open, c create, w workspace filter, / search, g refresh. Everything else is in the manual.

Server setup

By default everything is managed for you: before the first RPC, dsh-emacs-server-ensure probes the base URL, locates (or offers to install) the dsh CLI, and spawns dsh web --no-open in the background. Set dsh-emacs-server-auto-start to nil to run the server yourself — a server you start is used and never killed.

Works with remote deployments too: a non-loopback base URL — including https:// and nginx Basic-Auth via user:pass@host — is probed and used directly, and dsh-emacs never spawns a local server for a remote one.

Provider/model configuration is owned by dsh, not by dsh-emacs: configure it in the dsh web UI (M-x dsh-emacs-open-web) or the dsh home files (~/.dsh/settings.yaml, ~/.dsh/.credentials.yaml).

Screenshots

Session list view

Chat buffer view

Documentation

Contributing

Changes come in via pull request; the main branch is protected, and each PR should be one topic. For non-trivial work, open an issue first to align the scope. Development workflow, verification commands and commit conventions are in AGENTS.md — run emacs -Q --batch -l scripts/check-lisp.el and the test suite before pushing.

Acknowledgments

The UI is designed to mirror the dsh web UI: tool rows reuse its exact SVG icons and ToolRow / ioCard semantics, and the session list, command rows and context meter follow dsh-web conventions.

The Markdown-rendering and folding machinery builds on agent-shell (agent-shell-ui.el / agent-shell-markdown), and the mode-line stats and compact token formatting follow pi-mono.

License

GPL-3.0-or-later — GNU General Public License v3 or later.