Generated from CHANGELOG.md. Packaged binaries are signed, checksummed, and attested by the release workflow; see each release for platform downloads.
Unreleased
Added
macOS: "Use F1–F12 as standard function keys" in the menu bar menu switches the function keys between standard F1–F12 and the printed brightness, volume and media actions, without opening System Settings. The change applies immediately, survives a restart, and the checkmark shows the current mode.
Planned
Notarized Developer ID distribution for macOS.
Broader Windows and Linux desktop validation.
Browser adapter and npm delivery for upyr-wasm.
v0.5.0
Per-layout switch tunes, a caret-side layout indicator, Backspace revert and
Security
Build wayland-scanner 0.31.11 from crates.io, which ships the quick-xml 0.41 fix for RUSTSEC-2026-0194 / RUSTSEC-2026-0195, and drop the vendored 0.31.10 backport and its [patch]. cargo install upyr no longer builds against the unpatched scanner, since a [patch] never applied to installs from crates.io.
Added
Each layout has its own switch tune, so you can tell by ear which layout you landed on without looking. A tune follows the layout's place in the Globe-key cycle, leaving out skipped layouts: the first rises, the second falls, then up-up, up-down, down-down and down-up, repeating after six. The pack changes only the voice (soft, bright or sparkle), never the tune. Anime Reactions now synthesizes these tunes as well; its recorded switch cue remains only for a layout outside the cycle. On Linux and Windows, English gets the first tune and Ukrainian the second. Previewing the layout-switch sound in Settings plays the active layout's tune.
macOS: the layout indicator appears next to the caret of the text being typed, in apps that expose the caret through Accessibility. The letters sit just below the caret line. The flag shrinks to the active layout's flag at half size, just after the caret and raised off the line like a superscript, so it covers neither the text before the caret nor the next line. Elsewhere the whole flag row stays near the bottom of the screen and the letters follow the pointer. upyr doctor reports what the focused app exposes.
upyr shell-init zsh|bash|fish: prompt widgets that convert the command line (Ctrl+X Ctrl+L) or the word before the cursor (Ctrl+X L; the active region in zsh) through upyr convert, preferring the installed layouts. The script calls the Upyr that printed it. Tested in real interactive zsh, bash 4.4–5.2 and fish through a pseudo-terminal (tools/test_shell_widgets.py), now also in CI.
macOS: Backspace as the first key after an automatic correction reverts it (backspace_undo, on by default); the word comes back as typed, without the space or punctuation the Backspace deleted. This works in the terminal_typing_apps too.
macOS: Upyr learns from your own fixes (auto_correct_learning, on by default). A correction you revert twice with the undo shortcut becomes an exception for that word; a word you convert by hand twice becomes a correct rule. A Backspace revert teaches nothing, since that Backspace is often meant for the space. A revert followed by converting the same word back counts as a slip, not a lesson, and a learned rule never overrides your own exception or rule.
Transliterate the selection to Latin by the 2010 national system (Київ → Kyiv, Згорани → Zghorany) and cycle its case (lower → UPPER → Title), with optional transliterate_hotkey / case_hotkey shortcuts (off by default) and upyr transliterate / upyr case for scripts. Neither switches the layout. The system is not reversible, so there is no Latin → Ukrainian direction.
Pause automatic correction in one app from the menu bar (macOS): "Pause automatic correction in <app>" names the app you were typing in and keeps it in auto_correct_disabled_apps; upyr doctor lists them.
Correct the last word before Enter on macOS. While a word that would be corrected is being typed, the target app's input tap is armed; Enter is held there until the corrected word is pasted, then follows it, so a chat message is sent corrected instead of corrected after it has gone. Words that need no correction never delay Enter. Terminal-typing apps are unchanged.
"Correct words in terminals" in Settings → Automatic (macOS). Automatic correction stayed silently off in Terminal, iTerm2, Ghostty, kitty, Warp, Alacritty, WezTerm, Termius and cmux unless their bundle IDs were added to the configuration file by hand; the checkbox now opts them in and out.
Your own correction rules: auto_correct_rules in the configuration file takes pattern correct|keep [english|ukrainian] entries with * wildcards, written either as the keys typed (ghbdsn) or as the text seen (руку). The engine supported these rules since 0.4, but only its tests could use them. They apply to normal and terminal correction; a matching keep wins.
Caps Lock no longer turns automatic correction off. It inverts the case of letters as Shift does (GHBDSN → ПРИВІТ); a Ukrainian letter on a punctuation key ([ ; , .) ends the word, since its intended case depends on the layout.
Fix an accidental Caps Lock on macOS: a word typed as пРИВІТ or hELLO while Caps Lock is on becomes Привіт / Hello (and gHBDSN becomes Привіт), and Caps Lock is turned off for the next words.
The last word before Enter uses the short-word policy terminals already use, since no later word can resolve it: nfr⏎ → так⏎, zr⏎ → як⏎.
Manual conversion on macOS no longer rewrites typography. The installed layout table included the Option layers, so converting a selection turned «, », … and ’ into ±, Ú and ∏; it now holds only the plain and Shift layers the tracker reads (75 pairs on ABC + Ukrainian).
Saving Settings no longer reverts changes made elsewhere while the window was open (CLI, upyr globe, the configuration file): the window's edits are merged onto the file as it is now, and only the fields it changed win.
Switching layouts with Ctrl+Space, Ctrl+Option+Space, Cmd+Space or Win+Space in the middle of a word no longer drops the word: g, switch, hbdsn is repaired to привіт. A bare modifier no longer ends the word either; a shortcut key (Cmd+A, Ctrl+K, …) does, as it may edit text or move the caret.
Linux: British, Irish and Australian XKB layouts count as English, and Dvorak, Colemak or Workman variants are unsupported rather than misread as QWERTY. The layout notification now follows the configured indicator duration and replaces the previous one instead of stacking.
Fixed
macOS: every key was typed twice in Gemini and Claude ("tteesstt") from the moment Upyr started watching a word it would correct until you typed in another app. These apps receive each key-down at their process event tap twice; with Upyr's tap in place, both copies reached the app. The tap now lets each key event through once and drops a repeated copy, including copies of Upyr's own paste and of held keys it releases.
macOS: words corrected while typing no longer reach clipboard-history apps such as Paste, in apps that expose the selection through Accessibility. Upyr checked the selected word with a copy, which left it on the clipboard unmarked for about 90 ms, until Upyr's own hidden copy replaced it. It now reads the selection through Accessibility, which also skips that 90 ms wait, and copies only where an app does not expose its selection.
macOS: a long correction no longer freezes Upyr when it ends. Each conversion opened its own keyboard connection, and closing it waits about 20 ms for every key it sent, so after a 30-character word the Globe key and typing waited close to a second. One connection now serves every conversion.
ок typed on the English layout (jr) and ok typed on the Ukrainian one (щл) are corrected; the model abstained on jr (it reads half-English), so both are built-in rules now.
An unreadable configuration file no longer stops Upyr from starting with no message. The background app runs with defaults (on macOS it explains why and offers to open Settings), and Settings opens on the defaults, names the problem, and replaces the file on Save.
Linux: key and event sounds no longer leave a finished canberra-gtk-play process behind per sound (a zombie per keystroke with key clicks on), and at most eight players run at once. Opening Settings or a link from Settings no longer leaves a zombie either.
Stop automatic correction from rewriting a correctly typed word that collides with a dictionary word on the other layout (руку is no longer turned into here).
Rewrite only the confident word, not earlier words that clearly belong to the typed language: ok ghbdsn becomes ok привіт, not щл привіт. Ambiguous earlier words are still corrected together (nfr f xb ,elt → так а чи буде).
Keep a final ю or б as a letter when the whole word reads better than the punctuated stem (hj,k. → роблю, not робл.).
Let words on the Exceptions list override the built-in correction rules, and let a keep rule win over a broader correct rule regardless of order.
Convert the Ukrainian shifted number row (", №, ;, :, ?) in the built-in layout table used by the CLI and as the fallback for conversion.
Keep typing through an automatic correction on macOS: keys pressed while Upyr selects, copies and pastes the corrected word now wait in the target app and follow the paste in order, instead of replacing the selected word. A click during the edit cancels it and the held keys follow the click.
Stamp the input counters before the slower focus queries, so a key typed during them cancels a terminal edit instead of being backspaced.
Collapse a selection whose copy arrived late with one arrow instead of moving the caret past the word, and release the selection when the selected text has nothing to convert.
Correct words with number-row punctuation and hyphens while typing. The live tracker used to drop every digit-row key and -, so ghbdsn!, ghbdsn? (Shift+7), "ghbdsn", (ghbdsn) and ,elm-zrbq were never corrected even though the engine handled them. Bare digits still end tracking (h264, mp3), and @handle and user@host stay technical while a quoted @word@ does not. Applies to the desktop app, terminal typing and the web demo.
Score words with the macOS Ukrainian apostrophe ʼ (typed on the backslash key of the default Ukrainian layout) and the typographic ’ like ASCII '. пʼять and мʼясо typed on the English layout were never corrected.
Prefer the current macOS default Ukrainian layout (Ukrainian-PC, shown as "Ukrainian") over "Ukrainian – Legacy" when switching after a correction.
Treat a layout as English only when English is its primary language and its letters are in QWERTY order. German, Hebrew, Polish and similar layouts that merely list English, and Dvorak, Colemak, QWERTZ and AZERTY, used to be read as US QWERTY, which could rewrite the wrong text; they are now unsupported.
Keep the selection aligned with the screen after a double space, which used to make a multi-word correction fail its copy check.
Replay clicks, Enter, Tab and arrows that happen during a correction, so the next word is not joined to the previous one (ok, click, ckjdj → okckjdj).
Unchecking "/commands in Superset" now also removes Superset from terminal typing, which checking it had silently enabled.
An exception typed as "two words" is saved as two exceptions instead of blocking every other change in Settings.
upyr run --hotkey survives configuration reloads and Settings saves.
The modifier gesture no longer converts text while Settings is open.
Windows and Linux: a conversion shortcut equal to the macOS-only undo shortcut no longer blocks saving, and Settings search no longer lists controls those platforms do not have.
The tray item is "Pause Upyr", since pausing stops every action.
Web demo: on-screen Shift and Caps Lock reach the engine, a real keyboard's layout is read from the typed character, and "Corrected" appears only when the text was actually replaced.
Site and README: the Anime pack's six event cues are pre-rendered clips; automatic correction happens after Space; the browser adapter and live demo already ship; maintainer tools that download data are listed.
Known limitations
Windows still treats any English input locale as English, including Dvorak and other layouts that move the letters; use a QWERTY English layout there.
The "Layout switch" sound on Windows and Linux plays only when the conversion's own sound is turned off, since there is no Globe-key switcher.
Keep accepted terminal corrections with trailing punctuation reversible, validate mapped punctuation against the installed keyboard map, and support macOS's backquote position for ґ in typing replacement.
Preserve punctuation runs such as ... without turning earlier periods into ю; keep a known word's last letter before the remaining marks.
Cover custom slash commands containing digits, hyphens and underscores with generated editing sequences. Add an offline headless corpus/runner and a read-only native macOS layout-map integration check.
Re-arm freshly typed slash-command prefixes after clicks, Escape, navigation, shortcuts and edits, without requiring an extra Return. Discard the previous tracked span and keep known inline prose unchanged.
Recognize three-letter terminal words whose first physical punctuation key produces a Ukrainian letter ([ez → хуя, ;er → жук, ];f → їжа). Retain dictionary/model confidence, configured exceptions, technical-token guards and explicit minimum lengths above four characters.
Expand the compact Ukrainian lexicon for common initial-letter and colloquial word forms, and cover the reported cases in the opt-in Superset input probe.
Security
Update event-listener to 5.4.2 for RUSTSEC-2026-0221. Document four unmaintained-dependency notices with exact, time-limited OSV exceptions and check pull requests with OSV before merging.
Integrated GlobeSwitch, guarded terminal correction and output-aware feedback.
Added
A dedicated Exceptions tab with an editable table for words that automatic correction must always leave alone, replacing the single comma-separated text field on the Automatic tab in both settings UIs.
An indicator style setting (letters, flag, or both) for the floating language indicator, in both settings UIs.
Anime Reactions' six application-event cues (auto-correct, manual conversion, layout switch, pause, resume, error), rendered offline with the ElevenLabs Sound Effects API by the new tools/generate_event_sound_pack.py and bundled the same way as the Original pack's event cues.
macOS undo for the last automatic correction (Cmd+Alt+Z, configurable in Shortcuts). Restores the original text and exact input source in the same focused field, including terminal and slash-prefix corrections. Available for 30 seconds before further typing, navigation or pointer activity.
Separate macOS headphone sound limit in Feedback (12% by default, 0–30%), with current output and effective gain. Speakers retain master volume. Headphone cues have softened edges and peak attenuation, never overlap, and stop on output changes. Unknown outputs also use the quiet limit. Schema 12 preserves existing sound preferences during migration.
A searchable country-flag picker in macOS Feedback settings, showing all 259 bundled country and region flags with names and codes. Assign flags per keyboard layout with live previews, explicit Save Flags, automatic defaults and Revert. Saving merges only edited layouts and preserves other preferences.
Opt-in line-start slash-command correction in terminal interfaces, including the leading slash (.сщььфтв → /command), before Space or submission.
Live embedded flag preview in macOS Feedback settings, with a preview-layout selector, the actual GlobeSwitch renderer and saved per-layout overrides.
Opt-in macOS terminal/TUI typing replacement for applications listed in terminal_typing_apps. A freshly tracked single word is replaced using exact Backspace counts and Unicode key events, without Copy/Paste or Enter. Input, focus changes, cursor controls and mouse activity cancel pending edits. Configuration schema 10 keeps this backend disabled until selected.
The original GlobeSwitch pixel-flag row on macOS, including its 259 pixel flags, animated centering, accent glow, pointer-screen placement and fade. Select **GlobeSwitch flags** in indicator settings. Configuration schema 9 adds [globe_switch.layout_flags] for region or custom-text overrides.
Integrated GlobeSwitch on macOS: opt-in listen-only Globe-key taps cycle all enabled layouts directly, with configurable tap duration, skipped input sources and recent-layout order. No separate app or helper is required.
A native General settings control, upyr globe configuration/diagnostic commands, and upyr globe migrate to uninstall standalone GlobeSwitch before enabling its replacement. Pause/quit restore macOS handling; globe restore recovers the saved preference after an unclean exit.
Globe switches use Upyr feedback and invalidate pending automatic corrections.
Configuration schema 8 adds [globe_switch]. Upgrades leave the feature off and preserve all existing correction, shortcut and feedback settings.
The cross-platform settings UI enables AccessKit again on Windows and Linux.
Linux/X11 tray support now uses StatusNotifierItem over D-Bus instead of the GTK/AppIndicator stack; layout feedback uses a Freedesktop notification.
The project MSRV is now Rust 1.87 so AccessKit can use the quick-xml-free zbus_xml parser line.
macOS preview documentation now names the exact Gatekeeper warning users see for the unnotarized build and clarifies that updates are checked manually via GitHub Releases.
README and upyr.org now document the crates.io Cargo install and Homebrew tap install paths alongside the GitHub Releases preview.
The install-critical upyr, upyr-core, and upyr-audio crates are now published to crates.io.
Fixed
Word and prefix conversion no longer strands the caret when the focused app (notably terminal emulators) drops the Shift modifier from the selection chord instead of extending a selection with it: Upyr now detects the resulting empty copy and moves the caret back to its original position.
Capture the undo target at the correction itself. Slash-command tracking can outlive a focused editor within the same window; undo now binds to the field actually edited while still refusing changes after focus moves elsewhere.
Send terminal replacements as single-character keypresses. Multi-character Unicode input can take Chromium's composition path and let a following letter reach the terminal before the replacement. Add an opt-in Superset regression probe covering real terminal input, undo and focus changes.
Ignore nonactivating windows from other processes when validating terminal focus. A desktop overlay above Superset must not reject a valid word edit.
Commit terminal layout changes only after the target accepts the word edit; cancelled corrections no longer switch layouts silently. Successful automatic replacements show the active-layout indicator even when that layout was already selected.
Prefer a known complete Ukrainian word over a punctuation-preserving guess from its shorter stem (hjpevs. → розумію, retaining the final ю).
Deliver terminal Backspace/typing as one target-process event-stream batch; prevent a following letter from being consumed by a delayed Backspace. Use window identity and native input counters on the terminal edit path.
Apply the short-word terminal policy in both directions (nfr → так, zr → як) and accept physical punctuation keys that form Ukrainian letters (lj,ht → добре, [jnskjcz → хотілося) in the typing backend.
Recognize English contractions such as it's, and evaluate terminal words individually rather than rejecting a correction containing an earlier ambiguous phrase. Common short English words (not, so, for, the) can establish the English layout under the default terminal policy.
Preserve terminal target identity by frontmost application/window when an Electron terminal does not expose an Accessibility text element.
Select the destination macOS layout before sending Paste. Changing it while Cmd+V is queued can make macOS replay the event and insert the text twice.
Run macOS automatic-correction observation through AppKit's main-thread event monitor. Avoid rdev's background Carbon translation, which terminates the process on macOS versions that enforce the input-source queue contract.
Keep the macOS event loop responsive during Copy/Paste delays. Conversion phases use scheduled deadlines, cancel before paste if input or focus changes, and resume word tracking before delayed clipboard cleanup. Cleanup failures never move the caret after a committed replacement.
Restore Rust 1.86 compatibility in the desktop word tracker; its let-chain required a newer compiler than the workspace's declared minimum.
Ignore punctuation when detecting the dominant script for smart conversion; text such as a.... now converts from English instead of treating periods as Ukrainian letters.
Preserve clipboard data copied by another application while Upyr's temporary value or delayed clipboard restoration is pending. Native change counters distinguish even a later copy of identical text.
Apply the correction engine's exact replacement after verifying a GUI selection; do not recompute it from already rendered, potentially mixed text.
Skip unverified automatic terminal edits instead of deleting words with Ctrl+W and assuming Ctrl+Y can restore an arbitrary terminal program.
Replace shortcut registrations transactionally and retain the previous keyboard monitors if a reloaded shortcut is occupied. Pausing, resuming and reloading cancel stale automatic corrections on every desktop platform.
Replace an unrelated persisted code graph with Upyr's graph; check repository identity and source-file coverage in CI, and normalize indexer JSON escaping.
Security
Update webbrowser to 1.2.2 for RUSTSEC-2026-0257 and replace yanked clipboard-win 5.4.1 with 5.4.3.
Removed the Linux GTK/glib dependency chain and its accepted advisory entries.
Kept the compatible wayland-scanner backport documented after confirming upstream master's scanner is not compatible with the released wayland-client stack used by winit/eframe.
High-confidence trigger rules can now match exact words, prefixes, suffixes, and contains patterns (word, word*, *word, *word*). This is Upyr's clean-room counterpart to Punto Switcher for Windows consuming its A tag as an any-position wildcard.
Recall and performance benchmark coverage for the trigger layer.
English and Ukrainian reverse-engineering articles for the Punto Switcher rule format and the Mac/Windows A-tag divergence.
A multipage product site, live Cloudflare Pages deployment at upyr.org, and article-level navigation with an English/Ukrainian language selector.
Changed
The trigger layer now uses wildcard-aware matching instead of exact-only comparisons for built-in high-confidence rules.
Public project links now point at https://upyr.org/.
Documentation now clearly separates Upyr's clean-room behavior from Punto's data files and binary-specific rule semantics.
Security
Added OSV, Trivy, SBOM, and Cosign-backed supply-chain checks around release and deployment workflows.
Documented the currently accepted Linux GTK/egui advisory exposure and keeps it on a dated revisit path while the gtk3 replacement work remains parked.
Upyr Original, Pocket Arcade, and Anime Reactions sound packs with native AppKit and cross-platform settings controls.
Dependency-free upyr-audio synthesis with deterministic pfxr-style cue variations and locally generated, non-sampled formant reactions for non-character keys in the Anime pack.
Opt-in physical-key feedback for characters, Space, Enter, Escape, Tab, modifiers, Caps Lock, Delete, Backspace, navigation, and function keys.
Changed
Configuration schema 6 adds sounds.pack and sounds.key_clicks; migrations preserve the original event theme and keep keyboard monitoring disabled.
Keyboard cues branch from raw physical events before autocorrect filtering, are cached by pack/cue/variant, and are rate-limited for comfortable typing.
Every pack now synthesizes both event and key cues locally. Pre-rendered raw audio assets were removed from the source tree and distributable packages.
Security
Audio synthesis is local-only and receives physical key categories rather than rendered text. It uses no recordings, microphone, network service, telemetry, or new third-party runtime dependency.
Privacy CI and automated review reject pre-rendered audio assets in distributable source paths.
Upyr drops keyboard cues while its own synthetic replacement input is active, preventing copy, paste, and correction keystrokes from producing feedback.
English ↔ Ukrainian correction for selected text and the previous word.
Opt-in automatic correction with physical-key mapping, punctuation and case preservation, technical-token guards, and a compact local signed character n-gram model.
Native macOS input-source integration, rich pasteboard snapshot/restore, Accessibility permission lifecycle, searchable AppKit settings, About page, language indicator, event sounds, and launch-at-login controls.
Preview Windows, Linux/X11, and DOM-independent WebAssembly targets.
Reproducible model generation and frozen mixed-language evaluation fixtures.