A Tale as Old as Time
Ch1. Humble Beginnings
Once upon a time, there existed a software engineer who resided continuously hunched within a dreary cubicle - adorned with demotivating motivational posters and speckled with horrendous fluorescent light from above. The day was coming to an end and they were just about ready to clock out.
Their eyes - gleaming with some sign of life, particularly boredom - glazed across their MacBook's fingerprint-smudged screen. The employee had realized that they needed to complete one last operational task before ending their remarkably unremarkable day. "Let's get this over with," they say with a rapturous murmur.
"Okay, simple enough, let's download a Docker image from the registry that this project uses for containerized builds. I'm sure the command is in my terminal history."
Ch2. The White (Docker) Whale
"Damn."
They don't see the command that they are looking for even after quickly tapping the up arrows roughly twenty times.
"No worries, you've done this enough that you can do type it out in no time!"
. . .
"Shit."
They forgot a dash in the internal Docker registry name.
"Alright no worries, up arrow once more and add the dash and enter."
They forgot to supply the registry API token.
"Oh yeah, this again. Let me pull up the secret, I'm sure I have it saved somewhere on my desktop," they say, unfazed. They attempt the command once again.
Ch3. UnaBASHed
"Sweet, the image is downloading. This task is turning out to be no biggie."
Now, it's time to build the project. Lucky for them, it's only a poorly documented Bash command that is incomprehensible because there are twenty pipes (|
) and seven ANDs (&&
) littered throughout. They start praying that it's in their terminal history.
A bead of sweat drips down their forehead.
After a few minutes of terminal history-hunting, accompanied by a orchestra of shallow breathing and stressed-out grunts, they realize that instead of scouring through their terminal history, they could just search Slack to find the command posted in the past by their teammate.
"Brilliant, let's search Slack and just copy-and-paste it!"
Ch4. Pesky Platforms
"Bingo," they say with a smirk, as if they have finally hacked into the metaphorical mainframe everybody seems to mention. The job doesn't permit them to be cool often, or really at all. Thus, the employee has to milk any opportunity they get to feel cool.
They've found it. After a simple copy-and-paste into the terminal session, they hit enter and...
"Fuck. Why is glibc
for node-rdkafka
throwing errors when compiling? What the hell is this shit!?"
. . .
"Calm down... It's just because you're using an ARM64 processor. Easy, all you have to do is redownload that image from the beginning for ARM64 - instead of X86 - and then pass in the platform as an argument in half of the commands. Wait, what were the commands, again?"
Ch5. Subjectively, a Matter Expert
The employee left nearly two hours after everyone else. With one final "win" under their belt, they packed their sleek black laptop bag and swaggered to the elevators.
"This is the work of a hero - a champion. Somebody's got to do it, and just seems like the world has chosen me to be the paragon of excellence," they somehow convinced themselves.
. . .
Legends say that, to this day, the employee does not realize they were the cause of the complete production datacenter outage that cost their company at least a few million dollars.
Epilogue
"Drat," their tech lead says in the customer incident report. "They must have used an old version of the build scripts that didn't run the unit tests. Will make an action item to prevent this for next time!"
. . .
The action item remains in that team's evergrowing backlog of operational burdens tasks.
Moral of the Story?
Wouldn't it be nice if you didn't have to type out the same thing over and over again? Save yourself the time scouring for it in your terminal history, on the web, and in your team chats. Just create your own dotfiles and maintain them!
Dotfiles 101
What are "dotfiles"? Let's start with examples you are likely familiar with. Developers often encounter one of the following "dotfiles" relatively frequently:
.bash_profile
.bashrc
.zshrc
.vimrc
.gitconfig
.gitignore
.npmrc
.yarnrc
.env
If any of these look familiar, then congrats, you have experience with a dotfile! Dotfiles are plaintext files prefixed with a dot. Pretty straightforward right?
Dotfiles are typically used to define configurations for programs, such as shells (Bash, Zsh), text editors (Vim), version control systems (Git), and package managers (NPM, Yarn). In the case of .env
, a dotfile can also be used to store static data such as environment variables.
They can be used in conjunction a special dotfile - your shell profile dotfile (e.g. .bashrc
if your terminal uses Bash or .zshrc
if it uses Zsh) - in order to significantly augment your terminal's "smartness"!
Abstracting Responsibilities
While you can add directly to your shell profile dotfile, I find that this can get unruly really quickly. Instead, I prefer adding to "external" dotfiles and importing them into my shell profile dotfile by using source
to essentially import their contents. This way, I can create dotfiles with distinct responsibilities.
Other than the shell profile name (and other protected dotfile names like those listed above), the names of the following dotfiles are arbitrary. You can use whatever system of grouping works best for you.
Secrets and Exports
One example is a .secrets
or .exports
dotfile, which could export persistent global variables like API access tokens. Bonus points for this one, since it makes it easier for you to share your screen with a colleague or collaborator. This way, debugging sessions - which can often require editing shell profile dotfiles - won't result in you exposing sensitive secrets that you need to have stored locally.
Our starry-eyed employee could have just exported their registry's API token as a shell environment variable here to save themselves the hassle of finding and manually inputting the secret.
Aliases and Functions
More examples are a .function
or .alias
dotfile that could hold all your custom shell functions or aliases. In the case above, the employee could create functions/aliases (depending on the complexity of the logic) that make often repeated tasks much less arduous.
In the story above, the employee could have created an alias to download that specific image and assign it to an easy-to-remember command like pull-my-img
.
Meanwhile, for the build command sequence, which was different depending on the platform required (i.e. X86, ARM64, etc.), they could have turned it a function. This function could then take a parameter, representing the platform, which could easily be substituted into all the commands in the sequence where the platform needed to be specified. Instead of a bulky, hard-to-remember, and easy-to-mess-up sequence of commands, the employee could have just run build-my-project x86
or build-my-project arm64
.
Portability
Last, but not least, dotfiles have the advantage of being hyper-portable. They are extremely lightweight, being plaintext files that are often small and can be made smaller by factoring them into separate files like mentioned above.
Store these on flash media like a thumb drive or SD card and you'll be quickly rolling with a souped-up terminal. Push them to a remote Git repository or cloud storage, and you'll be able to pull your favorite settings, custom functions, and time-saving aliases from nearly anywhere. This makes sharing your setup or setting up a new environment a breeze!