Skip to content

Learn from typing to personalise word prediction - #1030

Merged
enaboapps merged 11 commits into
mainfrom
claude/1029-learn-from-typing
Oct 12, 2026
Merged

enaboapps merged 11 commits into
mainfrom
claude/1029-learn-from-typing

Conversation

@enaboapps

@enaboapps enaboapps commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1029

Word prediction now learns from what the person types with the scanning keyboard, so their own words, names and phrases are suggested sooner.

What changes

  • Setting. Adds Learn from my typing under Scanning › Keyboard › Suggestions, on by default.

    • It is stored in AppSettings beside autoApproveAccountDevices. It is per computer, excluded from synced settings, and the synced schema is unchanged.
    • Forget learned words deletes what was learned, after a confirmation step.
  • Where it is stored. The isolated prediction worker opens prediction/personal.sqlite in this computer's app config directory and passes it to switchify-prediction.

    • If the file can't be opened, prediction keeps working without learning.
  • What is learned. Only the existing prediction buffer is learned from, which is successful Switchify keyboard input:

    • A sentence is learned once, when the next one begins, so a fix just after the punctuation is learned corrected. Backspacing into learned text relearns that word whole.
    • Enter/Tab learns everything typed so far. The keyboard now queues a private Edit::End, which keeps the last word, instead of a Reset.
    • Other context loss learns only the completed words, not the word in progress.
    • Text about to be clipped from the 512-character buffer has its completed words learned first.
  • Changing the setting bumps a learning generation, so the running worker and any spare are replaced at the next keyboard update.

  • Forget sets a pending flag, replaces any worker holding the file, and deletes the file plus its -journal, -wal and -shm. It finishes as soon as no worker holds them: immediately, on stop(), or before the next worker starts. No worker reopens the file while the delete is pending.

  • Library pin. switchify-prediction is pinned to Make learned words count, boundedly, without a second baseline copy switchify-prediction#30 (stacked on feat: redesign desktop setup UI #28):

    • Incremental learning: about 8 ms per sentence instead of about 190 ms.
    • Bounded weighting: one learned use counts as up to 500 built-in uses, less as more is learned.
    • Typo protection: a new or rare word counts once learned twice, so a single typo is never suggested.
    • Results on a synthetic person: learned words reach the suggestions for 46% of queries instead of 1%, and no misspelling was suggested.
    • Memory: the library no longer copies the English model, so the prediction worker's peak memory falls from about 362 MiB to 134 MiB.

    The worker release assets (v0.2.1) are unchanged, and library_revision was updated to match.

  • AI slots. The AI slots don't learn themselves. They exclude slots 1–3, so they still offer different words.

  • Docs. word-prediction.md gains a Learning from typing section. The neural, six-slot and keyboard docs are updated, and so is the settings note, which said typing "is not used for learning".

Typed text is never logged or synced. The file holds counts, not a transcript, but it is unencrypted, and the settings note says it can include names or passwords.

Validation

All checks from AGENTS.md pass: npm run prediction-model, lint, test, build, cargo fmt --check, cargo clippy --all-targets -D warnings, and cargo test (754 + 7 tests).

New tests, all using fake adapters with no desktop input:

  • Worker: a sentence is learned once when the next begins; a correction after the punctuation is learned corrected; End keeps the last word; lost context skips the word in progress; clipped text is learned in whole words.
  • Model: a real SQLite personal file ranks learned words, persists to the next worker, leaves the baseline byte-identical, and learns nothing with learning off.
  • Main process: Enter/Tab queue End; a spare started for another personal file isn't adopted; closing passes the personal file to the spare; Forget deletes the file and its journals, only when asked.
  • Settings: learnWordPrediction defaults to true for stored settings, is excluded from the synced document, and survives an incoming sync.
  • UI: the toggle saves app settings, not the scan config, and Forget calls the backend only after confirmation.

