Other
Contents
Three small things I wrote because the tool I was using annoyed me.
None of them is better than what it replaced. There are a hundred terminal music players, and several are older, faster and better tested than kurono. I wrote one anyway, because I had opinions about how the other hundred worked and no standing to make anyone else act on them.
That is the whole reason, and I think it is a legitimate one. Ego is a real engineering input. It is what makes someone spend a weekend rebuilding a solved problem, and the rebuild teaches things that reading the original never would. These are the projects where I got to be unreasonable about details nobody else was bothered by.
kurono
A terminal music player in C. Linux only, deliberately.

One process, one binary, no daemon and no MPD protocol underneath. It indexes a music tree into SQLite, gives it a three-column ranger-style browser, and plays it back gaplessly with full-text search over the library through FTS5. About 17,500 lines of C across the audio, library and UI trees.

The interesting part is that the sound card does not wait. It consumes samples at a fixed rate, and missing its deadline is an audible click, not a slow frame. So the audio callback gets a hard rule list: no locks, no malloc, no syscalls. A mutex is out, not because it is slow but because it can block, and the OS can deschedule the decoder mid-critical-section and stall audio for milliseconds.
What is left is a lock-free single-producer single-consumer ring between the decoder and the callback, with C11 release/acquire ordering on the two positions. That ordering was the first bug I had to reason about that the source code cannot show you: compilers and CPUs both reorder, so a second thread can legally see the write position update land before the audio it is announcing.
better-library
A self-hosted book manager. NiceGUI, Python, ships as a container.

A local-first replacement for Goodreads that manages my own library and its metadata, tracks reading progress, and keeps all of it on a disk I own. Built on NiceGUI, packaged with a Dockerfile and a compose file, and it is one of the services actually running in the homelab.
This is the one that had to be finished rather than merely made to work. A scraper that fills a table is an afternoon. A thing you use every week needs a data model that survives you changing your mind about it, a UI that is faster than the website it replaced, and a container that comes back up correctly after a host reboot without you remembering how. The interesting work was all in that last mile, and none of it is visible in a screenshot.
better-ls
An ls -al replacement in C. The oldest and smallest of the three.
$ bls -s -r src/pages src/styles
INDEX | PATH | EXT | SIZE | MODIFIED
----------------------------------------------------------------------
[001] | homelab.astro | astro | 55325 | 2026-09-10 02:26
[002] | mitya.astro | astro | 35027 | 2026-09-10 02:37
[003] | index.astro | astro | 9932 | 2026-09-09 17:15
[004] | other.astro | astro | 9781 | 2026-09-10 13:49
[005] | base.css | css | 5240 | 2026-09-09 01:48
[006] | tokens.css | css | 1194 | 2026-09-09 00:44Prints a fixed-width table of index, name, extension, size and modification time, with hidden-file and recursive modes and four sort orders. Around 700 lines, no dependencies beyond a POSIX system and a C compiler.
Almost nothing about it is interesting, and that is the point of including it. It was the first C I wrote that I then had to live with, and living with it is what taught me the difference between code that runs and code that is correct. Small and finished beats large and abandoned.