When I first encountered the Internet my peers and I thought it was great fun to share our dev setups. We were always optimizing and always looking for new ways to optimize. Not to mention showing off.

I lost interest in this practice because I settled into a system that was sufficient for my needs. Also, I didn’t have time!

But I’ve recently made a ton of changes to my workflow that some might be interested in, and I happen to have some time as I’m between jobs. So I thought it might be a good time to share!

I have a highly optimized workflow that probably doesn’t make a lot of sense to people. I have a policy of sticking as close as possible to defaults, but there are still some heavy customizations. Some of those might make sense to some people, some not so much.

I also have a policy of learning as much as I can about the tools I use in order to leverage them effectively. Years ago, I read the entire vim manual! Nowadays, due to time constraints, I am a bit more selective in my reading. I know the kinds of things I want to do and search to see how best to do them. Sometimes I’ll look for tips and tricks sites for inspiration to do things I hadn’t thought of.

Table of Contents

The space

I currently use a 4’ Fully Jarvis electric standing desk. I bought it in 2015 when it was considered best value for dollar, but there are cheaper ones available. I don’t spend as much time standing as I should, mostly because I can’t concentrate as well when standing. This is a stream-of-consciousness article, though, so maybe I should stand up now.

Ah, that’s better. Stand up tall, Dusty.

The desk is only 4’ wide because I was living in a 700 square foot condo when I purchased it and that was all the space I could squeeze out of it. It was ok when I had two 24" monitors, but it feels pretty cramped these days. The thin desktop also wobbles a bit as I type, which jiggles the monitors annoyingly.. I am planning to buy or build a 6’ desktop 2" thick this summer. I can attach it to the same jarvis frame. That should hopefully dampen the typing vibrations, and will give me a bit more breathing room in general.

I have my monitors mounted on three Gas Spring Desk Mounts that I purchased from primecables. They were the only ones I could find heavy enough to support my imac pro (more on that later).

My chair is a custom build by Ergo Centric. You’ll have to visit their website to understand the next few sentences. :) It’s the airCentric multi-tilt task chair. I actually originalyl purchased it with the synchro-glide mechanism, but after several years, realized the multi-tilt would allow me to tip back further.

