A physical-keyboard kit for KOReader. One plugin, four features:
- Key remap — Vim-ish global shortcuts (menu, paging, ToC, search, …).
- Command palette — fuzzy search across the entire upper menu (
P). - Word search — fuzzy picker over words visible on the current page (
Shift+D). - Visel — vim-style visual sentence / word selection on EPUB (
Shift+V).
Designed for KOReader on devices with an external keyboard (Bluetooth or USB-C): Android phones, the Boox Palma, the Kobo Sage with a hardware keyboard accessory, the desktop emulator, etc.
Copy the keyreader.koplugin/ directory into KOReader's plugins/ folder:
git clone <repo-url> keyreader
cp -r keyreader/keyreader.koplugin ~/.config/koreader/plugins/
# Android: /sdcard/koreader/plugins/
# Kindle: /mnt/us/koreader/plugins/
# Kobo: /mnt/onboard/.adds/koreader/plugins/
# Desktop: ~/.config/koreader/plugins/Restart KOReader. Enable in Settings → Plugin management → Keyreader.
Vim-ish global shortcuts that fire in both the Reader and the File Manager. Handlers no-op while a text input is focused, so the letter flows through to whatever search/edit bar is open.
| Key | Action |
|---|---|
M |
Open upper menu |
. |
Next page |
, |
Previous page |
S |
Toggle status bar / footer |
T |
Table of contents |
F |
Full-text search |
D |
Dictionary lookup |
I |
Book info |
O |
Book map |
L |
Bookmark list |
B |
Toggle bookmark |
H |
History (recent books) |
U |
Back (follow link back) |
To customise the bindings, edit BINDINGS at the top of
keyreader.koplugin/keyremap.lua.
Press Shift+D in the Reader (EPUB / CRengine documents only) to open a
fuzzy picker over every unique word visible on the current page.
| Key | Action |
|---|---|
| any letter | Type into the filter |
↑ / ↓ |
Move selection |
↵ |
Look up selected word in dictionary |
Esc / Back |
Close without action |
All unique words from the page are collected, deduplicated, and sorted alphabetically. The right column shows hint markers:
| Marker | Meaning |
|---|---|
✗ |
Definitely not a headword (single char, digits, punctuation) |
? |
Possibly not a headword (two Unicode codepoints) |
| (none) | Normal word — lookup likely to produce results |
Markers are heuristic-only. The actual dictionary result always tells you for certain; the markers just help you skip obvious non-entries.
Press P to open a fuzzy palette over the entire upper menu — every
toggle, every submenu, every action. Tap to run, long-press to "walk me there"
(open the menu at that path and select the entry).
The fuzzy matcher scores against both the localised string and the English
msgid (via KOReader's gettext catalog), so you can type font even when
running a non-English UI.
Inside the palette:
| Key | Action |
|---|---|
| any letter | Type into the filter |
↑ / ↓ |
Move selection |
↵ |
Run the selected command |
| long-press | "Walk me there" — open the menu at that path |
Esc / Back |
Close palette |
The palette also registers a Dispatcher action named Command palette so you can bind it to any gesture or KOReader profile from Settings → Gestures.
Press Shift+V in the Reader (EPUB / CRengine documents only) to open a
modal visual selection overlay.
| Key | Action |
|---|---|
→ / J |
Extend selection by one sentence |
← / K |
Trim selection by one sentence (min: one) |
Tab |
Move whole selection forward (span preserved) |
Shift+Tab |
Move whole selection backward |
↓ |
First sentence of next paragraph |
↑ |
First sentence of previous paragraph |
Shift+W |
Drop into word mode (single sentence required) |
Shift+X |
Look up selection in dictionary |
Shift+Y |
Copy selection to clipboard |
Return / Esc / Back |
Close overlay |
If the visible page ends mid-sentence, extending past the bottom auto-pages forward and keeps the selection anchored.
| Key | Action |
|---|---|
→ / ← |
Extend / trim word selection |
Tab / Shift+Tab |
Move word selection forward / backward (wraps) |
↓ / ↑ |
Move to nearest word on the line below / above |
Shift+W |
Back to sentence mode |
Shift+X / Shift+Y |
Dict / copy (same as sentence mode) |
Visel requires:
- A rolling (CRengine) document — EPUB, FB2, HTML, plain text. PDF / MuPDF documents are not supported (different word-box API).
- A hardware keyboard. The overlay has no touch fallback.
- Key collisions: the global key remap fires the same letters even while
the Visel overlay is open (e.g.
Hopens History,Tjumps to the ToC). If you live in Visel a lot, drop those bindings fromkeyremap.lua. - Letter-typing into Reader fields: key remap handlers detect focused
text inputs and forward through, but only for widgets that follow the
standard
InputTextshape (a.focused = trueflag and a.charlistbuffer). Exotic dialogs may still swallow letters. - Tested on: KOReader 2024.04 and newer, on Android (Termux + hardware
keyboard), the desktop emulator, and the Boox Palma. Older KOReader builds
may be missing some of the events fired by key remap (
ShowBookMap,ShowRecentBooks).
keyreader.koplugin/
├── _meta.lua plugin manifest
├── main.lua umbrella plugin: instantiates all sub-controllers
├── keyremap.lua global Vim-ish shortcuts
├── palette.lua command-palette widget + entry point
├── wordsearch.lua word-search palette + entry point
└── visel/
├── controller.lua key handling + open/close
├── overlay.lua full-screen display widget (sentence/word picker)
└── wordsource.lua CRengine word/sentence collection
Each sub-controller is its own InputContainer instance and self-registers in
self.ui.active_widgets for global key handling. The umbrella plugin only
exists so the user sees a single entry in Plugin management.
MIT.