dotenv and direnv for better developer QoL

The latest RubyTapas tutorial taught me the difference between the dotenv and direnv tools. While they have significant overlap, they complement each other quite nicely. dotenv simplifies both development and production ops by importing environments variables either from a .env file or the application hosting platform. direnv on the other hand augments the dev environment even further; not only can it add dev-only variables but also modify shell settings like extending $PATH on a per-project basis.

Verify your assumptions

That’s what I keep preaching to my team but still fail at myself every so often.

This week, I wasted a whole day implementing a fix for a bug that wasn’t there. My task was to add one line to a configuration file in a Chef cookbook. When I ran its test suite, it surprisingly failed and it was clear that my simple change couldn’t be the cause. I assumed it was due to recent changes in software packages installed by the cookbook. So I started adapting our old code to these changes, and one change led to another, and another, until I finally realised that over the course of multiple hours, my one-line bugfix had turned into a full code overhaul. How did I get here?

I decided to start from scratch. git reset --hard HEAD. I quickly fixed my config file and ran the tests. When they failed again, closer inspection revealed that it was actually just the same test failing twice. The cause was a bug that had found its way into the main branch without breaking the CI pipeline (finding the reason for this will be interesting). It had been there all along! After another one-line fix, my change was ready for review. Round 2 had taken me less than half an hour.

The lesson: Don’t rush into battle blindly. Look closely. Identify assumptions and verify them. It might just be windmills!

Weeknote W5 2021

To tile or not to tile

Looking at Twitch streams and Youtube videos around Linux, it seemed to me that everyone was into tiling window managers. This week, I decided to finally try this approach of filling and subdividing the whole screen area. On macOS, I installed yabai, and on Linux (more on that below), I chose the popular i3.

After a few days of the tiling life, my conclusion is that I don’t see much benefit in forcing my application windows to fill up all the available screen real estate. Maybe it’s because I already have a habit of tiling my windows manually – when it makes sense. However, often it just doesn’t make sense. Some windows really don’t like to be squeezed into a tiny space, and even on a 13” screen, a full-size terminal window isn’t of much use to me. I’ll keep my windows floating. If I really want to tile them, there’s always BetterTouchTool.

Linux on Apple hardware

Another item of curiosity this week (is this some kind of lockdown syndrome?) was if 2021 could be the year of Linux on the Desktop for me. While I still enjoy the stability and user-friendliness of the macOS ecosystem, some of its constraints do annoy me from time to time. I have an unused Macbook Pro 13” from 2015, and it’s now running Ubuntu 20.04. My go-to applications like Brave, VS Code and Obsidian worked fine out of the box. But when it came to more specialised use cases, I quickly realised how much macOS spoils me with its choice of well-polished applications.

Maybe I will pursue a “best of both worlds” approach, where I do my management work on the Mac and my DevOps work on Linux. That is, if the hardware issues that drove me into Apple’s arms more than a decade ago don’t spoil it for me again. For example, there’s a 50:50 chance that after powering up the laptop, Bluetooth doesn’t work, preventing me from using a proper mouse and keyboard. Sigh.

Clean Chef code: Depend on public cookbook interfaces

For about a year, we’ve been cleaning up the Chef Infra code for freistilbox to make updating dependencies, Chef versions and even operating systems easier. It’s a lot of work because our early code is functional but not pretty. There have been many instances of “we didn’t know better”, and that’s what refactoring is for. But I also came to realise that we were missing a critical fact: Common software engineering principles and practices apply to infrastructure code like they do to any other type of code.

Or as early Chef developer Joshua Timberman puts it:

“Hey, ya’ll remember when devops really just meant you knew how to write all your bash in ruby instead?”

Ouch. Making this connection earlier would have saved us weeks of work. That’s why I’m going to share my findings in a series of posts.

In this post, I’m going to advocate for treating a Chef cookbook as a unit of software that provides explicit interfaces instead of tempting its users to depend on implementation details.

Chef Infra cookbooks use node attributes as variable parameters for system configuration. In software engineering terms, node attributes are global variables. They’re implementation details of a cookbook. In consequence, using a cookbook’s node attributes for any purpose other than defining setup parameters creates a dependency on implementation details which can change at any time.

For example, it’s common practice to use a search on node attributes for service discovery. As node attributes are global variables, any cookbook can do this:

service_nodes = search(:node, "webservice_id:myservice")

