Benjamin Esham

A Dream of Zsh

Last night I had the strange sensation that as I was dreaming, my conscious mind was also turning over a programming idea, one that still kind of made sense when I woke up: what if I were to write a static site generator… in zsh?

Maybe it’s not as crazy as it sounds! Think about some of the things that shell scripts make easy:

And at a high level, what does a static site generator do?

For a number of reasons which aren’t particularly interesting, I’ve grown dissatisfied with Jekyll, the tool that generates this site right now, and I’ve been thinking about the form a replacement might take. (Like many hapless programmers, I would want to create my own.)

I use Haskell and zsh for most of my hobby programming. The former would be the obvious candidate for a Serious Application like a static site generator, but maybe the latter is suited to the problem domain too. To be sure, it wouldn’t be very fun to parse my Markdown files’ YAML headers with a shell script; there are disadvantages to using a language whose two types are “string” and “strings.” Shell scripts are also not exactly known for their speed. But zsh in particular lets you write text manipulation one-liners which in Haskell would require a Ph.D. and three Monoid instances.

If I do take the plunge and write my own static site generator, I’ll probably end up doing it in Haskell. But I’ll keep the possibility of a zsh version in the back of my mind. I could call it Tartini.


The idea of microblogging on my own website is something I’ve been kicking around for years. Instead of posting short pieces of text to Twitter, longer pieces of text to this blog, and photos to Instagram, why not just post all of that stuff here? I could still cross-post to other sites if I wanted to, but my intention has always been that this website should represent me on the web and so it only makes sense to put all of my work here.

My microblog is a new part of this site where I’m posting the kinds of things that I posted on Twitter and Instagram. I’ll still post things on those sites for the foreseeable future, but only a subset of the things I’m posting here. You can follow my microblog using a feed reader (well, more on that later) using the links on my new feeds page.

Why bother posting on my own site?

Posting to Twitter and Instagram is pretty frictionless and it’s easy for people to find my stuff there. Why would I bother to post here instead of there? Control. By posting here I have complete control over how my stuff is presented; there’s no advertising and there are no creepy trackers exfiltrating your browsing history. I have the ability to edit my posts and delete them (as much as anything can be deleted from the internet, anyway).

You shouldn’t have to be beholden to some giant company to host the stuff you made. Even if their intentions were good—and this is a little harder to believe every day—how good is Instagram’s customer service if you need it? How easily can you get in touch with a human being at Twitter? It’s a cliché but it’s true: you are their product, not their customer. At best, you’re their user, and then just one of millions (or billions). Practically speaking, you have no recourse if they change something you liked or break something you relied on.1

Aside from that, it’s nice to have one website that holds everything you’ve posted. Maybe there are also copies of those things on other sites, but you know you have a copy on yours.2

The problems

There were two things preventing me from microblogging here sooner. The first was a personal form of not-invented-here syndrome: a self-defeating desire to make all of the parts of my website myself. I’ve gotten comfortable writing plugins for Jekyll, the program I use to generate my site, but if I added Twitter and Instagram posts here I’d need (well, want) to create a bunch of machinery to listen for new posts on those services and copy them here (or else take each new post here and copy it there).

That was a daunting amount of work which didn’t seem worth it because of the other thing holding me back: most of my Twitter posts are tossed-off, snarky, timely thoughts that often don’t have a lot of value a month later (and sometimes don’t have much value to begin with). Why would I go through all the time and effort to bolt these on to my website when I felt like some of them barely deserved to be posted to Twitter?

Technical solutions

The technical problems, at least, were partly solved for me. The first thing that happened was the introduction of, a Twitter alternative that emphasizes owning your own content (and which has taken an unequivocal stance against the kind of harassment that Twitter has become known for). is a full-fledged online community, but I really only use it as a means to cross-post some of what I write here to Twitter.

I also learned about OwnYourGram, a service run for free by Aaron Parecki that will periodically look at your Instagram posts and send the new ones to your site using the Micropub protocol.3

Getting my site to speak Micropub was a pile of work, but it was an interesting project and it means that I can also now take advantage of the other tools in the Micropub ecosystem, like Quill (another Aaron Parecki production) for posting notes. Relying on external services like and OwnYourGram isn’t my favorite thing but it makes way more sense than duplicating all of that work just to be able to say that I did it myself.

