Recent Posts (all)

Elgato Key Light Spoon

I bought an Elgato Key Light during Covid, and lately I was operating it with Lolgato app.

Since a couple of weeks, however, I started replacing small menu bar utilities with Hammerspoon. So, I thought, can I replace Lolgato with pure Hammerspoon?

Turns out you can (with some help from Claude Code). The result is a new Spoon, for which I opened a PR to the Spoons repository.

Part of Kagi Small Web

I’m pretty stoked that this very blog was added to Kagi’s Small Web initiative.

As a result, traffic from Kagi went up many folds since then!

A screenshot of Umami showing the traffic coming from Kagi. It was basically 0 before March.
A screenshot of Umami showing the traffic coming from Kagi. It was basically 0 before March.

Hieroglyphic for macOS

The other day, I stumbled upon the GNOME-only app Hieroglyphic, that finds LaTeX and typst symbols when you draw them on a canvas.

So, I set out to port it to macOS and I can happily report that I succeeded. There’s a PR open to contribute everything back, but in the meantime, grab it from my GitHub fork!

A screenshot of the main window
A screenshot of the main window

Get Rid of Bartender and Other Menu Bar Apps

Since having a notch on my MacBook, I cannot fit all the icons in my menu bar.

I’ve tried heaps of apps to make it work: Bartender, Ice/Thaw, and Hidden, but they all had subtle bugs.

Turns out, there’s an easy way to avoid using these apps by shrinking the spacing and padding of the menu bar items, and now I don’t need any of these apps!

From the terminal, type

defaults -currentHost write -globalDomain NSStatusItemSpacing -int 2
defaults -currentHost write -globalDomain NSStatusItemSelectionPadding -int 2
killall ControlCenter

(You can play around with -int 2 and see what works best for you!).

To undo and go back to normal, type

defaults -currentHost delete -globalDomain NSStatusItemSpacing
defaults -currentHost delete -globalDomain NSStatusItemSelectionPadding
killall ControlCenter

It’s a bit crammed, but it’s bug-free.

Protect against supply-chain exploits using uv

LiteLLM was recently victim of a supply-chain exploit, where an attacker was able to run arbitrary code on infected machines.

In the aftermath, I saw how uv provides a safety setting for this, and it would be good practice to add this to your pyproject.toml

[tool.uv]
exclude-newer = "1 week"

or uv.toml:

exclude-newer = "1 week"

The docs provide multiple options to protect yourself.

Minifeed

I added this blog to minifeed

Minifeed is a nifty website by Rakhim Davletkaliyev, who added this blog there today.

The tagline for Minifeed is:

Minifeed is a curated blog reader and search engine. We collect humans-written blogs to make them discoverable and searchable.

You can create an account, but search works without logging in.

Mentoring a Box of Numbers

More on the impact of AI coding, and the Jony Ive-designed Ferrari interior.

Killer quote by John Siracusa on the (possible) existential dread programmers are experiencing because of tools as Claude Code:

The skills that I’m most proud of are not the skills that involve me typing particular API calls.

That whole part (53’ in) is worth a listen.

Couple Mailmate to Things for Maximum Productivity

Recently, Michael Lopp wrote I Hate Fish in which he outlined his approach to getting work done.

The simplicity to remember when to do what resembles how I use Things (which he also uses) in combination with Mailmate and Keyboard Maestro:

The system also works when I just replied to an email, and I want to be reminded if there has been a follow-up or not.

The core of the system relies on this Keyboard Maestro macro

The Keyboard Maestro macro
The Keyboard Maestro macro

All the heavy lifting is done by this bit of JS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
let addDays = (days) => {
    let d = new Date();
    d.setDate(d.getDate() + days);
    return d.toISOString().split('T')[0];
};

function createThingsTodo(name, activationDate, notes) {
    let url = "things:///add?";
    let params = [];
    
    if (name) params.push("title=" + encodeURIComponent(String(name)));
    if (activationDate) params.push("when=" + String(activationDate));
    if (notes) params.push("notes=" + encodeURIComponent(String(notes)));
    url += params.join("&");
    
    let app = Application.currentApplication();
    app.includeStandardAdditions = true;
    app.openLocation(url);
}

let d = parseInt(kmvar.Days, 10);

let mailmate = Application("Mailmate");

let message = mailmate.messages[0];
let name = message.name();
let URL = message.messageUrl();
// Usage examples
createThingsTodo(name, addDays(d), URL);

Some notes:

You can download the macro here.

Slack's Feed Command is Secretly Broken

Slack’s /feed command is really useful; it allows you to subscribe to an XML feed and receive updates in any channel.

However, it doesn’t always work as expected, and when it fails, there’s no way to find out why.

Recently, I added an Atom feed to an announcement channel, but the posts weren’t coming through. I initially thought the /feed functionality might be incompatible with announcement channels, but I was wrong.

After contacting support, they told me:

We only recognise the following tags for date values: <pubDate>, <issued>, <modified>, <updated>, <dc:date>, or <published> (this last date type applies to Atom feeds) and the date tag fields must be within an <item> tag to be read

Great, I thought. Since I controlled the Atom feed, I figured I could just wrap every entry in an <item> tag. However, the Atom standard expects items to be wrapped in <entry> instead. The spec says feeds should be like:

<feed>
  <entry>
    <title>Post Title</title>
    <published>2025-01-24T10:00:00Z</published>
  </entry>
</feed>

Essentially, Slack’s requirements and the Atom spec are incompatible.

In the end, since I was able to rewrite the feed, I simply switched it to RSS to get everything working.

MapToPoster

Transform your favorite cities into beautiful, minimalist designs.

I stumbled upon this beautiful utility to create minimalist posters of the (water)ways of a city.

If you have uv, getting started is really easy:

git clone https://github.com/originalankur/maptoposter  
uv venv --python 3.14.2
source .venv/bin/activate
uv pip install -r requirements.txt
python create_map_poster.py -c "Padua" -C "Italy" -t forest -d 4000

The last command will take a bit of time the first time, as it needs to download quite some data, but the results are beautiful:

A MapToPoster rendering of Padua, Italy
A MapToPoster rendering of Padua, Italy

1/15