RC RANDOM CHAOS

The best terminal assistant has no AI

TERMy is a terminal assistant that maps natural-language requests to shell commands deterministically, with no LLM, machine learning or embeddings.

· 4 min read
The best terminal assistant has no AI

TERMy turns “list files” into ls -lah and “create file test.txt” into an echo redirect, in milliseconds, on a CPU, with no LLM, no machine learning and no embeddings anywhere in it. The parser and NPC classes that do this come to roughly 1000 lines of code. The developer behind it, better known for the PJON network protocol that ETH Zurich recently implemented in silicon, says the parser is small enough to run on a microcontroller, and that the NPCs it drives will respond on hardware as modest as a Raspberry Pi Zero.

TERMy is the demonstrator for NPC-Forge, a framework, server and CLI whose functions are OpenAI API server management, NPC management, and diagnostics and testing. The path to it ran through two false starts, both of which are more instructive than the destination.

Two false starts

The developer spent two months on the problem, prompted by Copilot price increases, on a machine with 16GB of RAM, a GTX 1050 Ti with 4GB of VRAM and an i7-4790K. The first attempt was to train a transformer from scratch: a NanoGPT-style model of 100 to 200 million parameters, flash attention, the usual optimisations, and experiments with Mamba, trained on Project Gutenberg, open-source code and Huggingface datasets. The models looped, repeated themselves and rarely answered technical questions. A usable run would have needed a month of continuous training, which the author judged wasteful and useless.

The second attempt, “howto”, wrapped ollama and open-weight models in a harness whose pre-prompt forced the model to reply only with terminal commands. Models like ornith:9b, mistral:7b and cogito:14b managed it sometimes, but not fast or reliably enough for general use on 4GB of VRAM.

The third attempt dropped the models entirely, under three self-imposed constraints: no embeddings, no machine learning, no LLMs.

How the matching works

The design rests on a dataset format the author calls NDF 0.0. Each entry is a self-contained JSON object: a category, a list of input phrasings, the tool calls to run (in a VS Code-compatible shape), a permission level, and optional “thinking” strings. Teaching the assistant a new domain means writing a file of these objects, for example dataset_docker.json, and dropping it in the dataset directory. There is no training step.

Fixed phrasings are handled by listing them. Variable requests use templates. “create file test.txt” is matched against a structure of tagged slots: a concept tag like <||vocab_create||>, which expands to a synonym list (create, generate, craft, forge), an optional <||vocab_file||>, and a typed entity <||file||> whose value is pulled out with a regular expression ([\w\-]+\.[a-zA-Z0-9]{2,4} for filenames). Required and optional tags can share a position.

The matching pipeline, written as the FlintParser and FlintNPC classes in cross-compatible Python and JavaScript, runs cheapest-first, a habit the author traces to writing a compiler for their own BIPLAN language. It strips noise words (expletives, interjections, thanks), runs sentiment analysis, then tries exact match, then template match, and only then a slower probabilistic match. The probabilistic stage uses inverse document frequency to weight rare words, a bag-of-words step to tolerate word order, and an IDF-weighted Levenshtein distance to absorb typos.

The permission field, and what it doesn’t cover

The security story is the permission field on every entry. Destructive operations are set to "ask", and the author argues that forcing confirmation on anything potentially destructive makes the tool inherently safe, while conceding that implementation bugs and dataset bugs remain, as does ordinary human error.

The honest version is narrower. Determinism means a given input maps to a known command you can audit ahead of time, which is a real improvement over a model that might generate rm -rf under the wrong prompt. But the generated commands interpolate regex-extracted entities straight into a shell string (echo '' > '<||file||>' && termy_set_context ...), and the author already warns that TERMy sometimes emits command chains that will draw complaints. The filename regex is the only thing standing between an extracted entity and the shell, so the dataset’s regexes are effectively the input-validation layer, and they deserve to be read as such.

Where it fits

Against established NLU tooling the pitch is weight. Rasa and NLP.js lean on machine-learning classifiers and training pipelines; ChatScript is large and has a steep learning curve. NPC-Forge asks for none of that, trading model generalisation for a data format you edit by hand.

The author’s wider argument is architectural: harnesses like Copilot should answer trivial requests with a deterministic NPC and route to a heavy model only as a last resort, rather than spending tokens, compute and electricity on “activate the virtual environment”. They have wired TERMy into Copilot to take over a subset of the prompts previously sent to Claude, and expect deterministic agents behind a harness to become common.

It is an early release and the author is candid about it: a first Python project, two months old, not production-ready, with dataset and parser work still needed before the command chains are safe. For anyone evaluating it, that dataset is where both the capability and the risk live.

Share

Keep Reading

Latest on the Wire

Full wire →

New signal daily · RSS

Stay in the loop

New writing delivered when it's ready. No schedule, no spam.