Just Don’t Do It

Technical hurdles cleared, what made me decide to actually start microblogging on my own site? Posting my photos here was an easy one: copying over my previous Instagram posts, and mirroring all of my future ones, jump-started the photoblog I had always intended to create.

I was ambivalent about putting Twitter-like posts on my site, since so many of them have only ephemeral value. I had a simple realization: don’t post something on the internet if you wouldn’t want it on your own site. It takes self-control for me not to post snarky jokes on Twitter, but it’s an easy choice not to post that here. And if it doesn’t clear that bar, is it really adding anything to the discourse? Is it doing anything positive for society? If I’m honest… probably not. Once I set this bar for myself, I felt fine putting these kinds of posts here.

(Incidentally, a little while after I started microblogging on this site, I fired up a Mastodon server and started posting there too. I immediately found myself posting the kind of drivel I had recently stopped posting to Twitter. In the future I’m going to treat my Mastodon account as just another cross-posting destination for the things I write here.)

What I’m doing now

I mentioned that there’s a microblog section of this site now. I imported all of my Instagram photos as well as my posts from,, and Mastodon. (I left out reply posts, which would be awkward to copy to my own site.) I’ll probably copy my Twitter posts here at some point, but there are a lot of them and I’m not sure yet what I’m going to do with the at-mentions and things like that.

In the future I intend to post things here first. If I post to those other sites it will just be cross-posts of my posts here or replies to discussions that are happening there.4

There’s a big downside to me posting to my own site. How are other people going to interact with me? How are other people even going to see my stuff? There’s no opportunity here for the serendipity you get on dedicated social networks, where you see something your friend liked and that gives you a new person to follow.

I am publishing my posts as feeds, but how do you link someone to a feed? Even for the few people who actually have an RSS reader set up, reading someone’s social timeline in a feed reader is still an awkward prospect. The interfaces are generally less suited to showing a large number of short posts; some readers don’t even support posts without titles.5 And how do you like a post or retweet it? There are efforts underway to create the standards, the APIs, and the implementations of better social readers, but it’s going to be at least a couple of years before any such effort is as approachable to the average person as Facebook and Twitter are now.

Things are getting better here. I don’t think there’s ever been so much interest in—or effort being put into—wresting our online social lives back from the Silicon Valley giants that control them now. It remains to be seen whether taking control of your online presence will ever be cheap and easy enough for everyone to do it. In the meantime, I don’t mind blazing some of the trail myself.

  1. You’re going to be relying on big companies even if you host everything yourself; you need a domain name, at the very least, and you’re probably going to rent a server instead of maintaining your own. There are two important differences between this situation and the one with the social-media giants, though. First, you’re actually paying these companies, which means they have an incentive to provide at least some level of service. Second, if one of these companies doesn’t meet your needs in some way then there are viable alternatives you can use instead—and switching from one blog host to another makes no difference to your ability to interoperate with other blogs. It’s not like Facebook, where you can only interact with other people who are also on Facebook.↩︎

  2. It’s possible to take this too far, though, I think. If you post a comment on, say, Reddit as part of a discussion, it doesn’t usually make sense for that to be posted by itself on your site. (And if you copy other people’s comments onto your site for context, you start to run into moral and legal issues.)↩︎

  3. Instagram’s API doesn’t have any provision for posting photos, which means that it’s not possible to post photos on your own site and then copy them to Instagram—you have to post them to Instagram yourself using the app. If you want an automated workflow then you have to start by posting to Instagram and then copying to your own site.

    Compare this to how lets you post to Twitter by posting on your own site first and then copying to Twitter. In the IndieWeb community, the former flow is called PESOS (“publish elsewhere, syndicate to your own site”), while the latter form is called POSSE, for “post on your own site, syndicate elsewhere.”↩︎

  4. I’ve been thinking a lot lately about something Ryan Barrett wrote about online communities. Both he and I are mostly looking to interact with people we already know. I’m “on” and Mastodon, both of which have the potential to become nice online communities, but I’m not trying to find new people to hang out with—I want to keep talking to the people I already follow on Twitter or know in real life.

    For me, the sole killer feature of an online community is who’s in it. That’s the reason I’m still on Facebook even after all the crap they’ve pulled.↩︎

  5. Feed readers are starting to catch up. Feedbin, the reader I use, has added native support for following Twitter accounts in the same interface that you use to follow other feeds.↩︎

