Muneer Alam Work / Klicky

The code was fast. The keys still sounded late.

Klicky turns physical keyboard events into sound. My Linux work follows the entire path from evdev input to cached PCM and the audio mixer, where a small software timing number can hide a much larger buffer delay.

Klicky / contribution
Linux input, audio buffering, normalization, service integration and packaging, building on Sauhard Gupta’s original keyboard-sound daemon.
Timeline & status
October 2026
Linux release
Built with
Rust · evdev · Rodio · systemd
Native software01 / AUDIO
KLICKY
ctrlprepared audio. instant feedback.↵

NATIVE INPUT → RUST DAEMON → SOUND

Klicky↗
Original explanatory illustration based on the project’s documented architecture. Not a screenshot or a performance measurement.

A keyboard-sound application has a wonderfully immediate test: type something. If the sound trails your fingers, you do not need a benchmark chart to notice.

Klicky is a Rust daemon that plays a selected sound for physical keypresses. Its most interesting Linux engineering problem was the difference between sending a sound quickly and hearing it quickly.

The delay beyond the stopwatch

The published Linux run records 55 physical keypresses on Arch Linux with Hyprland and PipeWire. Average callback-to-mixer dispatch was 0.241 ms, with the recorded p95 at 0.56 ms. That measures the software path from the input callback to adding cached audio to the mixer.

It does not measure the whole physical-key-to-speaker journey. The original Linux prototype negotiated 1,102 audio frames at 44.1 kHz: about 25 milliseconds of buffer time. That was large enough to undermine the feeling of immediacy even when the dispatch number looked excellent.

At 44.1 kilohertz, 1102 audio frames are about 25 milliseconds; 256 frames are about 5.8 milliseconds. These are buffer durations, not measured total audible latency.
Calculated buffer duration on the documented test path. The dispatch measurement and buffer duration describe different parts of the journey. Open the diagram ↗

The revised player requests 256 frames, then falls back to 512, 1,024 or a device-selected configuration if the audio backend rejects the smaller size. The documented hardware test negotiated about 5.8 ms and reported clearly reduced audible lag. A rigorous end-to-end measurement would need a microphone or loopback recording of the physical impact and generated sound together.

Prepare once. Respond many times.

Decoding a sound file and initializing an output stream on every keypress would put expensive setup in the most sensitive part of the application. Klicky instead keeps decoded PCM in a shared cache and uses a persistent Rodio mixer. The keypress path selects a prepared source and submits it.

The Linux listener reads keyboard devices through evdev. It responds to an initial key-down, rather than sounding on every release or held-key repeat. That avoids tying the core keyboard path to a particular Wayland compositor or X11 desktop.

Volume and pack changes take a different route through local Unix-socket IPC. Acknowledgements and timeouts make a control command an operation with an answer, rather than a hopeful message to an invisible daemon. Those controls are what make a background sound toy practical to live with.

A quiet sound pack is also a systems problem

Some of the key slices in the tested pack were much quieter than the comparison packs. The fix was not to repeatedly process each sound while typing. Quiet slices are normalized once when loaded, with gain capped at six times. That keeps the work near the cache and away from the input callback.

The surrounding Linux experience matters too: a user service, device-access setup, Arch and Debian/Ubuntu packages, runtime switching, documentation and optional Omarchy controls. A daemon that technically works but is frustrating to install is an unfinished interaction.

Building on someone else’s good idea

Klicky began with Sauhard Gupta’s project. The daemon concept, decoded sound cache, sockets, KeyEcho support and original macOS work deserve that credit. My work develops the Linux path: direct input capture, audio-buffer and normalization changes, service integration, packaging and release work.

The result is Linux v0.4.0 and a useful reminder for the next performance problem: time the boundary a person actually experiences, then explain precisely what your smaller measurements include.

Code & further reading

Written by Muneer Alam · Reviewed 1 November 2026