TERMy deterministic terminal assistant – fast, LLM‑free command automation
TL;DR
TERMy is a fast, deterministic terminal assistant that converts natural‑language requests into shell commands without any embeddings, machine‑learning, or large language models, making it cheap, instant, and safe for low‑resource machines.
Why a non‑LLM terminal assistant matters
Traditional AI‑powered command assistants rely on large language models (LLMs) that consume significant GPU memory, incur token costs, and introduce latency. TERMy eliminates these drawbacks by using a rule‑based parser and a lightweight dataset format, enabling sub‑second responses on CPUs with as little as 4 GB VRAM.
Core design constraints
TERMy was built around three hard limits:
- No embeddings – the system does not store vector representations.
- No machine‑learning – inference is deterministic, not probabilistic.
- No LLMs – all processing runs on the host CPU. These constraints force a minimal, predictable implementation that can run on devices ranging from a laptop to a Raspberry Pi Zero.
NPC‑Forge Dataset Format (NDF 0.0)
The assistant reads a JSON‑based dataset where each entry defines:
- Category – logical grouping (e.g.,
linux_files). - Input phrases – natural‑language triggers.
- Tools – the shell command template to execute.
- Message – the textual response shown to the user.
- Thinking – optional diagnostic traces.
- Permission – safety flag (
"ask"for potentially destructive actions).
Example entry:
{
"category": "linux_files",
"input": ["list files", "list files and directories"],
"tools": [{
"name": "run_in_terminal",
"arguments": {
"command": "ls -lah",
"explanation": "Lists the files in the current directory.",
"goal": "Display current directory contents",
"mode": "sync"
}
}],
"message": "Done",
"thinking": ["That is quite simple!", "This is boring..."],
"permission": "yolo"
}
Adding new capabilities is as simple as dropping another JSON file (e.g., dataset_docker.json) into the dataset directory.
Template‑based intent parsing
To handle variable elements such as filenames, TERMy uses template intents. A template defines a sequence of tags, each representing a vocabulary set or a typed entity. Example for file creation:
{
"intent": "file_creation",
"category": "linux_files",
"type": "template",
"structure": [[
{"tag": "<||vocab_create||>", "type": "vocab", "required": true},
{"tag": "<||vocab_file||>", "type": "vocab", "required": false},
{"tag": "<||file||>", "type": "filename", "required": true}
]],
"message": "<||completion||>",
"tools": [{
"name": "run_in_terminal",
"arguments": {
"command": "echo '' > '<||file||>' && termy_set_context 'active_file' '<||file||>'",
"explanation": "Writes <||string||> in file <||file||>.",
"goal": "Directory Allocation",
"mode": "sync"
}
}],
"permission": "ask",
"thinking": ["Ok, I am asked to create the file <||file||>."]
}
Tag vocabularies are defined separately, e.g.,
{"<||vocab_create||>": ["create", "make", "generate", "craft", "forge"]}
Regular expressions extract typed entities such as filenames.
Safety through permission gating
Every dataset entry includes a permission field. By default, destructive commands are marked "ask", prompting the user for confirmation before execution. This simple rule dramatically reduces accidental damage while keeping the system fully deterministic.
Parsing pipeline (≈ 1000 LOC)
TERMy’s core consists of two cross‑language classes—FlintParser and FlintNPC—implemented in both Python and JavaScript. The processing steps are:
- Noise removal – strip expletives, interjections, and gratitude words.
- Sentiment analysis – a lightweight count of stripped tokens used only for tagging, not for command generation.
- Exact match – direct lookup of the input phrase.
- Template match – pattern matching with variable extraction.
- Probabilistic match – fallback using IDF‑weighted Bag‑of‑Words and Levenshtein distance to tolerate typos. The final step is optional and only invoked when earlier stages fail.
Performance and hardware footprint
Because the entire pipeline is rule‑based, TERMy responds in milliseconds on a modest laptop (i7‑4790K, 16 GB RAM, GTX 1050 Ti). No GPU is required, and the memory footprint stays well below 10 MB, making it suitable for embedded devices.
Community feedback highlights
- Nate B. linked to the nl2bash paper (arXiv 1802.08979), noting prior work on translating natural language to shell scripts.
- publlus_enigma praised the return to traditional NLP, emphasizing the simplified dependency stack.
- zserge likened the approach to an ELIZA‑style system but with a richer dataset format.
- superposition highlighted the token‑saving benefit for developers who currently burn tokens on LLM‑based shells.
- mbil suggested a hybrid model where TERMy falls back to an LLM for low‑confidence queries, automatically generating new dataset entries—a direction the author acknowledges as future work.
- dmos62 proposed a nightly self‑learning routine that converts executed commands into NPC‑Forge recipes, enabling the system to grow without external models.
- paguasmar and superposition both see TERMy as a “main model” that can offload repetitive tasks from costly LLM APIs.
Comparison with existing NLU frameworks
| Feature | TERMy | Rasa / NLP.js | ChatScript |
|---|---|---|---|
| Training data | Hand‑crafted JSON dataset | Supervised ML models | Script‑based rules |
| Runtime cost | CPU‑only, < 10 MB | Requires Python/Java runtime, optional GPU | Large C++ binary |
| Latency | Sub‑second | Seconds to minutes (model loading) | Variable |
| Extensibility | Add JSON files | Retrain models | Write new scripts |
| Safety | Permission flags, deterministic | Depends on model confidence | Manual safety checks |
Integration with GitHub Copilot
The author wired TERMy into VS Code as a Copilot‑style harness. When a user types a natural‑language command, TERMy instantly returns the appropriate shell snippet, bypassing token‑based LLM calls. This demonstrates a practical workflow where deterministic agents handle routine tasks while heavyweight LLMs are reserved for complex, creative queries.
Future directions
- Self‑learning – nightly analysis of executed commands to auto‑generate new dataset entries.
- Hybrid confidence routing – delegate low‑confidence requests to an LLM, then ingest the generated command into the deterministic dataset.
- Broader device support – porting to micro‑controllers and IoT devices for truly ubiquitous assistants.
- Community dataset expansion – shared repositories of domain‑specific JSON recipes (Docker, Kubernetes, Git, etc.).
Getting started
- Clone the NPC‑Forge repository.
- Install the Python or Node.js dependencies (standard library only).
- Populate
datasets/with JSON files following the NDF 0.0 schema. - Run
flintnpc(Python) orflintnpc.js(Node) to start the assistant. - Use the provided VS Code extension or invoke the CLI directly:
termy "list files".
Conclusion
TERMy proves that deterministic, rule‑based NLP can replace costly LLM calls for everyday terminal automation, delivering instant, low‑resource command generation while maintaining safety through explicit permission gating. Its open‑source dataset format invites community contributions, paving the way for a decentralized ecosystem of lightweight conversational agents.
Sources
Related
- Project
- Project
- Project
- Project
- Project