The Pull-Request Heist
13 minutes read
Your effort to remain what you are is what limits you.
– The Puppet Master
The Beginning
May 3, 2014. Benjamin “Ogham” Sago has just made his first commit to Exa. This will go on to be one of the most used ls alternatives, with ~22k stars, 655 forks, and 151 contributors.
For almost a decade, he maintains exa. Yet, around 2021, activity is drastically slowing. Eventually, the project falls dead.
With 63 open pull requests, 276 issues, and some major bugs, the project is on its deathbed. The users are begging for activity.
At this point, other projects are being advertised in the issues for various features. Features that — mind you — are already finished in the pull-requests, but without anyone to merge. The situation is dire, are we all doomed to use LSDeluxe and endure its awful color scheme?[1]
That’s where I somehow came in.
The rabbit hole yak-shave
The terminal emulator kitty is really neat. So is exa, and I’ve been using exa for a fairly long time. Never have I given it much more thought than installing it from nixpkgs, I’m for the most part blisfully unaware of the projects state (which speaks to it’s quality no doubt).
Kitty has a feature. You can type ctrl+shift+e, and it highlights links with letters, a bit like vim easy-motions, and allows you to effortlessly open them in your browser.
As a keyboard only extremist, this pleases me.
Of course, the thing is, when I exa some directory, I can’t “easy motion” for files. And I want that. So I look into it. Turns out, kitty has that feature! And so does ls!
ls --hyperlink=auto
Neat!
Then, tragedy… exa doesn’t. What! A bit of searching reaveals to me a PR on exa. It’s been there since April. It’s awsome!
But it isn’t merged. Why? I orient myself in the issues. I try to figure out who to complain to. But there is none, the project looks dead.
I dip my toes in some forks, see if I can get this done. Seems trivial. Then, my partners has to help sister move. I have the weekend free. The nerd snipe tinglies are coming on. A hacking run is imminent — whether I like it or not.
Onto the programming
Fork other forks, we’ll write our own! Call it eza, old habits die hard, and the x is next to the z on my keyboard. This will suffice. In one bold move we have already solved half of the hard problems of computer science[2], I’d say that’s a good start.
Now we just have to get those pull request over in our repo. One way to do this is the following:
git fetch \
git@github.com:ogham/exa.git/pull/<pr-id>/head:<target-branch>
This way, we can take a pull request branch from exa, and copy it into a branch in our repo. The problem is, there’s 63 pull-requests!?! We’d have to do this for each of them, push the branch to github, then slowly click through the webui and make that pull request, one at a time.
As a keyboard only extremist, this displeases me.
There is no way we’re doing this. If only we had a list of all those repo-ids, we’d be able to at least automate the fetching.
Then, lightbulb. Github has a REST-API ripe for our queries[3]. A bearer token is created. An absolute unit of a curl request is crafted. The world pauses for a moment as we lay the fate of the project into the wire.
curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer <the-bearer-token>" \
-H "X-GitHub-Api-Version: 2022-11-28" \
'https://api.github.com/repos/ogham/exa/pulls?per_page=100' > open-prs-full.json
Then we wait for the response.
After the Suspense
Well. It worked.
cat open-prs-full.json | head -n 10
Was this what we needed? We do see a number property there, and if we look in the html_url property, we see that it matches the expected url for that pull request. Now here is the part where I’d shown off my jq prowess, but I have no such thing. So instead, I make do with some regex.
cat open-prs-full.json \
| rg -i 'pulls/\d+"' -o \
| tr -d "pulls/" \
| uniq \
| tee pr-ids.txt \
| wc -l
63
The number of lines is right, but is the output?
cat pr-ids | head -n 5
1221"
1219"
1210"
1204"
1202"
Ahh, close enough, a little adjustment and we are there:
cat open-prs-full.json \
| rg -i 'pulls/\d+"' -o \
| tr -d "pulls/" \
| tr -d '"' \
> pr-ids.txt
Now did we get it?
cat pr-ids.txt | head -n 5
1221
1221
1219
1219
1210
Seems we did!
The Part Where We Jam Those Pull-Requests into GitHub
At this point, the estrofem tablet under my tongue had dissolved, and I’d woken from my groggy morning state. A purely performative crack of the knuckles were in order, as I leaned over my desk like a hawk that’s caught sight of a mouse.
If you’re a keyboard-only extremist like me, web-ui is a nuisance to be solved. GitHub has gh, or the GitHub CLI. It is extremely useful to sync your nixpkgs fork, and send your package definition pull requests. But today, old reliable was gonna learn some new tricks.
Then I paused. And stared.
In my head flashed visions of old Bell Labs informational videos on the Unix Operating System. The voice of Brain W. Kerninghan echoed in my head — “I think the notion of pipelining is the fundamental contribution of the system…”. The hacking cgi was front and center as I said out loud “It’s a UNIX system, I know this!”. Temporarily absolved of my mortal coil, I resided in waves of abstraction and shell, time and language lost their meaning to the beauty of the baud. It was as if every bit moved in concert with my thoughts, as if the collective will of every electron in my sillicon rock filled out the sails of my spaceship gently surfing on the stream of raw information entering and exiting me. As I slowly raised my cup of tea to my mouth, not for one moment breaking this intimate emergence and embodiment of me in my code, in my will, in my craft, before me it appeared, at the end of time and space itself. The final destination, the one truth of programming, the zen was ever closer. Then the tea — hotter than a NVidia GPU running KDE — removed my taste buds faster than a Arch maintainer removes system critical boot code. What had been my ticket to enlightenment turned into a leaky abstraction all over my desk.
However, I had tried so hard and gone so far, there was no way that in the end, it wouldn’t really matter.
Now — armed with a more modest disposition, xargs, and the GitHub CLI — I went to work. Soon, emerged the command that would seal my fate:
| ) As a smut novel once said[4]: There comes a time in every woman’s life where she reaches a crossroads. A chance to choose between two paths. One is unknown, filled with potential and struggles that demand growth and change, but could lead to new beginnings. The other is familiar, grooved with well-worn ruts and established twists, muddy holes and isolation. The path that, while lonely, fits like a glove.
When — if — I hit enter, I’d be down the road of committing myself to maintaining the damn thing. Were I not to, I’d never downlive the internal shame. Were I to do it, I’d have allocated quite a substantial amount of time in my life to pesky users, stubborn contributors, and the chore and dull drag of changelogs, version bumps, and releases.

