DeepSeek Harness plugin

dsh-voice-kotdath

ChatGPT-style voice input for the DeepSeek Harness Web GUI: mic button, recording pill with live waveform, transcription via transcribe.cpp (Handy model catalog), whisper.cpp, or an OpenAI-compatible

Jump to install

Source facts

Repository
KotDath/dsh-voice
Latest update
Aug 19, 2026
Category
Plugin Markets & Managers
GitHub stars
0
Format
plugin
Catalog evidence
Upstream dsh.bundle evidence
Evidence path
package.json#dsh.bundle
Checked against
0.1.0-rc.8
Upstream check date
2026-08-20

This evidence comes from the upstream catalog. This site has not installed, run, or security-reviewed the plugin.

Install

Start with a prompt that asks an agent to review the GitHub repository and source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to review the GitHub repository and source first.

Do not install or run any commands yet. Read this plugin's GitHub repository, README, and relevant source code. Then answer the questions below clearly and directly so I can decide whether it fits my needs:

1. What is this plugin, and what problem does it solve?
2. Who is it for, and what are its typical use cases?
3. How is it used after installation? Include one minimal example.
4. What known limitations or privacy, security, compatibility, or maintenance risks does it have?
5. Give a clear recommendation: recommend, conditionally recommend, or do not recommend, with reasons.

Distinguish statements documented by the repository, inferences from source code, and unknowns. If evidence is insufficient, say so explicitly. Do not guess or simply repeat the README.

GitHub: https://github.com/KotDath/dsh-voice
Plugin: dsh-voice-kotdath
Author: KotDath

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer3 files
README.mdSource · read only

dsh-voice

Voice input for the DeepSeek Harness Web GUI — as an official plugin bundle.

A microphone button (SVG icon) sits next to the send button in the composer. Clicking it brings up a ChatGPT-style recording "pill" above the composer:

[ ✕ cancel ] [~~~~~~~~ waveform ~~~~~~~~] [ ⏹ stop ] [ ↑ send ]
  • — cancel the recording;
  • — stop, transcribe and insert the text into the input (without sending);
  • — stop, transcribe and send to the chat immediately.