The new tests originally started enough PowerShell fake workers to starve cancellation_kills_and_reaps_a_blocked_worker after a rebuild. They now start only what they need, and the suite passes on repeated runs straight after a rebuild. One unrelated account-sync UI test flaked once during a concurrent build and passed on three reruns.

Manual check still to do: with signed builds (npm run macos:run on macOS), type sentences and check that learned words rank higher after reopening the keyboard. Then use Forget and check the file is gone.

Note: #1026 (docs) edits some of the same doc lines. Whichever merges second needs a small rebase.

🤖 Generated with Claude Code

A per-computer Learn from my typing setting, on by default and outside the
synced schema, lets the isolated prediction worker open a personal SQLite file
in this computer's app data. The worker learns each completed sentence once,
when the next begins, so a correction after the punctuation is learned
corrected. Enter or Tab learns the text so far through a new private End edit.
Other context loss learns the completed words but not one in progress. Only
verified Switchify keyboard input, the existing prediction buffer, is learned.

Changing the setting replaces the worker at the next keyboard update. Forget
learned words replaces any worker holding the file and deletes it and its
journals, finishing once no worker holds it and before any worker reopens it.
A personal file that cannot be opened leaves prediction working unlearned.

switchify-prediction is pinned to incremental learning (about 9 ms per
sentence instead of about 190 ms). Worker release assets are unchanged.

Closes #1029

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@enaboapps enaboapps added this to the v1.0.0-rc.24 milestone Oct 12, 2026
OwenMcGirr and others added 5 commits October 12, 2026 13:18
Forget learned words now records the request on disk and kills the spare at
once. A spare started while forgetting, or after learning changed, never
opens the personal file. Deletion finishes once no worker holds it, and a
restart finishes it before any worker starts. The page says whether the
words are gone. The pending request is main-thread state, like the workers.

Replacing a worker after learning changed fails a suggestion being accepted,
as a missed deadline does, so the keyboard never waits on the old worker.

A full buffer is learned in long pieces up to a word boundary 256 characters
from the end, rather than word by word, keeping phrases and leaving recent
words correctable. Word boundaries are tested by grapheme, so a combining
accent stays with its letter.

Refs #1029

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deleting an open file succeeds on macOS, so Forget only deletes when no
keyboard worker has the personal file; otherwise the worker is replaced at
its next update and the deletion finishes then. A request left by an earlier
run finishes at startup. The learning generation, like the forgetting state,
is main-thread state, since settings are saved and workers run there.

Refs #1029

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each Windows fake worker is a PowerShell process. The new tests started
eight, enough to starve the kill-and-reap timing test after a rebuild. Tests
that only need an absent or refused worker no longer start one.

Refs #1029

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
switchifyapp/switchify-prediction#30 keeps learned counts apart from the
baseline. One learned use counts as up to 500 baseline uses, less as more is
learned, and a word the baseline lacks or has seen fewer than three times
counts once learned twice. On a synthetic person, learned words reach the
suggestions for 46% of queries instead of 1%, with no misspelling suggested.
The library no longer copies the English model, so the prediction worker's
peak memory falls from about 362 MiB to 134 MiB. Worker assets are unchanged.

Refs #1029

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #1029

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@enaboapps
enaboapps marked this pull request as ready for review October 12, 2026 16:49
@enaboapps

Copy link
Copy Markdown
Contributor Author

Pins switchify-prediction e5223aa (#30). #30's final head b1904a9 differs only in docs, so the code is identical. Re-pin to the merged main commit if #28 and #30 are squash-merged.

OwenMcGirr and others added 4 commits October 12, 2026 18:14
…m-typing

# Conflicts:
#	docs/neural-prediction.md
#	docs/qwerty-keyboard.md
#	docs/word-prediction.md
…m-typing

# Conflicts:
#	src/settings/ScannerPreferences.tsx
Refs #1029

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #1029

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@enaboapps
enaboapps merged commit 3c80399 into main Oct 12, 2026
6 checks passed
@enaboapps
enaboapps deleted the claude/1029-learn-from-typing branch October 12, 2026 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Learn from typing to personalise word prediction

2 participants