lx turns plain-English task descriptions into ready-to-use Linux commands, powered entirely by a local LLM (via Ollama), so it's private, free, and works offline. It never runs anything automatically: you always stay in control.
What would you like to do? find every pdf larger than 50mb
⠋ Thinking...
Command: find . -type f -name "*.pdf" -size +50M
Explanation: This command recursively searches the current directory and its
subdirectories for files that match the PDF extension and are
larger than 50 megabytes.
Risk: LOW
Copy command to clipboard? [y/N]
I don't want to memorise every Linux command flag, and I don't want an AI agent auto-executing commands on my machine without me reviewing them first. lx is a small, focused tool built around one idea: an LLM is great at generating a command from a description, but a human should always be the one who decides whether to run it.
- 100% local, no cloud APIs. Everything runs through Ollama on your own machine, so nothing is sent anywhere, and there's no API cost.
- Never auto-executes.
lxonly displays a command, an explanation, and a risk level. Copying it to your clipboard is the only optional action it takes, and only with explicit confirmation. - Structured, reliable output. The LLM is prompted to return strict JSON (
command,explanation,risk), with a worked example included in the prompt (few-shot prompting) to improve reliability on trickier tasks. Since small local models don't always follow formatting instructions perfectly,lxalso includes a JSON-repair step (for common escaping mistakes), Ollama'sformat: jsonconstrained decoding, and automatic retry logic if parsing still fails. - A syntax-check safety net. Before displaying a generated command,
lxruns a dry-run bash parse (bash -n, nothing is executed) and shows a warning if the command fails basic syntax validation. - Risk labelling. Every generated command is labelled
low,medium, orhighrisk, and colour-coded in the terminal (green/yellow/red), so dangerous commands are visually distinct before you ever consider running them. - Streamed under the hood. Responses are read from Ollama as a stream of chunks rather than one blocking call, with a live animated status indicator while the model works. The final result is still shown all at once (not word-by-word), since a partially-generated command or JSON fragment isn't meaningful or safe to display mid-stream.
- Model choice, your call. On startup,
lxlists every model you've pulled locally via Ollama and lets you pick one interactively. Set theLX_MODELenvironment variable to skip the picker and always use a specific model. - Remembers your last model.
lxsaves your most recently used model to~/.config/lx/last_model, and offers it as a default (press Enter to accept) the next time you run it, without removing your ability to pick a different one. - Keeps a local history. Every completed request (task, model, command, risk, and syntax-check result) is appended to
~/.config/lx/history.log, one JSON object per line, purely for your own reference. - Tested and CI-checked. Core logic (JSON parsing/repair, input validation, display rendering, clipboard behaviour) has unit tests, run automatically via GitHub Actions on every push.
- Linux (developed and tested on CachyOS/Arch)
- Python 3.11+
- Ollama installed and running, with at least one model pulled (e.g.
ollama pull gemma4:e4b) - For clipboard support: a clipboard tool available to
pyperclip: on Wayland,wl-clipboard(provideswl-copy); on X11,xcliporxsel
Recommended, install as a standalone command available in any terminal:
git clone https://github.com/havl-code/lx.git
cd lx
pipx install --editable .
ollama pull gemma4:e4b # or any model you preferAlternatively, for development (running tests, editing dependencies), use a virtual environment instead:
git clone https://github.com/havl-code/lx.git
cd lx
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
pip install -e .
ollama pull gemma4:e4blxYou'll be shown a list of your locally available Ollama models to choose from, with your last-used model marked and offered as the default (press Enter to accept it), then prompted for a task in plain English. lx will show the generated command, an explanation, and a risk level, then ask if you'd like to copy the command to your clipboard. It will never run the command for you.
To skip the model picker and always use a specific model:
LX_MODEL=gemma4:e4b lxOther flags:
lx --version # show the installed version
lx --help # show usage informationInstall with dev dependencies (adds pytest and matplotlib):
pip install -e ".[dev]"Run the test suite:
pytestTests cover JSON parsing/repair logic, CLI input validation, display rendering (including a regression test for a real markup-escaping bug and the syntax-check warning), clipboard behaviour, and the last-used-model config, and run automatically on every push via GitHub Actions (see the badge above).
scripts/benchmark.py times a fixed set of tasks against every locally pulled Ollama model, checks JSON-parsing reliability and basic command syntax validity, and generates a comparison chart. See BENCHMARKS.md for results and findings from testing on this project's development hardware, including a follow-up investigation into few-shot prompting and syntax checking as reliability improvements.
python scripts/benchmark.py- Small local models (3B to 8B class) don't always produce perfectly formed JSON.
lxmitigates this with a repair step, retry logic, few-shot prompting, and Ollama'sformat: jsonconstraint, but it isn't foolproof: occasional failures are still possible, especially for tasks requiring nested shell quoting (e.g. a command that itself needs both single and double quotes). See BENCHMARKS.md for documented examples. - Valid JSON doesn't guarantee a correct or safe shell command; benchmarking surfaced real cases of syntactically broken or semantically incorrect commands, in some cases labelled "low risk". Always read the command and explanation yourself before running anything.
- Risk classification is entirely the LLM's judgement based on prompt guidance, and can vary between runs for similar commands. It's a helpful signal, not a guarantee.
lxis only available in terminals where it's been installed (viapipxor an activated venv), see Setup above.- Generated commands are checked for basic bash syntax validity (via
bash -n) before being shown, and a warning is displayed if a command fails this check. This catches bash grammar errors (e.g. unbalanced quotes) but not command-specific argument errors (e.g. a missing required argument tofind -exec), see BENCHMARKS.md for a real example of each. ~/.config/lx/last_modeland~/.config/lx/history.logare plain local files with no encryption; history includes the plain-English tasks you've typed and the commands generated, treat this the same as shell history.
- Package for proper installation (
pip install -e .,lxas a console command) - Add automated tests for core logic
- Add CI (GitHub Actions) to run tests on every push
- Stream responses from Ollama instead of waiting for the full response
- Interactive model selection, with an
LX_MODELoverride - Benchmark alternative models for speed/accuracy tradeoffs on CPU-only hardware
- Installable system-wide via
pipx, without needing manual venv activation - Investigate whether smaller models can be made more reliable for nested-quoting tasks (few-shot prompting, plus a bash syntax-check safety net)
-
lx --version/lx --help - Remember and default to the last-used model
- Local command history log
Built with guidance from Claude (Anthropic), used as a mentor throughout development: explaining concepts, reviewing code, and helping diagnose real bugs along the way.
Released under the MIT Licence, see LICENSE.