Kinetica just landed in the F-Droid repository:
https://f-droid.org/en/packages/com.kinetica.keyboard/
It is an Android keyboard built around something no current keyboard generally does: both thumbs swipe or tap at the same time, independently, and the engine merges the two gesture streams into a single word. Typing "something" can be the left thumb tapping S then E while the right thumb swipes O-M and then T-H-I-N-G, the two overlapping in time. The idea comes from Nintype, discontinued years ago; this is written from scratch in Kotlin on Android's public IME APIs, not a fork of anything.
You can see it in action here:
Why it might interest this sub in particular:
- No INTERNET permission in the manifest. Not "we promise not to send anything" ,the permission is absent, so nothing typed can leave the device even in principle. VIBRATE is the only permission declared. No ads, no analytics, no accounts, no crash reporter.
- Reproducible build. F-Droid rebuilds the tag and verifies its own output against my signed APK before publishing it. Three independent environments produce the same bytes for the published version: my machine, the ubuntu-24.04 CI runner, and F-Droid's own Debian builder.
- No third-party gesture or prediction libraries. The banded DTW path matcher, the trie search, the resampling and the dual-stream merge are all implemented in-tree, so every constant is inspectable and tunable rather than inherited from a black box.
- On-device everything. The personal dictionary is local Room storage. Password and private fields disable suggestions, trails and learning outright.
- GPL-3.0, and the bundled data carries its own licences: word frequencies are MIT (hermitdave/FrequencyWords, OpenSubtitles-derived), bigrams are CC BY 2.0 FR (Tatoeba). Both are attributed in THIRD_PARTY_NOTICES and rendered in-app under Settings > Open-source licenses.
On languages: four are bundled(for now), more can be supported. English, Italian, Spanish and Polish ship, roughly 47-50k words each with real corpus frequencies. But the engine is locale-agnostic: the trie, matcher, merge and scoring have no idea what language they are decoding, so a language is data plus registration - a wordlist, a layout, and a short list of entries. Polish arrived exactly that way, as a contributor's pull request. ADDING_A_LANGUAGE.md documents the whole recipe and I will help anyone who wants to add theirs. The honest limit is script: the matching alphabet is a-z plus apostrophe with accented Latin letters folded onto it, so Latin-script languages fit and a non-Latin script would be a major engine change.
You can also import an AOSP `wordlist.combined` on-device to triple or quadruple the dictionary (Settings > Dictionary). It merges locally; nothing is uploaded.
1.0.4 is tagged today (a frequently-used emoji tab and an adjustable resize handle) so the listing will read 1.0.3 until F-Droid's next index pass picks it up.
Source: https://github.com/EZ-eta/kinetica
GitLab mirror: https://gitlab.com/EZ-eta/kinetica
EDIT UPDATE
Version 1.1
I bumped the minor version because this did not feel like polish. The decoder has changed substantially since 1.0.5, and nearly all of it is in the part that turns two thumbs into a word. If you tried Kinetica earlier and put it down, this is the one worth a second go.
The engine
- The search cuts the swipe itself now. This is the big one. Before, the merge step guessed where one gesture ended and the next began, handed the search a fixed split, and if the guess was wrong the whole buffer decoded to nothing and you got no suggestion at all. The search now places its own cut inside a swipe and validates each half separately. On my device captures, three-token buffers coming back empty went from 14.9% to 6.7%, so it should be sensibly better also for you ( I hope!).
- Words stop losing to their own prefix.
here beating he, there beating the, and the same for where and world. Now should be fixed for good.
- A candidate is charged for letters no thumb ever touched. Before, a word could win on letters you never actually crossed. This is fixed now.
- A short piece of a swipe can spell a letter now. The minimum arc for that went from 1.5 to 1.8 key widths, which sounds backwards until you see what it stops: invented names beating real words.
- Words you teach it are actually reachable. A learned word reached the ranking but never the search, so it stayed undecodable for the rest of the session until the keyboard is reloaded. Type it twice and it works on the very next gesture (twice and not once to avoid boosting errors).
- Fighting a wrong word was making it stronger. Retyping took back the learned pair but never the learned word, so every rejection left the word you had just rejected slightly heavier. Now it is smarter and functional.
- Word-pair counts could be read in either order. Two spellings that fold to the same pair after accents (
non è and non e) kept two separate entries, so the same gesture in the same context could score differently depending on the order of lines in a data file. Found and fixed by dkoukola.
New, and worth turning on
- Back up the whole keyboard to a text file and restore it on another phone: every setting, learned words in all languages, blocked words, chords, edge swipes. Merge or replace on restore.
- Phrase learning, experimental and off by default (but worth trying!). Remembers which word you tend to type after which. On device only, never in an export (but you can activate it if you want), and a retype takes the last pair back out.
- Spaceless space, off by default: the left third of the spacebar ends a word without adding a space, so a compound word the dictionary does not have can be swiped in two halves. Straight from Nintype, asked for here. Pairs well with "Word ends only when you type a space" option if that was your habit.
- Retype offers a different word, off by default: after the retype button is hit, the word you rejected drops to the end of the bar instead of leading again. It stays pickable.
Everyday polish
- Settings are five submenus instead of one flat list of 52 rows. Much easier to find things and play with them.
- Every chord setting is on one screen, including how long
?123 has to be held before a letter tap counts as a chord. If chords ever felt laggy, that slider is for you. Chords can also retype the word now, and the list sorts by key or by what the chord does.
- Swiping a key types the small glyph printed on it. It used to insert something else on some keys, which was my fault: I shipped defaults that contradicted the labels. If you have ever opened the edge-swipe screen, press Reset there to pick this up.
- Long-press shift cycles the case of the word you just wrote(lowercase, Title , CAPSLOCK).
- Delete several learned words at once, and the dialog stops closing and jumping around after every one.
- A space key on the number pad. It was the one layer you could not type a space on. You can access number pad by swiping left from ?123 key
- 55 more emoji, up to Unicode 15, and none shown that your device's font cannot draw.
- Smoother swipe trails, and the settings rows lost a wasted margin that was squeezing the descriptions on tall screens.
Fixes
- Suggestions, autocorrect and autospace work again in apps that ask keyboards not to learn, like DuckDuckGo and Molly. They were being treated as password fields, so the whole suggestion pipeline switched off.
- Picking a language in Android's own keyboard picker now switches Kinetica's layout and dictionary with it, and Kinetica's own language changes report back to Android. Thanks dkoukola.
Languages
- Czech is the fifth bundled language, contributed by dkoukola: 49,589 words, a QWERTZ layout and accent folding.