Repository navigation
Releases: dedomorozoff/dmsh
Release list
v0.5.2
dmsh v0.5.2 — paste everywhere, install from source
Two small things: the paste key now works in every field the TUI edits, and a
binary built from source can be installed without hand-copying it to /usr/local.
Fixed
Ctrl+V worked everywhere except where it mattered
tea.PasteMsg was accepted only in the idle and question states, so the fields
that nobody wants to type by hand had no paste path at all:
- the API key in the setup screen (
Ctrl+P→ setup), - the proxy login and password in the settings screen (
Ctrl+P→ settings), - the filter lines of the model menu (
Ctrl+O) and the palette.
A sk-... key or a proxy password had to be entered character by character, and
the window looked broken while doing it.
Paste is now routed to whichever field is actually active — the same way a key
press is — and in terminal mode it is forwarded to the pty, so
Ctrl+V/Ctrl+Shift+V inside the embedded shell pastes as expected. Pasting
outside an editable field is still ignored rather than silently changing a
value: the pasted password stays masked in the list, and the tests pin that a
paste with no open field reaches neither the password nor the input line.
Added
make install for source builds
Installing from source ended at make build — from then on it was sudo cp by
hand. Only Arch had a path (make dist-arch through makepkg -si). Three new
targets, all installing the binary and the man pages:
| Target | Destination | sudo |
|---|---|---|
make install |
$(PREFIX)/bin/dmsh, default /usr/local |
only if the prefix is not writable |
make install-user |
~/.local/bin/dmsh |
never |
make install-stub |
as install, but built without llama.cpp |
only if the prefix is not writable |
sudois added only when the prefix cannot be written; the check walks up to
the nearest existing directory, because~/.localmay not exist yet and-w
on a missing path is always false.PREFIX=moves the destination (make install PREFIX=/opt/dmsh),DESTDIR=
stages the tree for packaging and never pulls insudo.install-stubskips the CGO build: nollama.cpp, no local GGUF, remote
providers (Ollama, Pollinations) only — but seconds instead of a 15-minute
compile.- On Windows the targets print a pointer to
install.ps1, which stays the way
in there.
Release binaries are unaffected by these targets — release.yml builds with
go build directly — so installing from the .deb, .rpm or the tarballs is
still the shortest route for a packaged system.
Full Changelog: v0.5.1...v0.5.2
Full Changelog: v0.5.1...v0.5.2
v0.5.1
dmsh v0.5.1 — Ollama, proxy, setup screen, live model catalog
A second remote provider, one screen that changes how dmsh connects, and a
TUI with a real command palette and an embedded terminal.
What's new
Providers: now with Ollama
| Provider | Behaviour |
|---|---|
auto (default) |
local GGUF if one is found, otherwise Pollinations |
local |
local GGUF only; fails with a hint if none is present |
ollama |
a local Ollama server over its OpenAI-compatible /v1 endpoint; no API key |
pollinations |
Pollinations API; needs an API key, local models are ignored |
dmsh --provider ollama --remote-model qwen3:8b "list big files"
dmsh config set provider ollama- Ollama answers on
http://127.0.0.1:11434/v1, so nothing leaves the
machine and no key is involved; the default model isqwen2.5-coder. - If the server is not running or the model is not pulled, the error says
which of the two it is. Tool calling needs a model that supports it. - Ollama and Pollinations now share one OpenAI-compatible engine — the base
URL is a base like in any OpenAI SDK, routes (/chat/completions,
/models) are appended by dmsh.
Proxy for every outbound request
LLM API, websearch and GGUF downloads all go through one setting:
| Mode | Behaviour |
|---|---|
auto (default) |
HTTPS_PROXY / HTTP_PROXY / ALL_PROXY / NO_PROXY from the environment, direct if unset |
off |
always direct, environment ignored |
custom |
proxy_proto + proxy_host + proxy_port + proxy_user + proxy_password |
- Protocols:
http,https,socks5,socks5h;no_proxytakes hosts,
host:port,.suffixand CIDR entries. - One flag sets the whole address:
dmsh --proxy socks5://127.0.0.1:1080 "...",
or field by field (--proxy-mode,--proxy-proto,--proxy-host,
--proxy-port,--proxy-user,--proxy-password,--no-proxy,
--api-key). - Settings screen:
Ctrl+P→ settings: proxy and endpoint — one row
per field plus a connection test that sends one real request and
reports the route it took. - The status line shows
proxy:on/proxy:off, so the route is visible
before the first connection error, not after. Credentials are never
printed — only their source.
Setup screen: change provider and model without restarting
Ctrl+P → setup edits provider (auto / local / ollama /
pollinations), remote model, local GGUF, endpoint and API key in one
window. The engine is rebuilt first and the config file is written only
after it loads — a failed switch keeps the engine that was already working.
Session-level model switches (below) stay session-only until apply here
writes them to config.json.
Model menu with a live catalog
Ctrl+O (or the new /models command) opens the model menu. With a remote
provider it fetches that provider's live catalog from its open /models
route — no API key — sorted by id:
- type to filter (
qwen,coder,5.4),Backspaceedits the filter,
Escclears it, then closes the window; Enterswitches the session to the chosen model and rebuilds the engine
(session-only; setup → apply persists it);- a failed fetch keeps its error on screen — an unreachable Ollama and a
missing key look very different.
With the local provider the menu still lists .gguf files: install a
recommended model or switch the loaded one.
TUI: three modes, a palette and a real terminal
Shift+Tabcycles ai → help → terminal,/modeopens the list to
pick from; the numeric/1/2/3shortcuts are gone.Ctrl+Popens the command palette: every command, mode, the setup and
the settings screens, filter by typing. Long lists scroll with the
selection.F1andCtrl+Qwork from any screen.- Terminal mode runs inside the app window: a pty (
creack/ptyon
unix, ConPTY on Windows) painted by a small screen emulator
(internal/vt), so colours, resize and full-screen programs work while
dmsh keeps its status line.Shift+Tabcloses the shell and returns to
the prompt. - In help mode
run_commandis absent from the tool schemas entirely — a
tool the model can see will be called. - Background commands no longer freeze the TUI.
Fixed
- The model catalog never loaded.
Ctrl+Owith a remote provider sat
on "loading the model list…" forever: the fetch wrote its result into a
channel that nothing read, and bubbletea only delivers what a command
returns. The result is returned directly now, and a regression test
drives the real fetch →Updatepath. /todolooked empty. The tool's result went only to the model, so
the transcript showed a blank line and a bare[tool] todomarker. The
first line of the result (added [1] …,open [1] …, or the error) is
now printed under the marker, tasks are stored as a single line (a
multi-line task used to inject blank rows), and the rendered status is
no longer duplicated.- Provider/model selection unified. One rule answers "which provider is
live now" everywhere (currentProvider: session → its config → shell
config →auto), one rule answers "is it remote" (showsRemoteProvider:
autowith a local GGUF is local — same answer in/model, the status
line and the model menu), and/modelprints one shared text in both the
TUI and the REPL. The setup screen deliberately still edits the config
value, soautodoes not silently turn into a concrete provider just by
opening the window.
Full Changelog: v0.5.0...v0.5.1
Full Changelog: v0.5.0...v0.5.1
v0.5.0
dmsh v0.5.0 — remote provider, tool calling, working clarifications
Two new capabilities and one bug fix that made multi-step requests unusable.
What's new
Providers: local model or Pollinations
dmsh could only run a local GGUF through llama.cpp. Now the inference
source is a setting:
| Provider | Behaviour |
|---|---|
auto (default) |
local GGUF if one is found, otherwise Pollinations |
local |
local GGUF only; fails with a hint if none is present |
pollinations |
Pollinations API; local models are ignored |
dmsh --provider auto "what's eating my disk?" # local if present
dmsh config set provider pollinations # always remote
dmsh --remote-model mistral "..." # another remote model
dmsh --search-model gemini-search "..." # model behind websearch
dmsh --remote-base-url http://localhost:8080/v1 "..." # any OpenAI-compatible endpoint- Anonymous by design. dmsh sends no tokens and adds no
Authorization
header — Pollinations works without an account. - No silent fallback. The provider is resolved once, at session start.
Withauto, a missing GGUF switches to Pollinations and says so; a local
model that fails to load is never quietly replaced. /modelshows the active provider, model, endpoint, search model and
whether tools are on.- Rate limits are explained instead of dumped raw:
429now reads
"anonymous access allows one request at a time", and402/403points at
--remote-base-url/--remote-modelinstead of showing provider JSON.
Tool calling (function calling)
With a remote provider the model can call tools before answering:
| Tool | What it does |
|---|---|
run_command |
run one shell command, return exit code, stdout and stderr |
read_file |
read a UTF-8 text file (truncated at 8 KB) |
list_dir |
list directory entries with size and mtime |
system_info |
OS, arch, CPU count, shell, cwd |
todo |
keep a checklist of the current task (add / list / done / clear) |
ask |
ask the user one focused question and wait for the answer |
websearch |
search the web through the provider's search model |
Safety is unchanged: the loop is bounded (12 steps) and run_command goes
through exactly the same path as a normal answer — denylist → allowlist →
confirmation (unless --yes) → audit log. In --dry-run tools refuse to
execute commands and the model is told to return the command in its JSON
answer instead. ask never blocks where it cannot: in the TUI, or when
stdin went into the prompt, the model degrades to ask_clarification.
Disable everything with --no-tools or dmsh config set tools false.
Session & UX
/todoshows the checklist the model keeps (up to 50 items, session
scope);/todo cleardrops it.- Clarification answers now go back to the model together with the question
they answer (see below). /modelin the TUI reports the provider as well, not just the file name.- The status line shows
model:pollinations:openaifor remote sessions.
Fixed
- Clarification loop — the follow-up used to be sent as
request\nanswer, so the model never saw the question it had asked and
kept re-asking the same thing forever. Now every exchange is sent back as
an explicit block, a repeated question ends the dialogue with an
explanation instead of a second prompt, and two rounds is the hard limit. - In the TUI the clarification question is written to the transcript (it used
to vanish as soon as the answer was typed), and the answer is echoed while
the model receives the framing block. - Answers like
1. project-namereach the model asproject-name, while
versions such as3.5are left alone.
CI
- Windows CUDA release builds again: MSVC via Ninja, plain
clang(MSVC
ABI) for cgo, short 8.3 paths for-Lflags,-lflags for CUDA import
libs, andlldfor linking. - Added a fast cgo toolchain probe so a broken toolchain fails in ~1 minute
instead of after a long build. - CUDA failures no longer block the CPU release.
Note: v0.4.0 was tagged but never published as a release — skip it and
upgrade straight from v0.3.7.
Full Changelog: v0.3.7...v0.5.0
Full Changelog: v0.4.0...v0.5.0
v0.4.0
v0.3.7
What's new
Safety & accountability
- Audit log — every executed command is written to
audit.jsonl(timestamp, source, risk, policy decision, exit code). View it withdmsh auditor/audit(add--jsonfor raw lines). - Allowlist — mark trusted commands (
allowlist: ["git status"]) so they are always treated as low-risk and never trigger confirmation. --preview— review the command with its options highlighted plus an explicit y/N confirmation before it runs.--yes— auto-approve confirmations, handy for scripting.- Config validation — invalid
mode, negative values, out-of-rangetemperature/top_pand broken regex are now rejected at startup instead of being silently applied. - Defensive dry-run — the execution path can no longer run commands while
dry-runis active, no matter which code path calls it.
Model integration
- Prompts now use the model's own chat template via
llama_chat_apply_template, with a ChatML fallback — broader compatibility with non-ChatML models.
Session & UX
resume_session— persists the multi-turn dialogue context across restarts.- Stderr fed back into auto-correction is truncated (4 KB) to protect the model's context window.
- Updated banner and help text (
/audit,--preview,--yes).
Packaging
Releases now ship as:
- Debian/Ubuntu
.deb - RPM
.rpm - Arch Linux
.pkg.tar.zst(pacman) - FreeBSD tarball
- Linux and macOS tarballs (amd64 + arm64)
- Windows executable
CI
- Fixed the test, lint and release pipelines.
- macOS amd64 is now cross-built on Apple Silicon runners; retired Intel
macos-13runners are no longer used.
Full Changelog: v0.3.6...v0.3.7
v0.3.1
dmsh v0.3.1 — Bubble Tea TUI, scrollback, ESC cancel
Full REPL rewrite on Bubble Tea TUI.
What's new:
- Full-screen TUI with scrollback: ↑/↓ line by line, PgUp/PgDn page by page
- Live streaming of model response with persistent [dmsh] thinking... indicator
- Visual separators before command execution and auto-correction stream
- F1 / /help — concise help for commands and keys
- Esc / Ctrl+C — cancels streaming and returns to prompt
- Cursor hidden during thinking to avoid blinking
- Updated banner and status bar (help F1)
Fixes:
- Commands now execute when model returns intent: explain or ask_clarification with a filled command
- ask_clarification without a question no longer blocks the execution path
Build:
make llama && make build
v0.2.6
nlsh v0.2.5
nlsh-beta1
v0.1.3 Fix: force add cmd/nlsh to git (was ignored by *.exe pattern)