From this code, we can tell that web service nodes are identified by a node attribute named webservice_id; nodes sharing the same webservice_id value belong to the same web service.

The problem with using this information outside the cookbook which provides it is that this particular implementation can change at any time. This kind of tight coupling is a liability. For example, a second attribute webservice_status might get introduced, reducing the node set by adding AND webservice_status:active to the query. Since this change in semantics is not necessarily a breaking change, there’s no simple way like semantic versioning to inform everyone who depends on this unofficial interface.

How about we provide an public API instead? Our web service cookbook could for example provide a class we can use for service discovery:

webservice ="myservice")
service_nodes = webservice.nodes

This is easy to implement as a cookbook library. By using namespaces, we make sure that method names don’t conflict. In my practice, I tend to use the camel-cased cookbook name under the namespace Cookbook and the company namespace.

With service discovery encapsulated and hidden behind a public interface, we could even reimplement the cookbook’s service discovery using a different technology like Consul without breaking any code outside our cookbook.

But even if other cookbooks depending on our implementation isn’t a concern, implementing auxiliary logic in a central library instead of scattering it across recipe files makes it much easier to maintain. I’m going to talk about “Plain Old Ruby versus Chef DSL” in a separate post.

DIRECT - The seven core topics of remote team communication

Pick any guide on remote work (oh, there are so many…) and it’ll tell you that communication is essential when you work in a distributed team. The problem is that it’s not obvious where exactly the centre of balance is between sharing too little and sharing too much. That’s why I’ve created a framework that uses a simple acronym to remind you of good opportunities to keep your distributed team in the loop.

You can watch it here or on YouTube. I’m already working on my next videos, so don’t forget to subscribe to my YouTube channel!


Despite working on a Mac, I’m using the mouse/trackball less and less. I’ve installed Vimium in my Brave browser; it allows me to follow links by selecting them with easy-to-type letter combinations.

I’ve also programmed my keyboards to send arrow keys when I hold the space bar and press the H, J, K and L keys. That way, I can move the cursor and scroll a page without even leaving the home row with my fingers.

My Daily Bootup checklist

With such a huge number of people suddenly thrust into working from home, I thought I’d share a bit of my experience (more than 10 years, actually) with doing Remote Work. I started a new morning livestream called “The Daily Bootup”. It’s named after the checklist I use to start every workday. This checklist helps me keep track of my goals and to-dos, especially my most important tasks (aka “MIT”). This is how it looks like:

  • Check my calendar for the day
  • Check my weekly goals
  • Check my to-do list
  • Check other sources of work
  • Schedule my MIT
  • Write a 5-Minute Journal entry
  • Send a team check-in

Let’s take a look at each checklist item in detail!

Check my calendar for the day

Before I can start planning my work for the day, I have to get a feel for how much of the day is already predetermined by appointments and repeating events. That’s why I first check my calendar.

Check my weekly goals

I use weekly goals to guide my focus. On Mondays, I define one or two important results I’d like to achieve by the end of the week. Every other weekday, I reference this definition (which I share with my team on Basecamp) to keep me on track.

Check my to-do list

Unfortunately, I’m still living in a world in which there are tasks that I have to do no matter what, and deadlines that I haven’t set myself. My to-do list helps preventing them from falling by the wayside.

Check other sources of work

On top of my primary to-do list, there are other systems that tell me things that need to be pushed forward. Sales deals in our CRM and incident follow-ups are only two examples.

Schedule my MIT

At this point, it’s finally time to define today’s work by entering tasks into my calendar. For me, a time boxing approach has been working best to make sure that I put in the work to get the important things done in time.

Write a 5-Minute Journal entry

Many people recommend picking up journaling as a daily practice for reflection and recording one’s thoughts and feelings. Instead of doing free form writing, I have a 5-Minute-Journal template in Day One that asks me three things every morning: “What are you grateful for?”, “What would make today great?” and “What’s your daily affirmation?”

5-Minute Journal

In my experience, a gratitude journal is a great way to keep myself on the positive side of things. Listing the things that are good in my life takes effect while I’m writing them down, and again when I read these entries two weeks or many years later.

Send a team check-in

As the final step in my morning routine, I submit a form that our team uses to tell everyone what to expect of ourselves today. It does so on multiple levels because it lets us not only enter our main goal for the day but also our mood and additional information that might be helpful for dealing with us. I haven’t yet tried to analyse the data. For now, it’s just nice to quickly see who’s feeling excited and who’s already tired at breakfast time.

