Fire and motion

Responsive colors for the Bash shell prompt

Here's a Bash shell tip for changing the prompt's colors to indicate the success or failure of the last command. You can set the background or foreground colors based on an arithmetic expression.

Let's set the background to green for successful commands, and red for the commands that failed. We'll use the commands "true" and "false" as handy example commands.

The trick is that bash's (( )) construct lets you evaluate $?, the exit status of the last command, when it evaluates $PS1.

From Bash tips: Colors and formatting we can see that \e[41m is the control sequence for the red background color and \e[42m is the control sequence for the green background color. So what we need to do is create an expression that evaluates to 42 on success (exit status 0) and 41 for any other value of $?


So the expression we use is: ((!$?+41)).

If $? is 0, then !$? is 1, and ((1+41)) = 42. Otherwise, if $? is anything but 0, then the expression becomes ((0+41)) = 41.

For my PS1, I use the 256-color black background \e[48;5;16m for successful commands, and a deep red \e[48;5;52m for failed commands. So the math becomes a little more complicated:


My expression is ((!!$?*36+16)). Successful commands (exit code 0) make !!$? evaluate to 0, so we get ((0*36+16)) = 16. Otherwise, it becomes ((1*36+16)) = 52.

Using a little math you can customize your bash prompt in various ways to indicate the success or failure of the last command!

Edit: The only constant is change

The truth is, I've since changed my prompt. Here's what it looks like nowadays:


I don't just use bash's arithmetic construct anymore, I use an "if" expression in the prompt to decide to print the checkmark or the cross-out character. I think this is more pleasing then the change in background color. It sort of corresponds to the following:

PS1='$(if [ $? -eq 0 ]; then \
   echo -e "\[\e[32m\]\xe2\x9c\x93"; \
else \
   echo -e "\[\e[31m\]\xe2\x9c\x97"; \
fi) \[\e[38;5;242m\]\w$\[\e[0m\] '

Into the Next Dimension

pixel_art_watermark_256.pngA few years ago, I created an 8-bit pixel-art version of my avatar that had a predominately blue sky and a small version of myself offset a little towards the right.

The new avatar lasted for a few years. However, I grew older, grayer, and balder and my avatar didn't.

I wanted to update the avatar, but I didn't want to "cheat" the rules of my pixel art. Any changes I made had to be made while retaining the 16x16 pixel dimensions of the icon.

I updated the pixel-art image to make the hair thinner (more semi-transparent at the top), and grayer on the sides above the ears, and I moved the part in my hair to the correct side.

And then Trump got elected to be America's next President, and everybody seemed to be more divided than ever.

avatar_thinking_earth_256.pngI wanted to add a suggestion to my avatar that I care about what's happening in America and how it affects everybody. I considered being political, but didn't want to further the divide between the right and left amongst my friends. Eventually I settled on the idea that my avatar should be shown to be thinking about everyone on the planet, not just one particular challenge. So I made room for a thought-bubble indicating that I was thinking of the Earth as a whole.

That's my attempt (above) at a 4x4 pixel-art earth in the thought bubble. Hope it worked!

magicavoxel_avatar_glasses.pngEventually, I started seeing charming voxel artwork being done with magicavoxel. This seemed like an opportunity to see if I could translate my 2D avatar into 3D. Challenge accepted!

So here's my latest avatar: A 3D 8-bit voxel version of myself thinking about the world. I kept it as faithful as possible to the 2D pixel art version. Nowadays, I have to wear glasses to read, so one version of my avatar wears glasses, and another doesn't.

I think I can live with this for a while. Let's see how it goes!

Did you notice the cheats? The nose isn't aligned on voxel boundaries. The eyes are two voxels apart, so the nose is one voxel wide but positioned a half-voxel from each eye. It's also only half a voxel deep, but that's really hard to tell. And of course, the glasses are at 1/8 voxel scale. But for some reason, I allowed myself these cheats in the voxel version.

My TechCrunch Feed Filter

It's the the sixth anniversary1 of my TechCrunch Feed Filter. In Internet time, that's ages. A lot has changed. Here's a look back.

The Problem

TechCrunch was a great blog about innovation and entrepreneurship. As it grew, it published more articles than I cared to read. Like many savvy blog readers, I used a feed reader to present the latest articles to me, but TechCrunch was simply too profuse.

The Solution

I created a service that'd visit TechCrunch's feed, and make note of who made which articles, what the articles were about, how many comments each article had, and how many Diggs2, Facebook likes and Facebook shares each article had.

With that data, the service would determine the median, mean, standard deviation, and create a minimum threshold for whether the article merited being seen by me. The raw data is stored in a live yaml file. There were some special rules, like, "If the article is by Michael Arrington, or has "google" in the tags field, automatically show it to me." Otherwise, other readers had to essentially vote the article high enough for it to pass the filter.


In the picture above, you can see that two posts out of seven met the criteria to be in the filtered feed. They're the ones with the gold stars. The threshold was calculated to be 116 shares, and you can see in the graph when each article had more than the threshold. (There's a red circle at the point the green shares line rose above the blue area that designates the criteria level.)

Once the service knew which posts were worthy of my attention, it listed them in its own filtered feed.

Changes over Time

In the beginning, TechCrunch used WordPress's commenting system. As such, its feed included the slash:comments tag. At the time, that was the best metric of how popular a TechCrunch post was, better than Facebook shares. But TechCrunch started experimenting with different commenting systems like Disqus and Facebook comments to combat comment spam. Neither of those systems used a standard mechanism to get comment counts, so every time it changed commenting systems, I had to change my service.

Digg, whose Diggs were once a great metric of the worthiness of a TechCrunch blog post, faded away. So I had to stop using Diggs.

So that left Facebook's metrics. They weren't ideal for assessing TechCrunch articles, but they were all that was left. Using Facebook likes and shared worked for a while. And then Facebook changed their APIs! They once had an API, FQL, that let you easily determine how many likes and shares an article had. The killed that API, leaving me with a slightly more complicated way to query the metrics I need for the service to do its work.

Not The End

I've had to continuously groom and maintain the feed filter over these past six years as websites rise, fade, and change their engines. And I'll have to keep doing so, for as long as I want my Feed Filter to work. But I don't mind. It's a labor of love, and it saves me time in the long run.

1 One of the original announcement posts.

2 Remember Digg? No? Young'un. I still use their Digg Reader.

Backup Solutions: Choosing


In June 2013, I investigated various online backup solutions, and decided on a hybrid solution: Use the free 5GB of iCloud and then backup the rest to DreamObjects.

That didn't work out.

  • boto-rsync only uses file-size to decide to update a file. There'd be too many false negatives for my comfort level.
  • I was still using DreamHost Backup which uses rsync proper, and the first 50GB were free. At that price, it was irresistible.
  • If I used duplicity, I wasn't comfortable (yet) with the cost associated with the incremental backups to DreamObjects.

It's a new world. And it became time to revisit my remote backup strategy.

  • Windows 10 will support Bash soon! This means I could use the same rsync scripts from each of my devices whether Raspbian, other Linux, Mac OS, or Windows. (And without having to use cygwin!)
  • "If you're not the customer, you're the product." I observed this fact when I used OpenPaths, and its service became unavailable. And again while I was backing up to DreamHost Backup, and it was discontinued. No more free remote rsync for me!

And then I discovered I don't know why I hadn't noticed them before, they've been around for years. It turns out that theirs is the service that I've been waiting for.

  • I'm the customer. I pay for the storage, so they're accountable to me. I've only heard good things about their customer support.
  • And as far as rsync itself is platform agnostic, so is their service. And I'm already using rsync for local backup on all my computers. Setting as my remote backup was very easy.
  • I already treat confidential data specially, so even on local disk it's encrypted.

I'm really happy with, and my Windows environment is going to be even more straightforward when I can use Windows Subsystem for Linux (WSL). The devices I'm still not certain about are the family's phones. Here's what we're doing so far.

  • We're doing rare full phone backups to local computers.
  • We're using Google Photos apps to sync photos more frequently from the phone to the cloud. (We're Google's product. It's a deal with the devil, I know.)
  • I use a different source for Contacts and Calendar data, and the phone is merely a sync target, never a source.

Two oddities that WSL might make better

I have to have two strange lines of code because I use CygWin and rsync to back things up. Applications like PuTTY, which store preferences in the Windows Registry, and FileZilla which store preferences in %APPDATA% need special treatment.

I copy PuTTY's settings to my Documents folder.

regedit /e "%USERPROFILE%\Docs\PuTTY.reg" HKCU\Software\SimonTatham

I backup FileZilla's settings explicitly.

rsync $(cygpath $APPDATA/FileZilla)

Who knows? Maybe there'll be another update about my backup strategy in the future.

Photo by Jill Laurie Goodman / CC BY-NC 2.0

How not to Monetize RSS and Atom Feeds


An RSS or Atom feed is a live document of recent events or items. For example, there are feeds of Twitter tweets, Facebook posts, and YouTube videos. Usually, other programs track the feeds, and then let you know when there's something new.

You can do other things with feeds, too. I've collated a few of my personal feeds into a Lifestream that updates automatically. It's a very convenient hands-off diary.

Companies like Twitter and Facebook have been trying to figure out if they should monetize feeds. They already inject ads into their main user interfaces (into Facebook's users' walls, and onto the Twitter timeline, for example), but what should they do about the feeds for the same information? So far, they've left feeds alone.

This week, Delicious tried injecting ads into its users' bookmarks feeds. The bookmarks feeds are activity feeds, because they reflect actions that the users have taken. On Delicious, users bookmark sites that they find noteworthy. So these new ads are clearly marked as Sponsored items, because otherwise it would look like everyone suddenly explicitly bookmarked the ad's product. That'd be straight up deception.

Still, there are problems with the way that Delicious is embedding ads into their users' activity feeds. To ensure that the ads are at the top of the list, they're always coded with a pubDate ("Published Date") of the current time. This goes against the original intent of these feeds, where each item's pubDate doesn't change if there's no actual change to the item itself. Old ads should get old, too.

Instead what happens is that every time the feed is fetched, since there's always a "new" item (the same old ad, but with a new, just-now pubDate), is that Delicious can no longer return HTTP code 304, which means, "I'm not providing the feed again, it hasn't changed since the last time you got it."

This is causing Delicious to be slammed with having to deliver full feeds for every request, and for all the clients to have to process what look like brand-new feeds. Beyond that, people who auto-tweet what they bookmark are all inadvertently tweeting ads now.

How did I discover this in the first place? My Lifestream started journalling that I've been repeatedly bookmarking the same ad over and over again.

That's not the way to monetize activity feeds.

« Previous Page