Do Not Disturb On Weekend Mornings

With each new release of iOS it becomes a little more ridiculous that you can’t set separate weekday and weekend schedules for Do Not Disturb. Do Not Disturb prevents your device from lighting up or making noise when you get a notification, and since its introduction in 2012 it has let you specify times of day when the feature should turn itself on and off. This fall there are a lot of DND improvements coming—“do not disturb until the end of this event,” “do not disturb until I leave this location”—but this most obvious feature is still not there. Lots of people go to bed and wake up at different times on different days of the week (with the Monday-to-Friday workweek being just the most obvious example) and want their notifications silenced automatically while they sleep.

In 2013, a bug in Do Not Disturb kept it from shutting itself off automatically for the first seven days of the year. The bug seemed to be caused by Apple’s developers using the ISO week year when they wanted the Gregorian year, which gave me hope that more sophisticated scheduling was going to become possible. After all, it’s not clear why a simple “on at this time, off at this time” schedule would need to consider year numbers in the first place. Long after that bug surfaced, though, Apple still seems to have no plan to let people set different schedules on different days of the week. My dog may not understand that I want to sleep in on weekends, but my iPhone should be able to.

Versioning and backward compatibility

Zhouwei Zhang wrote an article recently called “These 299 macOS apps are so buggy, Apple had to fix them in AppKit.” Ignore the clickbait title for now; the article shows that macOS’s AppKit framework reverts to older, sometimes buggier behaviors when it’s running certain high-profile applications. Microsoft has long had a reputation for bending over backwards in their OS to keep apps running well; Apple has not had such a reputation but it seems like they’ve still done plenty of that kind of work.

This reminds me of another article I read recently, “What’s better than semver?” by Graham Lee. In discussing the Semantic Versioning style of version numbering, where version numbers look like x.y.z and a change to z indicates “backwards compatible bug fixes,” he writes,

There is no such thing as an “internal change that fixes incorrect behavior” that is “backwards compatible”. If a library has a function f() in its public API, I could be relying on any observable behaviour of f() […] If they “fix” “incorrect” behaviour, the library maintainers may have broken the package for me.

As longtime Apple employee Chris Espinosa said on Twitter of the AppKit special-casing, “Often [third-party developers] were working around our bugs.” That’s why the “so buggy” part of Zhang’s headline is undeserved. It’s also why it’s usually silly for a library developer to claim that they’ve fixed a bug but remained backward compatible. Sure—if your library contains an algorithm that could be O(n) but is accidentally quadratic, fixing the performance while keeping the semantics the same is backward-compatible. Adding a new API is usually backward-compatible. But fixing a bug in your sorting algorithm—as Apple apparently did one time, breaking some Microsoft Office apps—is potentially a breaking change, and I think this is something that library authors (and versioning-scheme authors) need to consider.1

Contrary to Clojure’s Nihilistic Versioning philosophy (“version numbering is hard so let’s not even try”), I think that making breaking changes is okay. Bugs happen, but bugs should be fixed even if that breaks someone’s workflow. Rewriting a library to take advantage of the lessons you’ve learned makes things better for you and for your future consumers.

The most important thing for library authors is just to communicate what’s changing in each version. This should happen at two levels: the eye-catching but unspecific change in a version number and the more detailed and nuanced2 information in the project’s changelog (or GitHub releases page). It’s great if you follow a well-defined scheme for assigning version numbers but writing good documentation might be even more important.

  1. Haskell’s Package Versioning Policy uses numbers like a.b.c, where both a and b are part of the “major version number.” This lets you distinguish between smaller breaking changes, like fixing a sorting algorithm hopefully is, and larger changes like rethinking a library’s interface.↩︎

  2. It’s possible for a library to have a “breaking change” that turns out not to actually affect any of its consumers—in fact, this is more and more likely the more pedantic you get about what constitutes a breaking change. Along the same lines, version numbers matter a lot less if you know every single one of your consumers and can discuss potentially-breaking changes with them beforehand.↩︎