Repository navigation
Releases: annejan/local-llm-hotkeys
Release list
v0.3.0: answers in a chat window; translations that translate
Your laptop has an AI key? Make it do something, on your own NPU.
New
- Answers in a chat window. Explain (Ctrl+Copilot) and translate (Alt+Copilot, and Meta+Shift+Y for a screen region) now open the chat window instead of a text box. The answer appears while the model writes it (the first words after about 2 s), Esc stops it, and you can ask about the text: "what happens if I pay late?", "what does this word mean?". Answers to those questions come from the text; when the text does not say it, the answer says so. A translation shows exactly as written, line for line.
ELI12_WINDOW=0andUKTR_WINDOW=0keep the text box. - The Ai key icon for the chat window, instead of a question mark: the Ai on a key cap, readable on light and dark panels.
- A translation model per use:
UKTR_FILE_MODELfor documents (a slower, more careful model can do those) andDICTATE_MODELfordictate --translate(a fast one types sooner).
Fixed
- Translations that did not translate. With its old prompt, translategemma translated a Ukrainian news text into Portuguese, a Ukrainian sentence into Russian, and returned long Ukrainian texts (over about 1200 characters) untranslated. uktr now sends TranslateGemma's own prompt, at temperature 0. Measured on 8 texts in 8 languages into Dutch and English, every output read: 16 of 16 right, and long texts complete at every length.
- FastFlowLM stopped answering after 10 stopped answers (
ask failed: BrokenPipeError). That is a FastFlowLM bug (#680, up to at least 1.0.11): it never frees a connection whose client leaves while it writes. Stop, Esc, Ctrl+C and closing the window now end an answer in a way that the server can finish, so they no longer cause it. If another program causes it, the message says what to do:systemctl --user restart flm. - In the window, Stop works at once, also before the first word; a stopped translation is not copied; follow-up questions keep the text they are about.
ask --resumefilters control characters from saved chats; without PySide6's QtWidgets (split packages on Debian) the tools fall back to the text box.
Project
tests/injection.py: how often an instruction hidden in a text steers eli12 and uktr. All installed models compared in #5.- Reviews of the window and the FastFlowLM fix: #15, #17.
Update
cd local-llm-hotkeys && git pull && ./install.shinstall.sh installs the icon. The commands are links to the repository, so everything else comes with git pull.
Check the download
gh attestation verify local-llm-hotkeys-0.3.0.tar.gz -R annejan/local-llm-hotkeys
sha256sum -c SHA256SUMS
gpg --verify SHA256SUMS.asc SHA256SUMSv0.2.2: security review, round 2
Your laptop has an AI key. Make it do something, on your own NPU.
A second security review (#5), after #3 in v0.2.1. Nothing high or medium; the first item closes a hole in a v0.2.1 fix.
Fixed
askloads no local image file that the model names, also not through Qt's fallback. The v0.2.1 fix returned "not handled" for such an image, and Qt then loaded the file itself. Display only; checked this time by asking the document what it loaded.- Popups show the text as it is.
uktr clip,uktr shotandeli12 clipshow their result in a kdialog window, which rendered a line that starts with an HTML tag as rich text: a translated document could hide part of its own translation. - A link in an
askanswer is shown in encoded form (xn--…), as browsers do, so a host with look-alike letters is not mistaken for a known site. Bidi overrides and zero-width characters are removed from model output. dictate: a second hotkey press during start-up no longer kills the first dictation silently.- pdftotext, pandoc and tesseract are stopped after 600 s, with a message; their output is read as UTF-8.
- A broken saved chat file no longer takes the
askwindow down; chat-list tooltips are escaped;ask --resume ²gives a usage line. uktr FILEprints file names through the control-character filter;uktr listensurvives an odd-length audio block.install.shleaves a link of yours to another program alone.- CI checkouts keep no token.
Tested, not changed
A prompt guard against hidden instructions (the input between <text> tags with a "not addressed to you" rule, as fixtext has) was tested on the NPU with four hostile texts. It does not help qwen3.5:9b (5 of 12 followed without it, 6 of 12 with it) and makes translategemma drop lines, so the prompts stay as they are. tests/injection.py repeats that test after a model or prompt change. A hostile text can still steer an explanation; the README says so.
Update
cd local-llm-hotkeys && git pullCheck the download
gh attestation verify local-llm-hotkeys-0.2.2.tar.gz -R annejan/local-llm-hotkeys
sha256sum -c SHA256SUMS
gpg --verify SHA256SUMS.asc SHA256SUMSv0.2.1: security fixes
Your laptop has an AI key. Make it do something, on your own NPU.
This release has the fixes from a review of the whole code base (#3). The danger is a text, document, screenshot or audio from someone else: it goes to the model, and the model's output is written, shown, pasted or printed.
Fixed
uktr FILEand "Translate (uktr)" in Dolphin do not write through a link. A downloaded folder with a linkreport.nl.md→~/.bashrccould make the translation replace that file.- A link in an
askanswer opens only after you see the full address and click Yes. A web page in a screenshot could tell the model to write a link that sends your chat to someone else. Raw HTML in answers is not rendered any more. - Saved
askchats are readable only by you: the folder is 0700 and new chats are 0600. A folder from an older version is changed when the next chat is saved. - Control characters are removed from what the model and Whisper write, so a hostile text cannot send escape sequences to your terminal.
dictatetypes one line, so it cannot press Enter in a terminal. - Notifications show copied text and file names as text, not as markup.
dictatekeeps its pid file only in your runtime folder, and sends its stop signal only to a running dictate.install.shworks in a folder with a'in its name.- File names that start with
-work, and pandoc runs with--sandbox.
Documentation
- The README and
SECURITY.mdexplain the/dev/uinputudev rule. It is optional: without it,dictateleaves the text on the clipboard and you press Ctrl+V. On openSUSE, Fedora and Arch, KDE Connect and the Steam udev rules usually give the same access already. The README says what the rule allows and how to check it. - A hostile text can still make an explanation or a translation wrong; the README says so.
Update
cd local-llm-hotkeys && git pullThe commands are links to the repository, so git pull is enough.
Check the download
gh attestation verify local-llm-hotkeys-0.2.1.tar.gz -R annejan/local-llm-hotkeys
sha256sum -c SHA256SUMS
gpg --verify SHA256SUMS.asc SHA256SUMSv0.2.0: dictate and translate, explain a screen region
Your laptop has an AI key. Make it do something, on your own NPU.
New
- Dictate and translate (Meta+Ctrl+Shift+D): speak your language, and the text is typed in English (or
DICTATE_TO). Whisper and the translation model both run on the NPU. Handy for an email or a chat with someone who does not read your language. - Explain a screen region (Meta+Shift+X): drag a rectangle around an error message or a part of a window, and the chat explains it. Ask follow-up questions as usual.
- Explain the active window now also has a Meta+Shift key: Meta+Shift+W, next to Ctrl+Alt+Copilot.
- Stop works at once in the chat: Stop and Esc end an answer immediately, also while the model is still loading or before the first word.
Better
- The README explains when one model for everything (
UKTR_MODEL=qwen3.5:9b) is worth it: we compared it with translategemma on Ukrainian, German and Russian. It avoids the ~5 s model switch, but translates no better and about twice as slowly. - The README has the upstream status of the Copilot key: Qt 6.13 adds
Qt::Key_Assistant; KWin and the KDE shortcut recorder each still need a small change (KDE bug 502639). Until then, the key map inkde/xkb/(installed byinstall.sh) makes the key work.
Project
- CI on every push: unit tests on Python 3.9 to 3.13, ruff, shellcheck, desktop-file-validate, and a check that every package name
install.shprints exists on openSUSE Tumbleweed, Debian 13, Ubuntu 26.04, Fedora and Arch. - Signed releases: the tag is signed; the tarball and
SHA256SUMSare built and attested by GitHub Actions, andSHA256SUMSis signed with the maintainer's OpenPGP key. See "Check a release download" in the README. SECURITY.mdwith private reporting,CONTRIBUTING.md, issue and pull request templates, Dependabot, CodeQL.
Update
cd local-llm-hotkeys && git pull && ./install.shinstall.sh adds the two new hotkeys. KDE keeps keys you changed yourself.
Check the download
gh attestation verify local-llm-hotkeys-0.2.0.tar.gz -R annejan/local-llm-hotkeys
sha256sum -c SHA256SUMS
gpg --verify SHA256SUMS.asc SHA256SUMSv0.1.0: your AI key, on your own NPU
Your laptop has an AI key. Make it do something, on your own NPU.
The first release. New laptops have a Copilot key that does nothing on Linux. local-llm-hotkeys gives it four jobs on KDE Plasma, and runs all of them on the AMD Ryzen AI NPU in the laptop (FastFlowLM). There is no cloud and no account; nothing leaves your computer, and it works offline.
| Press | You get |
|---|---|
| Copilot | a chat window, with follow-up questions and saved chats |
| Alt+Copilot | the copied text, translated to your language |
| Ctrl+Copilot | the copied text explained in a few plain sentences, with a to-do list |
| Ctrl+Alt+Copilot | the window in front of you explained ("what is this error?") |
Every action also has a Meta+Shift shortcut, for keyboards without a Copilot key.
What is in it
- uktr: translate the clipboard, a screen region (OCR), documents (PDF, epub, docx, odt, html), or live subtitles for system audio.
- eli12: explain a text like you are 12, in your language, with a to-do line for messages that ask you to do something.
- fixtext: fix spelling and grammar of the clipboard (Meta+Shift+F).
- ask: a chat window with streaming answers, history, saved chats, and screenshots of the active window.
- dictate: speak, and the text is typed into the active window (Meta+Shift+D).
- Dolphin menu: "Translate" and "Explain like I'm 12" for documents.
- Everything answers in your language: the desktop language, or
UKTR_LANGUAGE.
Install
git clone https://github.com/annejan/local-llm-hotkeys.git
cd local-llm-hotkeys
./install.shinstall.sh needs no root. It checks the packages and prints the install command for openSUSE, Debian/Ubuntu, Fedora or Arch, links the commands, installs the hotkeys, the Dolphin menu and the Copilot key map, and checks the model server and models. See the README for FastFlowLM and the models.
Requirements
- KDE Plasma 6 on Wayland, Python 3.9+
- FastFlowLM on an AMD Ryzen AI 300 NPU (XDNA2), or ollama on a GPU/CPU
- Models:
translategemma:4b,hy-mt2-flash:1.8b,whisper-v3:turbo,qwen3.5:9b
Tested
- Daily use on a ThinkPad T14 Gen 6 (Ryzen AI 7 PRO 350) with openSUSE Tumbleweed and Plasma 6.8.
- The installer in containers: package names resolve on Debian 13, Ubuntu 26.04, Fedora 44 and Arch; a full install on Debian 13. Unit tests pass on Python 3.9 to 3.13.
- Not tested yet: the hotkeys on a Plasma desktop of another distribution, and Plasma 5.
Known limits
- The Copilot key needs the key map in
kde/xkb/(the installer adds it) and a new login: recent keyboard maps turn the key intoXF86Assistant, which KDE cannot bind. - FastFlowLM keeps one language model loaded; switching between translate and chat costs a few seconds.
- The models are small (4B and 9B). Translations are rough, and answers can be wrong; check facts that matter.