dsh-vim
v0.1.0
Published
Vim-style modal keyboard navigation, extracted from DeepSeek Harness ui-vim: framework-agnostic core plus a DeepSeek Harness adapter
Maintainers
Readme
dsh-vim
Vim-style modal keyboard navigation for the DeepSeek Harness Web GUI.
A short recording of modal navigation and the keybindings settings page in the DeepSeek Harness Web GUI.
- Core (
src/core): framework-agnostic vim keyboard engine — keymap, router, modal state, cursor/scroll/composer actions. - Adapter (
src/adapter-deepseek-harness): thin DeepSeek Harness plugin shell that wires the core into Cordis services and theshell.overlayslot.
Status
Extracted from packages/client/ui-vim in the DeepSeek Harness repository
(commit 528d5204, package @deepseek-ai/dsh-client-ui-vim).
Compatibility
Targets DeepSeek Harness 0.1.0-rc.7 (@deepseek-ai/* pinned to rc.7 in
peerDependencies). The vim engine reads the rendered web shell through stable
data-* attributes ([data-chat-flow], [data-shell-overlay], …); these are
not a public API — pin the plugin to your harness version and verify after
upgrading (see docs/adapter.md).
Default keymap
| Sequence | Action |
| --- | --- |
| j / k | Move cursor down / up |
| g g / G | First / last row |
| h / l | Fold / unfold tool row |
| Ctrl+d / Ctrl+u | Half-page down / up |
| z z / z t / z b | Scroll cursor center / top / bottom |
| y y | Copy current row |
| Ctrl+1 / Ctrl+2 | Toggle sidebar / details |
| g s / g d / g c | Toggle sidebar / details / goto conversation |
| Ctrl+h / Ctrl+l | Focus panel left / right (sessions · conversation · details; stops at edges). On the session list j/k pick a session, Enter opens it |
| : | Enter command mode |
| Esc | Back to normal mode (only Esc; Ctrl+[ is intentionally unbound) |
| g ? | Open the keybindings settings page (list + customize every binding) |
Command mode (:):
| Command | Effect |
| --- | --- |
| side | Toggle sidebar |
| details | Toggle details |
| theme <name> | Apply theme |
| vim on / vim off | Enable / disable vim keys |
| help / h | Show key help |
Keybindings settings page

Press g ? (normal mode) to open the settings panel on the Vim keybindings
page (also reachable via the sidebar gear → settings nav): it lists every
binding of the current mode with its action, lets you rebind an action by
pressing the new key sequence (multi-key combos like g g work; commit happens
after a short pause), remove a binding, or restore the built-in keymap in one
click. All changes persist to the durable ui-vim.keymap settings section, so
they survive reloads and can be edited by hand in settings.yaml (see
docs/adapter.md). While the page is on screen only g ?
and Esc act; Esc also cancels a rebind capture.
Install / usage
This package publishes a framework-agnostic core as dsh-vim. The DeepSeek Harness adapter is
shipped as source under src/adapter-deepseek-harness; see
docs/adapter.md for how to load it in a DeepSeek Harness
installation.
Installing into DeepSeek Harness
To enable vim-style keyboard navigation in your DeepSeek Harness Web GUI:
Install the bundle into your profile:
dsh plugin --profile web add dsh-vimThis adds
dsh-vimas a dependency to your profile and registers it as a bundle layer. Thecordis.patch.ymlin the package inserts the host-side settings registration, the browser-side engine, and the invariant companion.Verify the layer is active:
dsh --profile web --dump-config | grep -A 5 ui-vimBoot the Web GUI:
dsh --profile webPress
g ?in normal mode to open the keybindings settings page and customize bindings. Vim mode is enabled by default; toggle it with:vim offor:vim onin command mode.
Configuration
Vim settings are stored in the ui-vim section of your settings.yaml:
ui-vim:
enabled: true
indicator: true
keymap:
normal:
x: copy-row
j: '' # removes the built-in j bindingSee docs/adapter.md for the full settings schema.
From a local checkout
If you have a local clone of this repository:
dsh plugin --profile web add ./path/to/dsh-vimThis uses a pnpm link: dependency, so changes to the source are reflected
after rebuilding (pnpm build).
From GitHub
dsh plugin --profile web add github:Loyage/dsh-vimNote: git installs fetch sources, not built artifacts. The package includes
a prepare script that builds automatically after installation.
FAQ
| Symptom | Cause & fix |
| --- | --- |
| Ignored build scripts warning | pnpm 10+ blocks dependency build scripts by default. In the profile directory (~/.dsh/profiles/web) run pnpm approve-builds --all. |
| minimum release age / version younger than 24h | Freshly published versions are subject to pnpm's 24h minimum release age. Wait 24h, or re-run the command (pnpm fills minimumReleaseAgeExclude automatically). |
| “profile directory not found” | Run dsh web once to initialize ~/.dsh/profiles/web before installing plugins. |
| Keys unchanged after updating | Hard-refresh the browser (Cmd/Ctrl+Shift+R). Client changes hot-reload without a DSH restart; only host-half changes (src/adapter-deepseek-harness/index.ts, schema.ts, invariant.ts) need a restart. |
| Two mode indicators / keys respond twice | Double mount. Remove any leftover manual - insert line for dsh-vim in ~/.dsh/profiles/web/cordis.patch.yml; when an aggregate bundle (e.g. @linxin666/dsh-web-ui-all) mounts this package under its own entry id, the bundle patch backs off automatically — make sure only one channel is active. |
| Keys don't respond in an input field | In insert mode the vim keys intentionally don't hijack typing. Press Esc to return to normal mode. |
| Bindings break after a DSH upgrade | The engine relies on stable data-* hooks, which are not a public API. Pin dsh-vim to your harness version and re-verify after upgrading (see docs/adapter.md). |
Known limitations
Ctrl+[is intentionally not bound as an alternative toEsc(see Default keymap).- The
data-*hooks the engine reads are not a public API — pin the harness version and re-verify after upgrading (docs/adapter.mdlists the full selector set). - Panel focus navigation stops at the edges (sessions · conversation · details) and does not wrap; on the session list
j/kpick a session,Enteropens it. - Multi-key sequences resolve within
SEQUENCE_TIMEOUT_MS(900 ms); two presses slower than that are treated as independent actions. - The
g ?navigation to the settings page walks the shell's a11y hooks and is best-effort; the page can also be opened from the settings panel navigation.
Platform support
- Host: DeepSeek Harness 0.1.0-rc.7 web profile (
--profile web), Node.js ≥ 20. - Browser: any modern evergreen browser (Chrome / Edge / Firefox / Safari) — the client runs inside the shell, no browser-specific code.
- OS: no native dependencies, no node-pty-style compiled artifacts; consistent across Windows / Linux / macOS.
- Other clients: Web GUI only; the terminal client is out of scope.
Development
pnpm install
pnpm test
pnpm buildLicense
MIT. Contains code derived from the DeepSeek Harness project
(packages/client/ui-vim, MIT, Copyright (c) 2026 DeepSeek).
Repository: https://github.com/Loyage/dsh-vim