Team Check-In

So that’s my Daily Bootup routine! Let me know on Twitter or what you think of it. Or how about you drop by on Full Stack Live? I do “The Daily Bootup” weekdays from 9:30am to 10am (Ireland/UK time) and would love to have a chat!

Weeknote 13/2020

Learning JavaScript

While I’ve learned more than a dozen different programming languages in my three decades of using computers, I’ve been focusing on Ruby for the last one. At my company, we automate our hosting infrastructure with Chef, we build our websites with Rails or Jekyll, and even for more complex command line scripts, Ruby has replaced Bash for us. But lately, I’ve actually added another programming language to my roster that I wanted to learn for years: Javascript. With StimulusJS, it was really easy to add a bit of client-side logic to our hosting dashboard. There’s a lot to learn and I’m really looking forward to doing more frontend development!

Icons for everything

Talking about frontend: Iconography is an important part of every user interface nowadays. Of course, the internet offers endless supply of icons but many of these collections are of low quality, have unclear licensing policies or are of a quality that doesn’t justify their price. Discovering the Noun Project has solved this problem for me completely. I’ve started using their icons on web sites, in my talk slides and even to give my Stream Deck a more consistent look:

Stream Deck

Live stream for remote workers

With so many more people now working from home (and struggling with the change), I thought I’d share my 10 years of experience with remote work. I’ve started doing a 30-minute live stream over on my live coding channel every morning at 9:30am (10:30 on the continent) where I chat with viewers about how to make remote work… work. The stream is titled “The Daily Bootup”. How about you join me Monday morning and we start the day together? Simply click “Follow” to get a notification when we start!

Managing multiple Git identities

I’ve always been struggling to use the right name and email address, separate between work and personal projects, for each of my Git repositories. Micah Henning solved that problem nicely by removing the global settings but making a repo-specific configuration mandatory. And a handy alias is the icing on the Git identity selection cake.

The Live Coders Conference

There won’t be many conferences in the next few weeks, at least not the sort that you need to attend in person. However, with COVID-19 handing out lemons, people start to discover the lemonade of online conferences!

I’m happy to be part of an initiative by The Live Coders, a community of people broadcasting their software development on Twitch. On 9th April, we’re going to broadcast more than 12 hours of presentations on a wide range of topics. With my talk about burnout prevention, I’m probably going to have a slot in the (European) afternoon.

For details, check out The Live Coders Conference. Andy, one of the organisers, also did a write-up on Setting up an online conference.

When terminals were real tty’s

For my first Retro Saturday live stream, I chose working with a PDP-11 minicomputer. I don’t own a PDP-11, nor can I afford to buy or run one, but I can simulate one realistically usingsimh, the simulator for historic computer systems.

After successfully installing Unix V7, the original Unix operating system from 1979, I ran into unexpected issues with entering source code. One of the problems was the lack of a full-screen editor combined with my lack of ed skills. Another problem was that the Backspace key didn’t work as expected; an issue I first encountered 27 years ago trying out an early version of Linux. And then there was the strange behaviour that I had to escape the number sign at the beginning of #include <stdio.h> with a backslash; otherwise it would disappear.

After the stream, I found out what the problem was: V7 was simply still geared towards being operated from a teletype, basically a typewriter with a serial port. (It would take many years until typewriters actually came with correction ribbons that enabled you to erase and overwrite. But by that time, teletypes had been replaced by serial terminals with CRT screens.)

On an input device that prints each character you type immediately on paper, it’s impossible to do what Backspace does. That’s why the Unix developers assigned special meaning to the # and @ signs.

The # sign tells the V7 shell to ignore the previously typed character. Correcting a typo would look like this: cat memp#o.txt.

For larger errors, there’s the @ sign. It tells the shell to ignore everything before it. For example: rm mem@mv memo.txt memo.bak.

Exploring historic operating systems has become a passion for me lately. Not only do I learn a lot about early computing technology. It also makes me appreciate so much more the achievements of pioneers like Thompson and Richie who didn’t have any of the conveniences software developers enjoy today.

2.11BSD seems to be a more user-friendly OS for the PDP-11, so that’s what I’m going to try next!

If you have any questions or would like to discuss a topic, tweet me @geewiz or join the chat on my Discord server!