The waveform is a row of vertical bars: fresh signal arrives on the right, history fades left into a dim dotted baseline (like ChatGPT's voice mode).

Installation

Requirements

  • A running DeepSeek Harness with the Web GUI (Node.js quick start:

npx @deepseek-ai/dsh web, default http://127.0.0.1:3080).

  • On the host machine: bash, curl (engine/model downloads), ffmpeg (audio

conversion). The transcribe.cpp engine is downloaded automatically per OS/architecture from this repository's Releases — or adopted from PATH / a sibling .engine/ dir if a transcribe-cli binary already exists.

  • A browser with mic access over HTTPS or localhost.

Install into a profile (all sessions)

dsh plugin --profile web add github:KotDath/dsh-voice

For a local test build instead:

npm install && npm run build
dsh plugin --profile web add file:/path/to/dsh-voice

Then restart the web process (dsh web) — the new plugin row is picked up at boot. After that the plugin is active in every session of the profile: no per-session cordis_define, no source edits.

The package declares dsh.bundle.patch (→ cordis.patch.yml, one row id: voice, name: dsh-voice) and dsh.client (→ the browser half lib/client.js). dsh plugin installs it with pnpm into the profile and reconciles dsh.profile.bundles automatically.

To remove:

dsh plugin --profile web remove dsh-voice

First-run flow (for the end user)

1. Open Settings → Voice — the engine is either ✓ installed or downloadable with one click ("Download engine", releases built by CI). 2. Pick a model from the catalog and press Download if it is not marked ✓. 3. Use the mic button next to the send button in the composer. 4. Record → cancel / insert / send.

Architecture

[Client: browser]                                [Host: Node]
┌─────────────────────────────────┐  fetch      ┌────────────────────────────────┐
│ slot conversation.input.right   │ ──────────► │ /api/voice/transcribe          │
│  • MediaRecorder (webm/opus)    │ base64+meta │  • base64 -d → file           │
│  • AnalyserNode → waveform      │              │  • ffmpeg → 16 kHz mono wav    │
│  • timers, states               │ ◄─────────── │  • provider:                  │
│ inputActions.setDraft + submit  │   { text }   │     tcpp:  transcribe-cli      │
└─────────────────────────────────┘              │     local: whisper-cli -oj     │
                                                 │     api:   curl multipart     │
                                                 │  • temp file cleanup           │
                                                 └────────────────────────────────┘

Unlike the earlier dynamic-plugin versions, the two halves do not use the harness.handle/host.call bridge: the Node half registers plain HTTP endpoints on the harness webserver (/api/voice/*), and the browser half calls them with fetch. That is the pattern used by other static bundle plugins (e.g. dsh-track).

Transcription providers

Switchable in Settings → Voice (state is kept in memory, as expected from a plugin bundle).

ProviderHow it worksRequirements
tcpp (default)the transcribe.cpp engine (the same one inside Handy) — a static transcribe-cli binary (~5 MB). A catalog of 67 models (GigaAM v3 CTC/RNN-T/E2E, Voxtral Mini 3B/4B/24B, Whisper tiny…large-v3 (+turbo), Qwen3-ASR, Parakeet, Canary, Moonshine, Nemotron, Granite, SenseVoice, Fun-ASR, Cohere, MedASR…). Model picker dropdown, one-click Hugging Face download with progressengine (self-downloads for Win/macOS/Linux)
localwhisper.cpp (whisper-cli) + one GGML modelpaths to the binary and model; offline
apiOpenAI-compatible POST /v1/audio/transcriptions (multipart)URL, API key, model name (gpt-4o-transcribe, whisper-1, Groq, a local faster-whisper server, etc.)

transcribe-cli engine: out of the box, no Handy app needed

  • The plugin does not depend on the Handy application: the ASR engine is the

open-source library handy-computer/transcribe.cpp.

  • The binary is downloaded with the "Download engine" button from this

repository's GitHub Releases for the current OS/architecture (transcribe-cli-{platform}-{arch}, .exe on Windows).

  • If a transcribe-cli already exists on PATH or next to the configured

engine path, the plugin adopts it (copies it into its own directory) — no download needed. Discovery is explicit; there is no filesystem sweep.

  • Downloads are verified against a .sha256 sidecar when one is published

(best-effort integrity check).

  • Plugin data (engine, models, temp files) lives in the DSH process launch

directory (.engine/, .models/, .tmp/) — the sandbox only allows writes there. Paths are shown in the settings.

  • Release binaries are built by CI (.github/workflows/build-engine.yml):

Linux x86_64/arm64, macOS arm64/x86_64, Windows x86_64.

  • Models are GGUF files from Hugging Face (handy-computer); the catalog is

embedded in the plugin (sizes drive the progress bar). Models already downloaded by Handy into the HF cache are picked up automatically — no re-download required.

  • Long recordings: many models have a ~25 s window (e.g. GigaAM) and silently

lose the rest of a long recording. The plugin splits audio longer than 22 s into 20 s segments and transcribes them in one batch run (single model load, full text concatenated).

Verified on this machine: GigaAM v3 E2E-RNN-T — 30× realtime, Voxtral Mini 4B Realtime — 1.7× realtime (20 s of Russian audio), excellent quality.

API key handling

The OpenAI-compatible API key is host-only: it is set via its own endpoint (POST /api/voice/api-key), never echoed back to the page (the settings show only whether a key is set), and is passed to the provider via the DSHVOICE_API_KEY environment variable — never in argv.

Development

npm install          # dev deps (uses .npm-cache/ if ~/.npm is read-only)
npm run build        # gen-catalog → tsc → tsdown (lib/index.js + lib/client.js)
npm test             # host + client unit tests (plain Node, no browser)

The installable artifact is the npm package at the repository root. See [AGENTS.md](AGENTS.md) for the full agent instructions (layout, endpoints, security rules, troubleshooting).

Repository layout

src/plugin/          — Node half (index.ts, HTTP /api/voice/*) + browser half
                       (client/: state, recorder, waveform, components,
                       settings, voice.module.css) + generated catalog
scripts/gen-catalog.mjs — injects models.json into generated-catalog.ts
tsdown.config.ts     — node ESM bundle + browser CJS-closure bundle
cordis.patch.yml     — the bundle's composition patch (one row: id voice)
package.json         — dsh.bundle.patch + dsh.client declarations
models.json          — model catalog (source of truth)
test/                — host + client unit tests
.github/workflows/build-engine.yml — CI: plugin tests + 5-platform engine builds
AGENTS.md            — agent install/update instructions
README.md            — this document

Released versions are pinned by git tags (v0.3.0, …).

v1 limitations

  • Recording uses the browser MediaRecorder (HTTPS or localhost required).
  • Transcription is batch (after the recording ends); streaming partials are

planned.

  • Upstream whisper.cpp does not support Handy's Qwen3-ASR GGUF (needs the

transcribe-cpp engine); standard ggml models (tiny…large-v3) work.