Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

handy-fedora-wayland

A one-shot setup for getting Handy — the local voice-input app — working properly on Fedora 43 with GNOME on Wayland, with state-aware GNOME notifications and a reliable global hotkey.

Handy is a great tool, but the Linux + Wayland path has a few sharp edges that aren't obvious until you hit them. This repo packages the fixes.

What this gives you

  • A reliable global hotkey. Ctrl+Space (configurable) toggles transcription from anywhere, routed through a GNOME custom shortcut — not Handy's built-in hotkey, which is unreliable on Wayland.
  • State-aware GNOME notifications. You see "🎙 Recording…" when it starts and "Stopped" when it ends, with proper mic icons.
  • Debounced toggles. GNOME occasionally double-fires a shortcut; the wrapper swallows anything within 1 second of the last press.
  • A working ydotoold user service. Handy needs ydotool for synthetic keystroke injection on Wayland; this sets it up correctly as a user-session service.

Why this exists

Wayland intentionally prevents apps from registering global hotkeys or injecting keystrokes into other apps — these were X11 footguns that let malware spy on keyboards. That security model breaks any voice-input tool that wants to (a) listen for a hotkey anywhere and (b) type the transcribed text into the focused app.

The workarounds form a three-layer stack:

Layer Problem Solution
Global hotkey Apps can't register global keys under Wayland Use a GNOME custom shortcut → compositor delivers the key to our script
Keystroke injection Apps can't synthesize input into other apps ydotoold writes to /dev/uinput (kernel-level, bypasses Wayland)
State feedback Handy has no status CLI or system tray that works under GNOME Tail Handy's log to derive state; notify-send for visible feedback

Each piece solves a distinct constraint. Removing any one breaks the flow.

Prerequisites

  • Fedora 43 (should work on any distro with GNOME on Wayland, but only tested on Fedora)
  • GNOME desktop on Wayland session
  • Handy installed — grab the .rpm from their releases
  • ydotoolsudo dnf install ydotool
  • Your user must be in the input group (the installer checks this and offers to fix it)
  • libnotify (provides notify-send) — usually already installed on GNOME

Install

git clone https://github.com/<you>/handy-fedora-wayland.git
cd handy-fedora-wayland
./install.sh

The installer is idempotent — safe to re-run. It will:

  1. Verify required commands are on PATH.
  2. Check that your user is in the input group (and offer to add you if not; you'll need to log out/in once).
  3. Install handy-toggle.sh to ~/.local/bin/.
  4. Install and enable the ydotoold systemd user service.
  5. Register Ctrl+Space as a GNOME custom keybinding that invokes the toggle script.

To pick a different key, set HANDY_KEYBINDING before running — using GNOME's <Modifier>key syntax:

HANDY_KEYBINDING='<Super>v' ./install.sh

Handy itself manages its own autostart via its settings panel ("Launch on startup"); this repo doesn't touch that.

Uninstall

./uninstall.sh

Removes the toggle script, the systemd user unit, and the GNOME keybinding. Leaves Handy and ydotool packages alone.

Optional: streaming transcription (build from fork)

Upstream Handy transcribes after you release the hotkey — a long dictation means waiting for the whole clip to process. PR #1173 adds VAD-chunked live streaming (text pastes as you talk), but it's stalled behind an upstream feature freeze as of April 2026.

If you want streaming today, build from the fork at DylPorter/Handy, which has PR #1173 rebased onto latest main:

# Extra build dep on Fedora (beyond the usual webkit2gtk/gtk3/etc.)
sudo dnf install -y gtk-layer-shell-devel

# Clone, build, install
git clone https://github.com/DylPorter/Handy.git ~/Handy-streaming
cd ~/Handy-streaming
git checkout streaming-rebase
npm install --ignore-scripts

# The Tauri config calls `bun`; swap to npm if you don't have bun installed:
sed -i 's|bun run |npm run |g' src-tauri/tauri.conf.json

# Generate TypeScript bindings (runs the debug binary briefly so tauri-specta
# can write src/bindings.ts, then exits)
(cd src-tauri && cargo build && timeout 5 ./target/debug/handy || true)

# Build the RPM
npm run tauri build

# Install
sudo dnf install -y src-tauri/target/release/bundle/rpm/Handy-*.x86_64.rpm

Then restart Handy and go to Settings → Advanced → Transcription Mode. Stream (VAD-chunked, live paste) is the most useful setting for long dictations. Realtime uses fixed-duration chunks (faster first-chunk latency, more boundary errors). Standard keeps the original behavior.

Accuracy caveat: Whisper is fundamentally non-streaming, so chunked modes lose a little cross-sentence context. VAD-chunking at natural pauses minimizes this. If you can tolerate the tradeoff, the UX win on long recordings is significant.

How it works

handy-toggle.sh

Invoked by GNOME on hotkey press. Reads the last 200 lines of Handy's log (~/.local/share/com.pais.handy/logs/handy.log), greps for the most recent Recording started / Microphone stream stopped line, fires the appropriate notification, then runs handy --toggle-transcription.

Debounce uses a lockfile in /tmp with nanosecond timestamps. The default 1-second window can be overridden with HANDY_TOGGLE_DEBOUNCE_MS.

All output is appended to /tmp/handy-toggle.log for debugging.

systemd/ydotoold.service

A minimal user unit that runs /usr/bin/ydotoold as your user. Because your user is in the input group, the daemon can open /dev/uinput without root. The daemon creates a socket at /tmp/.ydotool_socket that the ydotool client — and Handy, internally — connect to for keystroke injection.

Fedora's ydotool RPM also ships a system service (ydotool.service), but a user service gives cleaner session lifecycle: the daemon dies when you log out, no PID files to clean up, and it runs under your own session so any environment tweaks are local to you.

GNOME custom keybinding

The installer appends a new entry to org.gnome.settings-daemon.plugins.media-keys.custom-keybindings, finding the next free customN slot. On uninstall, it reverses the append without disturbing your other custom shortcuts.

Troubleshooting

Hotkey does nothing.

  • systemctl --user status ydotoold — is the service running?
  • tail /tmp/handy-toggle.log — is the script being called at all? If not, the GNOME keybinding isn't registered (check gnome-control-center → Keyboard → View and Customize Shortcuts → Custom Shortcuts).

Notifications appear but no text is typed.

  • Your user isn't in the input group, or you haven't re-logged-in since adding yourself. Run groups to verify.
  • Try ydotool type "hello" in a terminal to isolate — if that fails, ydotoold isn't working.

ydotoold.service stuck in activating (auto-restart) with error: Another ydotoold is running with the same socket.

  • An orphan ydotoold from a previous session is holding the socket. The installer now cleans this up automatically on re-run, but you can also fix it manually: pkill -u "$USER" -x ydotoold && systemctl --user restart ydotoold.

"Recording…" notification appears but transcription doesn't start.

  • Check ~/.local/share/com.pais.handy/logs/handy.log for errors.
  • Make sure Handy is running: pgrep -a handy.

State-detection misbehaves (shows wrong state).

  • Handy's log format may have changed in a newer release. The wrapper greps for Recording started and Microphone stream stopped — adjust these patterns in handy-toggle.sh if upstream renamed the log lines.

Attribution & License

This repo is MIT-licensed and does not include any of Handy's source code. Handy itself is a separate project by CJ Pais, also MIT-licensed, available at github.com/cjpais/Handy. All credit for the voice-input tool goes to the upstream author — this repo is only Linux packaging glue.

About

Fedora 43 + GNOME Wayland setup for Handy: systemd user unit for ydotoold, GNOME keybinding installer, and a state-aware toggle wrapper with desktop notifications.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages