ReCast is a small background helper that watches what you type, checks each finished word against language dictionaries, and automatically switches the keyboard layout between English and Hebrew when it looks like you are typing in the wrong layout — then retypes the mistyped word in the correct layout.
- Captures global key events on every supported platform.
- Builds up the current word from key presses; resets the buffer on cursor / focus-shifting keys (Tab, Escape, arrows, Home/End, PgUp/PgDn, Insert, Delete) and on mouse clicks (macOS / Windows).
- When you press Space or Enter, it interprets the typed key sequence as both an English and a Hebrew word and looks each up in the matching dictionary.
- It anchors on your live keyboard layout (queried from the OS, with any English or Hebrew regional variant recognised). A sequence that already reads as a real word in your current layout is left untouched — including prefixed Hebrew forms (ו/ה/ל/ב/כ/מ/ש) and words whose other-layout reading happens to also be a dictionary word. It only switches when the other layout yields a confident word and the current one yields nothing real. This is what stops valid (and nested/prefixed) words from being mangled.
- On a switch it erases the mistyped word and retypes it (followed by the original Space/Enter), waiting until the layout change has actually propagated first.
- Missing-space splitting (carving
helloעולםinto two words) is opt-in viaRECAST_SPLIT=1; it is off by default because it cannot reliably tell a word we simply don't have in the dictionary from two run-together words.
| OS | Capture | Layout switch |
|---|---|---|
| Linux | evdev |
hyprctl switchxkblayout (Hyprland only) |
| macOS | rdev |
Carbon TISSelectInputSource |
| Windows | rdev |
LoadKeyboardLayoutW + WM_INPUTLANGCHANGEREQUEST |
Linux additionally requires the user to be in the input group (for evdev read access)
and creates a uinput virtual device named recast-injector to replay corrected words.
- Install Rust (
rustup,cargo). - Make sure both English and Hebrew layouts are installed in your OS keyboard settings. On Linux/Hyprland the xkb config must list English as layout 0 and Hebrew as layout 1.
The English and Hebrew dictionaries are baked into the binary at compile time, so the executable is self-contained and runs identically from any working directory — no data files or wrapper scripts to install.
One-shot setup. Adds your user to the input group (required for evdev access),
builds in release mode, installs the binary to ~/.local/bin/recast, and registers a
systemd --user unit that starts ReCast at login:
sudo usermod -aG input $USER && exec newgrp input <<< 'make service'newgrp applies the new group to the current shell so you don't have to log out;
omit the newgrp part and re-login instead if you prefer. Make sure ~/.local/bin
is on your PATH.
Manage the service:
systemctl --user status recast # health check
systemctl --user restart recast # apply a rebuild
journalctl --user -u recast -f # logs
make service-uninstall # stop + remove the unitmake # cargo build --release
make install # build + copy bin to ~/.local/bin
make deploy # clean + build + install
make uninstall # remove the installed bin
make run ARGS=-g # cargo run with the GUI flag
make help # full target listOverride the install root with PREFIX=, e.g. make install PREFIX=/opt/recast.
make serviceWrites a launchd LaunchAgent at ~/Library/LaunchAgents/org.recast.plist and starts it.
You will need to grant the binary Input Monitoring and Accessibility permissions
in System Settings → Privacy & Security the first time it runs.
PowerShell:
.\deploy.ps1 -Target serviceBuilds, installs to %USERPROFILE%\.local\bin, and registers a Scheduled Task that
runs ReCast at logon. .\deploy.ps1 -Target help lists every target.
If you don't want a service, just run the binary (or cargo run --release) from any
shell and leave it in the background.
Pass -g (Linux only) to launch a small control window with an enable/disable
switch and a counter of words fixed since startup:
recast -gSet RECAST_DEBUG=1 to print every word check and switch decision:
RECAST_DEBUG=1 recastSet RECAST_SPLIT=1 to enable opt-in missing-space splitting (off by default):
RECAST_SPLIT=1 recast