all writing
Aug 20263 min read

Speedy

by Amir Ahmadzadeh


I spend most of my working day in the terminal, and I love using different TUIs like OpenCode, lazygit, lazydocker, and k9s. Between writing code in Neovim, moving around tmux, working with Git, taking notes, planning projects, documenting progress, learning, and prompting agents, I am constantly typing.

At some point, I became curious about how many keys I press during a normal day and which hours are the most active. Because most of the time I'm typing means I'm doing something or learning so could be very nice to know how much active I am.

I was not interested in knowing what I typed. I already know what I am typing at that moment 😅. I only wanted the numbers so I could track my activity and compare it over time.

So I built Speedy, a small terminal application written in Rust that counts keyboard activity and reports some simple analytics.

The idea

The idea was straightforward:

  • listen for keyboard presses
  • count them by day and hour
  • store the counts locally
  • display the results in the terminal

The important part is that Speedy does not store which keys were pressed.

It does not record words, commands, passwords, applications, or websites. A key press is immediately converted into a number, and only that number is kept.

This matters because any application listening to keyboard events can easily sound like a keylogger. Speedy is intentionally limited to activity counts, and everything stays on the local machine.

The app

I wanted the interface to feel more like an odometer than a traditional analytics dashboard.

Speedy has four different views: Live, Daily, Hourly, and Records.

Live

The Live view gives me a quick overview of today’s activity, including my current typing speed and progress toward the daily goal. The target is currently fixed, but I want to make it customizable. I opened an issue on GitHub, so if you are interested in contributing to Speedy, this could be a good place to start.

Speedy Live view

Daily

The Daily view shows how my activity has changed over the last seven days and compares it with the previous week. Speedy Daily view

Hourly

The Hourly view shows when I am most active and how my keyboard activity is distributed throughout the day. Speedy Hourly view

Records

The Records view gives me a longer-term picture using all-time totals, recent averages, trends, and my usual working rhythm. Speedy Records view

How it works

Speedy is written in Rust and uses evdev to count physical key presses on Linux. Releases and automatic repeats are ignored, while hourly totals are stored locally in SQLite.

The dashboard is built with Ratatui and Crossterm. Speedy runs its recorder in the background, so closing the dashboard does not stop the count. To stop it manually, run:

speedy --stop

Running it

With Rust installed:

git clone https://github.com/4m1z/speedy.git
cd speedy
cargo install --path .
speedy

Speedy needs permission to read /dev/input/. On Arch-based systems, add your user to the input group, then log out and back in: sudo usermod -aG input "$USER"

All collected data remains on the local machine.

Integrating it with Omarchy

Finally, I wanted to integrate Speedy into my Omarchy setup.

Instead of opening a terminal and typing the command every time, I added a Hyprland keybinding to ~/.config/hypr/bindings.conf:

bindd = SUPER SHIFT, I, Speedy, exec, omarchy-launch-or-focus Speedy "uwsm app -- alacritty --class Speedy -T Speedy -o window.padding.x=12 -o window.padding.y=12 -e sg input -c /home/NAME/.cargo/bin/speedy"

Now Super + Shift + I opens Speedy in Alacritty. If the window is already open, Omarchy focuses it instead of starting another one.

I gave the window its own Speedy class and title, added some terminal padding, and used sg input so the process runs with the input-device permissions it needs.

Hyprland reloads the binding after the configuration is saved. If needed, it can also be reloaded manually:

hyprctl reload

This makes Speedy feel like part of my desktop instead of a separate command I need to remember.


The project is available on GitHub.