Tools

A 5-post collection

ghtraffic

By Matthew Hunter |  Jun 19, 2026  | github, analytics, homelab, golang, umami, postgres, docker

GitHub’s traffic API gives you 14 days of view and clone data per repository. After that, it’s gone. If you want a longer historical record of how your open source projects are performing, you have to collect the data yourself before the window closes.

ghtraffic is a small Go tool that solves this problem. It queries the GitHub traffic API for every repository you have push access to – including organization repos – and writes newline-delimited JSON to stdout, one record per repo per day. Run it hourly via cron and append to a local file, and you accumulate a permanent historical record.

Continue Reading...

dicta

By Matthew Hunter |  Jun 17, 2026  | linux, wayland, voice, dictation, accessibility, golang

Speech-to-text is one of the few accessibility tools where Linux still lags. The options that exist tend to want a commercial cloud API, a Python toolchain with GPU model files, or an X11 session – and often all three. I wanted something that runs as a single static binary on Wayland, talks to whatever ASR backend I already have, and doesn’t listen until I tell it to.

dicta is that: a Linux/Wayland voice dictation daemon written in pure Go. No always-on microphone, no wakeword, no push-to-talk. Capture starts when you press a key and stops when the session ends.

Continue Reading...

apt-cacher-ng

By Matthew Hunter |  Jan 25, 2025  | debian, apt, proxy, caching

When you manage more than a handful of Debian or Ubuntu systems, you quickly discover that downloading the same packages repeatedly from the internet is both wasteful and slow. Enter apt-cacher-ng, a caching proxy specifically designed for Debian package repositories. It sits between your local machines and the upstream mirrors, storing packages locally after the first download and serving them from cache for subsequent requests.

The beauty of apt-cacher-ng lies in its simplicity. Installation is straightforward: a single apt install apt-cacher-ng on a server, and you have a working proxy listening on port 3142. Client configuration is equally painless – you can either set the proxy in each machine’s apt configuration, or use the auto-detect feature if your network supports it. Once configured, every package fetched by any client is cached, dramatically reducing bandwidth usage and speeding up updates across your network.

Continue Reading...

Taskfile

By Matthew Hunter |  Jan 25, 2025  | automation, make, build

Every project accumulates a collection of commands: build the thing, run the tests, deploy to staging, convert images, lint the code. These commands live in README files, shell history, or the developer’s memory. Make has been the traditional solution for decades, but its tab-sensitivity and arcane syntax make it frustrating for simple task running. Taskfile offers a modern alternative.

Taskfile uses a simple YAML format that feels immediately familiar. Tasks have names, descriptions, and commands. Running task serve executes the serve task. Running task --list shows all available tasks with their descriptions. No tabs-versus-spaces gotchas, no implicit rules to remember, no wrestling with pattern matching when you just want to run a shell command.

Continue Reading...

find -exec

By Matthew Hunter |  Apr 2, 2023  | cli, unix

One very useful command for locating files and performing operations on them is find with the -exec option.

find [path] [arguments] -exec [command] {} \;

The part that’s tricky to remember is the escaped semicolon at the end.

Per-file vs batch mode

The \; terminator runs the command once per file found:

find . -name "*.log" -exec rm {} \;
# Equivalent to: rm file1.log; rm file2.log; rm file3.log

The + terminator batches files into fewer command invocations, which is faster:

Continue Reading...