By Max Schumacher (mxschumacher)
I love reading about the development machines of others and want to share my current setup below. There is a risk of procrastinating on actual software engineering tasks by fine-tuning a desktop, but by aggressively stealing drawing inspiration from others, you can get a highly customized setup without too much work. What follows isn’t the result of an afternoon of tinkering, a slow evolution over years has led to the current setup. This evolution is not and probably never will be “done”, new challenges and opportunities come along and I will adapt accordingly. Just in putting together this article I have made several changes.
Friends and family often ask me to fix some IT problem for them. I then get to use their computers, which often take forever for the simplest tasks. You want to open a file explorer? That’s going to take 5 seconds. That is a long, long time for a CPU these days and I am not willing to wait. Given how powerful hardware has become, I want all interaction to be close to instant. (Re-)booting should be quick and painless.
My goal is to have a machine that enables me to be productive. I’m looking for a short path between what I have in mind and what I can make appear on the screen. Common tasks like launching a terminal, switching to another workspace or invoking certain commands in my shell should be easy and fast. Drew DeVault put it well when he said “It’s what so many of us are looking for: a frictionless experience that instantly moves thoughts and ideas from our brain to the screen.”. Common command line utilities can be invoked via short aliases and fish’s based auto-completion are great helpers.
I try not to be dogmatic, I neither believe that CLIs are always better than GUIs, nor do I think it is useful to aim for goals like “you should never have to take your hands off the keyboard”. For tasks like moving files, using git (especially when resolving larger merge conflicts), interacting with databases or changing system settings I have found GUIs to be really useful.
Generally, I don’t want to be interrupted by notifications about software updates or emails. Instead of “push notifications”, I prefer looking at my emails/messages when I’m not busy. “We’re going to need 45 minutes to update your system” is not acceptable to me.
My laptop is a Lenovo T450s with an Intel i7-5600U CPU, 12GB of RAM and an Nvidia GeForce 940m, it’s about 5 years old now. The machine has been through lots of travel and at least one fall. The batteries aren’t what they used to be and my Enter key recently fell off, but the laptop is excellent overall. As of now, I don’t use an external screen or keyboard, but occasionally work with a mouse. I’m playing with the thought of buying a more powerful machine, but I doubt it would make me a more productive programmer. Laptops with significantly more than 16GB of RAM still seem to be rare. Instead of upgrading my hardware, I’m more interested in figuring out how to flexibly shift larger workloads into the cloud.
The basis for development machine setup is Manjaro Linux, a pre-configured version of Arch Linux with a GUI that is easy to install. There’s no need to bother with disk partitions or networking drivers: it just works. Instead of slowly building the system I want, I gradually remove everything I don’t need. A purist approach would have been to start with Arch directly, but I don’t really see why I should spend the time on a fresh Arch install if I can get sensible defaults in seconds.
This is what neofetch has to say:
The reasons for choosing an Arch based distro are simple: the documentation is outstanding and the packages available to Arch are expansive and up to date. Whenever I hear of any new tool, there is a good chance I can install the most recent version with a single command. No manual compilations, no outdated versions, no dependency conflict. I cannot stress enough how great this is.
At some point my last Ubuntu desktop forced me to go through a major version update, otherwise I wouldn’t be able to get additional package updates. To avoid a similar situation in the future, I have embraced the rolling release model of Arch. A nice perk is to have easy access to recent Linux kernels, the most recent stable release is 5.7.2, and 5.7.0 is running on my machine right now - not too shabby!
To block malicious hosts and social media sites, I modify the /etc/hosts files on my machine with the hosts, as their documentation aptly puts it “Having a smart hosts file goes a long way towards blocking malware, adware, and other irritants.”
For window management, I use i3-wm, I have not made the jump to the Wayland-based sway, mostly because I’ve never had any problems with i3. The window manager allows me to make efficient use of my screen “real estate”: no more unused areas of overlapping windows. In addition, work spaces can be easily set up and allow me to quickly jump from my IDE, to my browser, to my Shell and back. i3 provides some displays about the system status (networking, RAM utilization etc), but the default display is a bit raw. Luckily, polybar makes it easy to have beautiful and minimalist status bars in i3.
As an application launcher, I have set up rofi, it is accessible via a hotkey and much nicer than the default dmenu, because it sorts applications according to frequency of usage.
The terminal emulator I use is Alacritty, the shell is fish, with Vim bindings enabled. If I type in a long command and want to make modifications, I can easily jump to the right spot instead of holding the arrow key for several seconds; I’ve been looking for such a feature for a long time!
To handle extensions of my shell, I use omf (oh-my-fish), the theme I’ve been using for years and am very happy with is called sushi. Some people complain about a lack of complete POSIX compliance in fish that breaks some commands: other than minor modifications I’ve never had any trouble. More complex scripts are being run in bash anyway, so occasionally changing a quotation mark or escaping some character from the code I blindly copy from Stack Overflow isn’t a big deal for me.
To access the Arch packages on AUR, I use yay. Beside yay, I use pyenv, nvm and rustup to handle Python, node and Rust versions respectively. Global node packages are installed through node. I like having ipython globally available on the system for quick Python scripts.
There is no automatic remote backup of my system right now, just one folder with files that I don’t want to lose that sync to Cozy. I manually export data from Workflowy, OneTab and my Google account and Twitter into this folder. In the past, Linux clients from Dropbox have caused performance problems for me, but now I’m giving a new project called maestral a try to see whether Dropbox on a Linux desktop is feasible again. Code and system configurations are usually on remote git repositories, either on Github or Gitlab. I occasionally try to put a backup on an external hard disk. There’s definitely room for improvement through automation here. My aim is to always be protected against loss of data, be it through theft, destruction or otherwise losing access to my laptop. If the house burns down right now, that should not mean loss of data for me. I should get much more aggressive about redundantly storing my data and encrypting it.
Modern replacements for standard utilities.
grep, ls, cat, fd and others are familiar tools that many programmers use on a daily basis. Modern, expanded implementations, often in Rust, are available. To avoid having to change my habits, I use the new utilities though the names of the old commands by way of aliases.
To see the contents of files, it is often convenient to run cat <filename>, I’ve recently switched to bat, a similar command with convenient syntax highlighting:
Instead of the default grep, I use ripgrep. Grep is useful to find lines in large codebases, it is especially handy when I have the source of my dependencies/components on the same machine and can quickly find the code that triggers an error message, it is a bit crazy how fast the ripgrep implementation is. The code is the source of truth and it can be easier to look at the source than to aimlessly search for error messages in old threads. Grep or AWK also make it easier to parse large logs. Instead, of ls I use lsd, fd is a modern incarnation of find.
Firefox is the browser I use, the extensions are HTTPs everywhere, uBlock Origin and oneTab bitwarden and Vimium. OneTab is partiularily important because it allows me to store groups of tabs as collections associated with a certain theme or task: If I want to read an article later or pick up a task at another point in time, i just throw it into OneTab, this frees up a lot of system resources; some websites occupy an outrageous amount of memory. I wish I had a tool like OneTab for desktop apps: taking a snapshot of the current state of my IDE, browser and servers and just being able to close it in order to work on another project.
Now that Gmail has started to display ads directly in the inbox, I’m getting ready to pay for an email provider; I’d also like to get away from using a web app, to having a local copy of all my emails. I hear good things about Mailspring as an email client, but I’m worried about losing the extremely powerful search functionality Gmail has to offer. I have an account with Protonmail, but am also considering Fastmail. Leaving Gmail is a tedious and manual process, I doubt I’ll ever be able to delete my account.
I also have the Firefox Developer Edition and a Google Chrome installation without any extensions that could interfere with the web application I’m working on. The idea here is to see a web app the way a user would.
As a password manager, I have used Lastpass for years, but am now in the middle of migrating to Bitwarden, I have both the browser extension and the desktop app. I use the password manager in conjunction with the andOTP app on my Android phone and a Yubikey. I have tried to migrate away from any SMS based 2FA but given the ~200 accounts I have with various services, it is hard to be sure which accounts still use my phone number as backup.
In regards to developer tooling, I use Pycharm Professional with Vim keybindings and several plugins, aside from file hosting on Cozy, Pycharm is the only tool I pay for on a regular basis. The debugger is great and functionality like “Find usages”, “Refactor”, “Go to definition” and the git-GUI are highly appreciated. By using Vim bindings within a Jetbrains IDE, I feel like I’m getting the best of both worlds without having to put a lot of work into setup. I also use Visual Studio code for smaller projects or quick edits, Jetbrains tools are pretty heavy.
To run queries against my web servers during the development, I rely on httpie. To download videos I like on Youtube or Vimeo, I use youtube-dl.
A desktop system needs to be maintained: install software updates for the various packages, clear log files and the trash, check for orphaned packages, delete binaries I don’t use anymore, upgrade my kernel, run a virus scanner (I use clamav to scan my home folder for known malware signatures), investigate failed processes, check what is on the file system etc.
a great application to visualize and find out what is happening on a
file system. I’m often surprised to learn that some software I have
deleted long ago still occupies a good chunk of my hard drive or that
some old cache weighs in at 10GB+.
I have tried to automate several of these steps in a small script, but this is very much a work in process and I’m sure many of the more experienced Unix users want to tear their hair out when looking at it. A much higher degree of sophistication is possible here.
To access files, I use krusader, which allows me to open two directories at the same time and remembers the last opened directory. This is handy for moving files/folders manually.
To view PDFs, I use Firefox, which has the nice benefit of letting me open web-links within documents in new tabs (instead of having to switch to a browser in another window). To read ebooks I use foliate, I play back videos with vlc, but I guess Firefox should also be able to do that, too.
To take screenshots, I use flameshot which I invoke through a convenient shortcut. It is nice to be able to insert little arrows into screenshots and then send them off. Flameshot allows for screenshots with a slight delay, which is handy when trying to capture a part of a UI that results from a mouseover event.
As a task manager, I use htop, it is great to identify rogue processes that gobble up all system resources and snipe them down. F4 to filter, F9 + 9 to kill. It’s a bit scary how often I only find out about a problematic process like this because the fans of my laptop flare up. It’s a bit unfortunate that I cannot hear the fans of the machines running my cloud applications.
For natural language writing, I switch between a text editor like VSCode, Libreoffice Write and Google Docs. I would love to have an integration into the Hemingway app to improve my style. It is hard to find the right balance here: Google Docs isn’t available when I’m offline but Libreoffice is much worse for collaboration and doesn’t have the same strength in suggesting improvements to my text. The beauty of writing in plain text is that I don’t have to worry about binary formats ever being inaccessible. The rest of the LibreOffice suite is installed on my machine, but I don’t have much use for it.
Especially when in public or at an office, it is a good
idea to lock one’s screen, I let the alias “afk” trigger i3lock-fancy, which blurs and locks my screen.
While I have not done as many screencasts as I would like, tools that have been recommended to me for this purpose are Obs Studio and Screenkey.
Using the "'man" command to show the manual
of an application can be intimidating and unhelpful - walls of text for
something that should be pretty simple. An modern interpretation of the
man pages is tldr,
which shows succinct summaries of what a command can do and gives
practical, real-world examples
To interact with databases, I currently use Dbeaver, just because I am too cheap to pay for Datagrip. psql should suffice anyway.
Workflowy serves as my notebook and to do list, a good part of my life is stored there.
Now that I live in France without being able to correctly write in French, the translation tool Deepl has become really important to me.
To get an overview of the Docker images and containers on my system, I find that lazydocker is a nice solution.
Now that I have read so many good things about spaced repetition, I try to insert newfound knowledge into Anki. Insights about French, software engineering, investing or myself go straight into the app.
Using the web interfaces of AWS or Google cloud has sometimes been tricky for me, I’m trying to transition to their CLIs.
For my private communication, I mostly rely on Whatsapp, which I use via their web app (great login experience!), but I also have the desktop apps of Telegram (very fluent experience!) and Signal.
I don’t play games anymore and I no longer use Spotify. So far, I have not felt the need to use Windows apps via wine.
The software I’m using is almost entirely open source and it is incredible to me that so many talented engineers from around the world have worked hard to make those tools stable, useful and fast. If you also consider the makers of the dependencies (and their dependencies …) and build tools that go into each project, we’re talking about a distributed army of passionate contributors. I’d love to visualize the dependency graph and map commits to contributors.
What am I missing, what are the next few issues I want to tackle?
A global system settings GUI for things like default format->app associations, system fonts, network settings would be great. I currently either modify text files or try to make my way through disparate GUIs to deal with things like Bluetooth, GPU drivers or WiFi.
Maybe it makes sense for me to run a VPN, I have to investigate that further, plenty of people sing the praise of WireGuard as a client.
To learn and customize more, I do plan to eventually run Arch on coreboot with a custom kernel I compile myself using clang, maybe even of hardware I’ve selected myself. The experience of going through Linux from Scratch is also widely lauded. My attempts of doing so within qemu have not borne fruit so far. Ideally I’d like to aim for a fully automated and reproducible process. Starting from a minimal install would certainly help in cutting down the number of installed packages on the system.
Here’s a list of similar posts where other developers present their systems and design goals:
If you see glaring problems here, I’d love to hear your
feedback. I'm aware that there is plenty of room for improvement.
Do you have favorite linux configurations you’d like to share?