When I purchased the chair, a sales rep came to my home and measured me for the best fit. He left two chairs with me and told me to try each one for a week before making a decision. The chair is designed for my tall (6'3") but slim frame. It has an extra long seat pan and gas spring to give me a more accurate position. It was impossible to find an off-the-shelf solution for my size; all the standard oversized chairs are labelled “big and tall”, but I needed something that was more like “big or tall”! That said, all ergo-centric chairs can be customized, and their prices are not out of line with other highly specialized ergonomic chairs.

I recently attached a Humanscale keyboard tray. My main goal was to free up space on my desktop for my bullet journal. More on that later as well.

The hardware

I recently acquired a middle-of-the line iMac pro, which is basically a top-of-the-line everything else. Its 27" 5K screen is a dream to code on. I have the 64 GB 3 Ghz 10-core model with Radeon pro Vega 56 8 GB graphics. The screen refresh rate on my terminal is amazing.

I decided to go with a iMac instead of another laptop for a few reasons. The first was, obviously, specs for price. You can get a much more powerful desktop machine for any given dollar value than you can a laptop. Another reason is that I simply can’t use a laptop keyboard. Typing an entire book on a laptop keyboard in 2019 lead directly to my worst ever RSI flare-up. I ended up having to spend eight month voice coding as a result. I decided that I may as well get the more powerful mac since I couldn’t leverage a laptop’s primary advantage: portability. With COVID going on it’s not like I need to work from anywhere else anyway!

My only complaint about the iMac Pro hardware is the weight. It was really hard to find a monitor arm that could support it, and setting it on the desk on its stand didn’t put it at the right height. Not to mention that I wanted more space beneath it for storing headphones and typing gloves and the like when not in use.

My other two monitors are 27" 4K LGs that I bought several years ago. I have them alongside the mac in portrait mode. The difference in resolution between the 5K mac and 4K monitors is noticable, but negligible, and I can code happily on each.

I have been typing on the same Kinesis Advantage Pro keyboard for over 15 years. I’ve worn through one set of keycaps and the second set is starting to look pretty ratty, too. I have it configured to dvorak keybindings. (Colemak wasn’t even a thing when I started using Dvorak.) I’ve dealt with RSI pain since a very young age. The dvorak + kinesis combo kept it at bay for many years. I find the keyboard is also more efficient, as more keys are available when I need them.

My mouse is a Logitech MX vertical. I love the mouse and have the hard Logitech mousepad to go with it. I bought a Fellows Microban wrist wrest to help support while I’m mousing. It’s absolutely delightful to cradle my wrist in.

To help keep circulation going in my hands, I wear a pair of hand-knit long-sleeve fingerless gloves. My wife measured my hands to make the fit as closely as possible. I also use silicon cups, a heated massager, reusable hand warmers, and antiphlogistine to keep the circulation moving.

Finally, I still do a bit of voice coding, for which a USB Tablemike is absolutely indispensible.

Key software

I spent most of my career as a hardcore poweruser. I was using Arch Linux in its earliest days and wrote substantial portions of the well-regarded wiki. I switched to Fedora in 2013 or so, because Fedora had finally reached the point where its autoconfiguration was faster to customize than my Arch configuration.

I switched to Windows with a new laptop in 2019, thinking that WSL would be enough to satisfy my unix needs. I tried really hard to like Windows and WSL, and they tried just as hard to be disatisfying. I really think that the vision Microsoft is trying to go for there is perfect, but the execution is simply not there. It’s 2021. I shouldn’t have to rearrange my monitors every time my laptop comes back from sleep, or beg people’s patience while I try to get the right microphone to connect in a video call.

I allowed myself to be talked into a mac with protest. I’d used macs twice before, in 2009 and 2013, and I hated the experience. But the 2021 MacOS is definitely the best operating system and user experience I’ve had. This is going to sound amusing to long-time Mac fans who have known it all along, but the combination of consistency and usability is too good to pass up.

Not to mention the 5K Retina screen.

I mostly stick with the default MacOS apps, which are more than sufficient for my needs. I use Chrome instead of Safari, of course, but other than that my only real customizations is in my development software.

I was using VSCode up until November, but a friend recommended switching to vim keybindings (I’d used vim all my life until VSCode came along and was so wonderful at me) to help with the RSI issues. The vim experience in VSCode is second rate at best, so I spent a lot of time discovering what has happened in the vim community in the last few years. More on that later.

One of the key discoveries with vim was that iterm2, which is an outstanding terminal in terms of features, is too slow for an enjoyable vim experience. I spent a lot of time trying various vim frontends and found them all lacking. Then I read somewhere that a faster terminal can make the vim experience silky-smooth, so I installed Kitty.

Kitty is an incredible experience. I never knew how much time was spent rendering program output. Programs that I thought were slow are not slow at all, not on an iMac pro with 10 cores and 64 GB of memory. The programs were executing faster than iTerm2 could render the output. Switching to Kitty made everything happen instantly. iTerm2 wasn’t properly leveraging the 8GB graphics memory. Kitty does.

Most importanly, runing neovim in Kitty is faster than any GUI app I’ve ever touched. And with the right configuration, it supports all the few GUI features I’ve come to rely on with VSCode.

I still use VSCode sometimes, when voice coding. I wrote an entire article on voice coding config, and it’s a right pain, especially since that entire config doesn’t work on macos. Luckily, I recently discovered Serenade which is a flawless voice coding experience. But I’ve been using it less and less because vim really has helped with the RSI issues.

Lazygit

I recently discovered lazygit in an effort to replace the git experience I’d come to rely on in Vscode. I actually had managed to get vim configured to do git better than VScode, but lazygit does it better, and requires zero configuration. So I removed most of my git plugins from the vim config, greatly simplifying it.

My only complaint about lazygit is the lack of decent documentation. Most of the cool features are only covered in videos, and those are hard to use as reference material. However, the context sensitive menus are a pretty good compensation.

I spend a lot of time curating my git history. I like my commits to be logical and independent. I’ve become very skilled at selective rebasing and cherry-picking, but lazygit abstracts a lot of that away, saving me swathes of time.

I highly recommend this tool.

ZSH config

I’ve used zsh for years, but switching to the Mac gave me an opportunity to rethink my configuration. I hadn’t bothered to set up oh-my-zsh, and that was a huge mistake. My zsh config is shockingly short compared to the previous version.

I use fzf extensizely, both in vim and on the CLI. The fzf oh-my-zsh plugin takes care of the heavy lifting for me. The zsh-interactive-cd plugin allows me to cd to any descendent directory with just a couple keystrokes. I also make heavy use of the dirhistory plugin, which allows me to go up a directory or go to the previous directory I was in with one keybinding.

The other two plugins that I use extensively are zsh-syntax-highlighting, and colorize. The former is indispensible for quickly determining if the command I want to run actually exists. The latter allows me to ccat a file instead of cat with full syntax highlighting.

I have several other zsh plugins, but they are mostly just to supply completions for various commands.

Vim config

I was afraid I’d be giving things up when I switched from VSCode to neovim, but I was wrong. Everything about my vim config is better than the vscode equivalents. I have full mouse support, icons in the right places, language server auto complete and the full nine yards. I guess if I was going to make one complaint it’s that window borders have to be a full character wide instead of just a couple pixels, just by the nature of terminals. Oh, and the hours it takes to tweak the config to be “just so”. I spent almost my entire week off during Christmas configuring it. But it’s worth it.

As I mentioned before, a GPU accelerated terminal like Kitty (there are a few others, but Kitty wins) is absolutely necessary for an amazing vim experience.

I settled on neovim over vim8 just because the plugin ecosystem seems to be more robust, and neovim tends to prefer modern over backwards compatibility. I really have no need for my vim to be backwards compatible with a 1970s experience. I use the nightly version of neovim because several of my advanced plugins rely on it.

Because I prefer defaults whenever possible, my neovim config is suprisingly short for that one week’s labour. At “just” 243 lines, it’s actually shorter than my vscode settings file is that long, and VSCode doesn’t even include my list of extensions!

You’d need to :help a lot of the commands in my config to make sense of it, but I’ll cover some of the most interesting details:

I map cmd-S to :w to keep my muscle memory active with other MacOS apps. Vim can’t actually pick up the cmd key, at least in Kitty, so this required mapping cmd-S to ctrl-S in my Kitty config:

map cmd+s       send_text all \x13

I have set my <leader> to space for most of my custom commands, and I repurposed the \ key as my “vim window management” key, mapping it to ctrl-w.

LSP support

Conquer of Completion is the primary plugin that makes vim behave like VSCode. It integrates with the exact same language servers that VSCode uses. I was pretty skeptical at first, as I expected CoC to crash and generally have a less integrated experience than VSCode. If anything, the opposite has happened. CoC Just Works, and it is fast.

My one complaint about CoC is that it doesn’t come with any default keybindings. The keybindings they list by default in the README are pretty much perfect for anybody’s needs, and it annoys me that I have to copy-paste them into my config. I prefer sane defaults over configuration any day.

Once configured, though, it gives you everything you’re used to from VSCode: hover text, completion, lint errors as you type (and they show up way faster thanks to Kitty not being Electron), symbol maps and refactoring.

Look and feel

I use bubbly.nvim for a modern looking status and tabline. I like that it requires relatively little configuration, but gives me everything I need.

I’ve installed the vim-devicons plugin and have set my Kitty font to a patched Jetbrains Mono.

Instead of the popular, but aged NERDTree plugin, I use CHADTree. It does pretty much the same thing, but faster. I don’t actually use the sidebar much (and didn’t in VSCode either), but it’s nice to have it when I need it.

Instead of the sidebar, my goto for file opening is the fzf.vim plugin. I use it for all my file opening and find in files (using :Rg with ripgrep) needs.

I use nvim-treesitter for my syntax highlighting. It’s beta and sometimes chokes, but it does make my Python code prettier, so I use it. It’s definitely more of a nice-to-have than a necessity.

Editing plugins

I maintain the standard suite of vim plugins, many of which I think should be built-in. I won’t go into detail as the READMEs should be sufficient, but these are the plugins I use most consistently:

’tpope/vim-sensible' ’tpope/vim-commentary' ’tpope/vim-abolish' ’tpope/vim-sleuth' ‘wellle/targets.vim’ ‘machakann/vim-sandwich’ ‘bkad/CamelCaseMotion’ ‘kana/vim-textobj-entire’ ’ethomas2/vim-indent-object' ‘glepnir/indent-guides.nvim’

I also use easymotion/vim-easymontion. This has been called a vim anti-pattern, but the latest version actually treats your motions like vim text objects, so I disagree. More importantly, it reduces the number of keystrokes my RSI-emburdened hands have to suffer through. I don’t explicitly recommend it, but it is a highly necessary part of my flow. In my old days of vim, I never had a need for it, but it’s serving my current purposes well.

I rarely use the mbbill/undotree plugin, but when I need it, it’s wonderful. It gives you a visual overview of all your changes in order. It’s kind of like a mini git for every edit. It’s most useful for this scenario:

You make a bunch of changes and realize that you might have made an incorrect design decision, so you undo them. Then you make a bunch more changes. But you discover that actually the original design was a better one, so you want to go back to the state before you started undoing. Undo tree shows the two sets of changes in different “branches” and allows you to step through them to go back to any state you were previously in.

There are a few other plugins in my config that you might want to look up. I spent more time looking for esoteric plugins than most people do, so you’ll likely find something you haven’t seen before.

One neat tip I picked up somewhere is that in insert mode, you can often use ; as a prefix for commands without having to switch to command node. For example, I have inoremap ;p <C-o>"*p in my config to paste from system clipboard when I type ;p. In normal typing, whether English language or source code, the ; is almost always followed by either a space or a newline. This means you can put any other character after it to create a vim command while in insert mode. I haven’t leveraged this as much as I intend to, but it’s a really clever idea.

I don’t have any git plugins besides mhinz/vim-signify and rhysd/conflict-marker.vim the former is just good sense, highlighting the changed lines in your file. The latter is useful when resolving conflicts. I was using flog and fugitive at first, but those have been superseded by lazygit, which I mentioned earlier. I haven’t had the opportunity to test out conflict resolution in lazygit, so I left conflict-marker.vim and its configuration in my vim plugins until I know whether or not I still need it.

Bullet journal

It’s not exactly a software thing, but I started keeping a Bullet Journal last year on a friends recommendation. I’ve experienced all the promised benefits, including better mindfulness, better comfort with my productivity and enhanced productivity.

Like most new Bullet Journal enthusiasts, I use a Leuchtturm1917 notebook. I use the highly regarded Zebra Sasara pens, which are supposed to be quick drying. This is super important for me, as I am left handed, but I find they still smudge on occasion. I may switch to pigma microns in the future.

If I go into detail of my bullet journaling ideas and collections, it would be an entire separate article, so I’ll leave it at that. Suffice it to say that I absolutely rely on it to remember what’s important to me, what I’m working on, and when I want to work on it.

Programming languages

If you look through my books, (or my LinkedIn), you’ll see that I’ve spent most of my career as a Python developer. I love Python very much, and I am extremely good at it. For the longest time, I refused to work in anything else. I’m very keenly aware of its shortcomings (usually speed, at least in the environments I work in), and I know both how to overcome those, or when to give in and switch to something else.

Python is still my goto language. I’ve been using it since before it was cool, let alone since before it was the world’s most popular language. It’s popular for a reason. I find developing in Python a joyful experience, and that is usually my primary reason for choosing a language. If I get into weird stuff where Python is no longer fun (usually highly concurrent systems or mobile apps), I switch to something else that is more enjoyable for that situation.

Python has developed a stigma in the past few years that I should not have found surprising. People tend to resent what’s popular. I went through it myself when I switched from Java to Python, around the time that Java was becoming one of the world’s most popular languages. I watched it happen to PHP and other languages as well. The Python ecosystem was also greatly slowed down by the Python 3 transition. This didn’t affect Python itself as much as people seem to think it did, but it did give other languages a chance to catch up to Python in features.

Javascript is the most notable of this. It seems to be the only language that people don’t resent for its popularity, and frankly, that’s because every new version of Javascript is practically a different language! That said, modern Javascript is a lovely language compared to the version I first started coding in (and hating) so long ago. It has borrowed almost many of Python’s most notable features (and those of many other languages), in some cases improving upon them. I sometimes joke that if I were to write a babel transpiler that took Python code as input and added braces it would run in Javascript. This may well be true if Javascript ever adds context managers and accepts the list comprehensions RFC.

I reach for Rust when I have to do systems programming, but I generally avoid situations where I have to do systems programming because I don’t enjoy Rust. Rust is super hyped these days, but I don’t think it’s going to become any more popular than Go, which was also super hyped not so many years ago. Both languages have a good niche, but I find that Rust is optimizing for the wrong things for virtually all of the situations I encounter.

Fast compile times and rapid development cycles are far more important to me than runtime speed and memory safety. Indeed, people seem to have forgotten that Rust is not the only way to guarantee memory safety. Garbage collectors, such as Go uses, are sufficient for many, if not most tasks. That said, for the tasks where a language like C, C++, or Rust is necessary, I will always prefer Rust over C or C++. I just find that it is so rarely necessary.

I write my code in Python, and might write the occasional Rust Python module for FFI if it seems like a bit of speed is needed. Even then, I’d probably reach for Cython first, though.

Finally, I was using Typescript in my previous role and found it very ergonomic compared to raw Javascript. It’s a great language, but my recent explorations of rescript have superceded any interest in Typescript. I will code in Typescript in production systems where popular support is necessary, but all my hobby web dev happens in Rescript. I believe Rescript will eventually overtake Typescript in popularity. It just maps so well to standard javascript practices.

Conclusion

That’s all I’ve got for now. Not sure if anyone will find it interesting or not. If I convinced you to switch to vim, I’m sorry, and if you use it already, I hope my vim config has one or two ideas to improve it.

If you don’t keep a bullet journal, I recommend it as a happiness hack. Perhaps I’ll go into more detail on how I use mine in a future article.

I’m publishing this article directly to my blog, but I want to mention that I have a patreon set up. I’ve committed to publishing one article per week while I’ve had free time through my recent unemployment. I fear, however, that without some financial incentive, I’ll probably drop that off once my free time disappears. It’s not that I expect Patreon to make it worth the time investment, but if it alleviates the ‘shouting into a vacuum’ effect, it will probably provide some motivation.