Somewhere beneath the keycaps lives Klicky: curious, a little mischievous, and absolutely delighted by sounds. Nobody knows quite how it found its way there. A single click catches its attention; a steady rhythm gets it moving. When the keyboard gets busy, its little world becomes a very happy place.
When you stop, Klicky settles down too. It’s happy to keep you company through a stretch of work, and just as happy to curl up while you take a break. That’s the feeling I wanted around the project: a little presence that makes an everyday interaction more enjoyable.
The software gives that idea a voice on Linux, macOS and Windows. Ten sound packs offer different clicks, clacks and thocks; you pick one, set the volume and carry on in your usual applications. Getting every response to keep up with your fingers became a project about input events, audio buffers and dependable background software.
From a macOS idea to three desktop paths
I first saw someone using Sauhard Gupta’s original project on their Mac. I really liked it and wanted it on my own machine, but I was running Omarchy on Arch Linux. So I did what an engineer with some time on their hands does: took the repo and started moulding it to work on my setup.
First Omarchy, then Linux more broadly, then Windows. I kept adding to it, and it kept growing: input handling, audio buffering, native controls, installation and all the less visible work that makes a background app comfortable to use.
The original macOS implementation, daemon concept, decoded sound cache, local sockets and KeyEcho support are Sauhard’s work. My contribution builds on that foundation, including the Linux and Windows paths and later macOS lifecycle improvements.
That expansion changed the question. It was no longer enough to make a key play a sound. The application needed to start once, report its state, survive an audio-device change, apply controls without blocking typing, and leave the machine cleanly when removed.
Klicky supports all three desktops: Linux has Debian/Arch packages and a source installer, macOS has source setup with its menu bar helper, and Windows 11 x64 is available from Microsoft Store, as well as a per-user installer and portable ZIP. Windows tray controls let you choose a sound pack, adjust the volume, pause and resume without opening a terminal.
A voice ready before you press a key
The sound packs pair an OGG recording with JSON definitions for individual keys. Loading a pack decodes the recording into PCM, prepares its slices and applies bounded normalization. Typing then selects already-prepared audio instead of opening files, decoding sound or constructing a new output stream for each press.
The operating-system edges stay native. Linux reads keyboard events through evdev, so the input path does not depend on a particular Wayland compositor or X11 desktop. macOS uses its native input integration, with Accessibility permission. Windows receives background Raw Input events through a dedicated message window and tracks repeat state per device.
The shared code handles sound-pack definitions and prepared audio. Linux and macOS retain their persistent Rodio mixer and Unix control path. Windows has a bounded renderer and supervised audio output, with a native tray host and a separate console client. Sharing the product’s core did not require forcing every platform through the same runtime.

The delay beyond the stopwatch
The first useful clue was a mismatch: the Linux input path looked fast, but the sound still felt late. A run of 55 keypresses recorded an average callback-to-mixer dispatch of 0.241 ms, with a p95 of 0.56 ms. That pointed the investigation further along the audio path.
The early prototype had negotiated 1,102 audio frames at 44.1 kHz, roughly 25 ms of buffer capacity. Requesting a smaller buffer brought that down to 256 frames on the tested setup, about 5.8 ms, and made the sound feel much closer to the keypress. Fallback sizes kept output working on devices that could not accept the smaller request.
I carried that lesson into Windows: inspect the buffer the device actually uses, then sit down and type. On laptop speakers, the result felt near-immediate and comfortable. Bluetooth headphones added a noticeable delay, making the output device an important part of the experience too.
Keeping that response consistent means preparing work ahead of time. Decoded samples and the output stream are reused, file loading stays off the input path, and Windows queues and active playback are bounded. The aim is simple: each new keypress gets attention immediately, without setup work or an old backlog getting in its way.
The difficult part is everything around a keypress
On Windows, the tray menu cannot be allowed to stall input. Pack decoding and persistence run away from the typing path; control replies report whether a change was applied. Audio supervision handles output failures and changes to the default device. Stale events are discarded during recovery so a backlog of old keypresses does not play later.
Process ownership and local IPC matter for an app that usually stays invisible. Linux and macOS use Unix sockets and platform service managers. Windows uses a session-scoped owner and protected named pipes. A second launch should find the existing instance, not create another sound engine and another tray icon.
Some of the most useful fixes came from ordinary use: keeping Pause and Resume consistent with the current state, separating duplicate test processes from a volume problem, and investigating intermittent missing sounds without recording typed text. Aggregate diagnostics help locate a failure without turning a keyboard utility into a key logger.
Installation has been another real engineering boundary. An earlier Windows removal path depended on its control executable, so a missing CLI could prevent clean removal. That led to a recovery path for damaged installations, alongside checks for running updates, login startup and settings preservation. Standalone installer removal keeps personal settings and custom packs; an explicit purge removes them too.

Try it, or follow the implementation
I wrote about the audio investigation in Every keyboard is a mechanical keyboard with Klicky on DEV, with the buffer comparison and native playback paths illustrated.
The Klicky website lets you step into its little world under the keys, listen to all ten sound packs and choose an installation method. Custom packs use the same OGG/JSON format as the bundled ones. Linux and macOS have a copyable shell command; Windows offers Microsoft Store installation and updates or a PowerShell installer entry point. The macOS menu helper and supported Omarchy integration are included by default, with opt-out flags. Each installation method has its own update and removal path, described in the guide.
For the code, start with the architecture guide, then the CLI reference and sound-pack format. The installation guide covers setup on all three platforms, including Microsoft Store and the separate unsigned Windows installer. Homebrew on Apple Silicon and Scoop on Windows offer additional package-manager routes.
The interaction is still tiny: press a key, and Klicky answers. Making that exchange feel natural has involved input APIs, audio scheduling, concurrency, process ownership, packaging and a fair amount of listening.
Code & further reading
- Source / github.com/Muneer320/klicky ↗
- klicky.muneer320.tech/guide.html ↗
- github.com/Muneer320/klicky/blob/master/docs/ARCHITECTURE.md ↗
- github.com/Muneer320/klicky/blob/master/docs/BENCHMARKS.md ↗
- github.com/Muneer320/klicky/blob/master/docs/WINDOWS.md ↗
- github.com/Muneer320/klicky/blob/master/ACKNOWLEDGEMENTS.md ↗
- github.com/Sauhard74/klicky ↗
- dev.to/muneer320/i-wanted-keyboard-sounds-on-linux-then-i-fell-down-the-audio-stack-3b1d ↗
Written by Muneer Alam · Reviewed 7 November 2026