As I hit enter, and as the pr tab on the repo slowly grew in the web interface, I hoped this wouldn’t be a mistake.
The Aftermath
Over the next two days, me and sbatial would go onto hack on eza. When monday came, 63 had been reduced to 18.
Hyperlinks, SE-linux contexts, git repo statuses, human readable relative dates, more security fixes than I have fingers to count them on. And the darn grid bug, the pesky bugger had been swatted and was now but a stain on the git history.
With flakes, CI, and sheer will, we had overcome. Trying out eza was as imple as running:
cargo install eza
Or if one was so inclined:
nix run github:cafkafk/eza
But had we won?
The battle, no doubt, but not the war.
Reflections on DevOps and Infra
In the excellent talk at Chaos Communication Conference 36: From Managerial Feudalism to the Revolt of the Caring Classes, the late David Graeber summarizes a core problem in modernity as eloquently as only he could:
[Whenever] I say, talk to a Marxist theorist, wherever, they try to explain value, which is what they always like to do, they always take the example of a [bottle].
[…] Well, look at this bottle, you know. [It] takes a certain amount of socially necessary labor time to produce this, say it takes, you know, this much time, this much resources. It’s always about production of stuff.
But a teacup or a bottle. […] You produce a cup once, you wash it like 10000 times. Most work isn’t actually about producing new things, it’s about maintaining things. […]
So I think that what we need to do is we need to start over. We need to realign. First of all, think about [work], not as producers, but as carers.

I spend four years of my life studying “the queen of the sciences”, mathematics herself. One view that I particularly enjoyed were that of the toolmaker. Sure, we were studying abstract structures, but that’s being a student. A mathematician was a tool maker.
That view might have a stink of applied mathmatics, but I think it’s true even for those who’d call themselves pure[5].
This too is true in DevOps, in systems programming, in infrastructure. At the end of the day, we’re toolmakers.
In my mispend youth, in the grips of startup culture, the idea of the elusive 10x developer, while just a mirage was still very alluring. Regardless of the obviously wrong and problematic discurse related to it, there is no doubt that some people move mountains, and others don’t. I wanted to move mountains.
What I’ve later came to learn is that’s just an illusion. The idea of the lone genious, burning the midnight oil is just a myth. John Carmack, Linus Torvalds, George Hotz, they’re just a personality cult.
And this isn’t just some clever insight I’ve come to, it’s stolen. But I like my iteration on it.
A certain Archmage of Infrastructure has the right idea about being a “force multiplier”. What really matters to move these mountains is to enable those that want to move them. The most dedicated cyclist in the world will cycle less than an average bikesmith will enable others to do.
In this creating of tools, and in this care work of maintaining them, we are force multipliers, and in our multiplication of force, the impossible becomes possible.
This is the point of DevOps. This is the point of infra. This is the next level of abstractions hackers should strive for if they wanna boil the ocean.
Post-Credit Scene
From 5:00-19:00, for two days, I had hacked. 3 meals a day, hydrating, and a walk in nature had supported this endeavor[6].
At last, a knock on the door, my partner had come home. After a hug and some pleasantrise, came the question:
So, what did you do with your weekend?
I eagerly typed eza in my terminal emulator, and showed how there were now letters next to the entries, and clicking them copied the text.
What should have been pure awe was a look of slight concern, followed by a shoulder shrug and a kiss on the forehead.
That’s all you did while I was gone?
It’s all love, I bet it’s just a bad screenshot on their git repo <3 ↩
And we’d never scrape a website, that’s rude :^) ↩
“Arabella Stone, Nashville’s darling, is eager to shuck her prim-and-proper rep, and a few wild months spent checking items off her ’ summer bucket list’ is the way to do it. First up: kiss the man she’s crushed on since she wore a training bra, the bad boy of country himself, Blue bassist Charlie Tucker. For Charlie, a beautiful woman flirting with him isn’t out of the norm—but a beautiful woman bolting after the hottest kiss of his life sure is. And when he finds out his kiss-and-run Cinderella is none other than Arabella Stone, daughter of his label’s CEO, he knows he’s in trouble. Because not only is she a Stone, she’s also his employee for the next few months at the recording studio he just bought. Over the course of one thrilling summer, Arabella and Charlie chip away at her bucket list and fight the simmering attraction between them…knowing that once it’s all over, so is their time together.”
Steamy. ↩
Which really should be called theoretical. ↩
All this rise and grind never sleep never eat never enjoy your life stuff is stupid. If you wanna be even like mildly consistent, you gotta get this right. Dumb stuff like hacking is like the last thing you get to in mazlows hierachy[7] for a reason. ↩
Yes, I know it’s “debunked”, it’s a working model geez louise. ↩
