One Week With Desktop Linux After a 20 Year Absence
March 21, 2025 š¬ Get My Weekly Newsletter ☞
I bought a Framework laptop a couple weeks ago, set it up with stock Ubuntu, and used it for my primary computer for a week. Itās the first time Iāve used Linux in earnest in 20 years. Itās amazing how much has changed and how much hasnāt.
The tl;dr for this post is that I donāt know if I could use Linux as my desktop full time for web development. While there are many papercuts, the three main issues I canāt see a way around are: lack of integrated API documentation lookup (e.g. Dash.app), inability to customize keyboard shortcuts consistently across all apps, and the absolute tire-fire of copy and paste.
Why Even Do This?
I actually grew up on UNIX and then Linux. All through college and for my first 12 years of professional experience, I used UNIX or Linux. OS X made it clear that Desktop Linux was possible, it was just made by Apple and based on BSD Unix.
I didnāt really miss Linux, but when writing Sustainable Dev Environments with Docker and Bash, I never actually tried anything on a real Linux. I checked it all on WSL2 and that was that.
It turns out that running a devcontainer as root creates a lot of problems on Linux, and I figured the best way to truly solve them was to revisit day-to-day Linux. However, I have lost a lot of enthusiasm for messing with configs and trying to get something working on hardware not designed for it.
Since it doesnāt seem like you can easily run Linux on an M3 Mac, I decided to get a Linux laptop whose vendor officially supported some sort of Linux.
The Hardware
My requirements for hardware were:
- Vendor must officially support at least one Linux distro, so I know it will work with their hardware
- 13ā Laptop I could take with me
- Can use my LG Ultrafine 4K Thunderbolt monitor as a secondary display
The Framework Laptop 13
I considered System76 and Framework. Anecdotal reviews of System76 hardware were mixed, and I liked the idea of a modular laptop, so I went with a Framework Laptop 13 DIY Edition (IntelĀ® Coreā¢ Ultra Series 1). This is not the latest one they recently announced, but the now older model. I also opted for Intel as that was the only processor I could determine should support my Thunderbolt display. I could not figure out if AMD did, and didnāt want to find out that it didnāt.
My configuration was pretty basic. I stuck with the default processor, but opted for the ābetterā of the two screens. I donāt need HDMI, Ethernet, or an SD card reader, so I went with three USB-C ports and a USB-A port. I stuck with the boring black bezel.
Assembly and Setup
It was fun putting the laptop together - I havenāt shoved RAM into a socket in quite a few years, so it was cool seeing all the parts and putting it all together. Frameworkās instructions were spot on and I had no real issues. Most everything either went into a secure socket or was magnetically attached. I did need to screw some tiny screws in, but they provided a nice screwdriver for their Torx screws.
The last time I did this, I was building a desktop PC and all the parts came in these anti-static foil thingies in very basic packaging. Framework has gone the complete other way, with Apple-style packaging that was very easy to open and deal with.
That said, even though itās all recylcable, it felt like a ton of waste. Not having something to recycle beats recyling any day of the week.

The DYI edition does not come with an OS, but Framework officially supports Ubuntu and Fedora. Since Iāve used Ubuntu as the basis for Docker containers, I went with that. I followed their instructions to flash a USB drive with an ISO and install from there. It all worked perfectly, exactly as they had documented.
Iāll discuss the software side in a minute
How Is The Hardware?
While the Framework is by no means a Macbook Pro, it does feel high quality. Yes, itās made of plastic and has holes for fans. And yes, there are seams in it where the modular parts connect. Iām fine with all of that.
The screen looked a lot better than I was expecting. It seems retina-quality, or at least nowhere near as bad as the $400 Lenovo Windows laptop I used for testing my book. Itās not as bright as my Macās, but the only time I really noticed was when I was switching between the two computers.
The keyboard felt as good as the one on my Macbook Pro. My only quibbles are: 1) the placement of the why-is-there-always-an-unmappable-Fn-key, as itās where Control is on my Mac, 2) a fucking Windows key logo, which I am not kidding almost made me not buy this thing, and 2) The F9 key, whose function I would describe as ācompletely decimate your display setup and fuck up everything until you keep hitting it and eventually arrive at what you had beforeā.


The trackpadā¦wellā¦itās OK. Itās not as big as Iād like, but not as tiny as your average PC laptopās. I find it extremely hard to use, but I also find the Magic Trackpad hard to use with Linux. Itās clear that Appleās driver does some stuff to avoid misclicks and other stuff. You also cannot control the scrolling speed, so I found myself making a lot of mistakes using both Trackpads.
Battery life seems very good. Not Mac-level, but I have left it closed for 24 hours and the battery is still pretty well charged. As I type, itās at 88% and the OS is telling me itās got 5 hours left.
No issues with WiFi; I was able to connect to my iPhone for tethering. The fingerprint reader is more finicky than Appleās TouchID, but worked almost every time.
The First Day Was Rough
The first day with Linux was rough for me. Mostly due to two things:
- Muscle memory of keyboard shortcuts that arenāt set up or do other bizarre things on Linux. This is purely my fault.
- The trackpad/mouse configuration is woefully inadequate. Scroll speeds are 100MPH, acceleration is weird, and clicking with the trackpad causes numerous mislicks. Each click on either my Magic Trackpad or the laptopās resulted in the mouse moving down a tiny bit. This was often enough to miss a click target. I have to assume Appleās drivers account for this.
As weāll see, I somewhat tamed the keyboard shortcuts, though not sufficiently, and I ended up getting a mouse which was much easier for me to control.
That said, after the first day, I realized I need to slow down and not try things until I knew they would work. It felt like trying to type on a new keyboard layout or using my left hand for mousing.
My Workflow
My goal was to recreate as much of my workflow from the Mac to this new Linux laptop. In the end, I was mostly able to do so, however some apps or behaviors were simply not possible.
At a high level, my workflow when programming is something like this:
- A terminal is for running command line apps and scripts.
- Neovim is my editor, however it runs as a GUI app, not in the terminal
- All development is done inside a Docker container, with source code mounted. This allows editing in Neovim, but alleviates me from having to manage a bunch of version managers and databases.
- A launcher like Alfred responds to Cmd-Shift-Space to allow me to type the name of an app or initiate a web search.
- I use copy and paste liberally, and have a clipboard manager (Alfred, again) to manage multiple pastable things.
- I heavily rely on a core set of keyboard shortcuts supported by all Mac software (including bad citizens like Firefox and Electron).
- 1Password manages my passwords, which I unlock with TouchID.
- Cmd-Tab allows switching apps..
- Inside Neovim (or through my launcher) I can look up API documentation using Dash. This means
if my cursor is in a
.css
file in the middle ofmax-height
, I can typeK
and Dash will raise to the top, get focus, and show me the MDN docs for themax-height
CSS property. - For Mail, Calendar, Mastodon, BlueSky, or Plex, I expect to be able to Cmd-Tab or use my launcher to select themāthey do not run as tabs in Firefox.
- Occasionally, I run the iPhone simulator, draw diagrams with Omnigraffle, or edit images with Pixelmator.
- I rarely use the Finder
I was able to get most of this working, however, keyboard shortcuts were challenging, copy and paste is confusing, and the API documentation options pale in comparison to Dash.
Software
I basically got to the setup below by working on real projects and, when I hit a wall, figured
out the Linux way of addressing the issue. This usually involved installing a lot of stuff
with sudo apt-get install
and I did not write down any of what I did.
I quickly learned that the Ubuntu āApp Centerā should never be used unless the people building the software say to use it. Several apps did not work until I uninstalled them via App Center and re-installed them on command line.
Below is a breakdown of which Mac app I use and what I used on Linux as a replacement.
Terminal Emulator

Terminal.app on Mac

Ghostty on Linux
Gnome-terminal was very hard to configure and very limited. Ghostty allowed me to configure all of my keyboard shortcuts and worked well. I don't use it on Mac since Terminal.app works well and Ghostty killed my battery life. It doesn't seem to have that issue on Linux.
Vim GUI

VimR on Mac

Neovide on Linux
Neovide has the most bizarre set of defaults I've ever seen. It is configured to animate every move of the cursor at an extremely slow animation rate. It is almost impossible to use. But, this can all be turned off very easily and the documentation is great.
I was also unable to get Neovide to behave as its own "app". I can Cmd-Tab to it as a separate
window, but it shows a default icon and is considered a window of Ghostty. I tried creating
magic .desktop
files, but they didn't seem to do the trick.
Docker

Docker Desktop on Mac

Docker Daemon on Linux
I installed Docker per their Linux instructions, which does not include a desktop GUI. That's fine, as I never use the GUI anyway. I followed the Linux post-install instructions to allow my user to access Docker. This was 1) because it was much easier than the rootless setup, and 2) required for me to get the details in the book right.
App Launcher

Alfred on Mac

Albert on Linux
Albert looks inspried by Alfred and works pretty well. I had to configure a
system-wide keyboard shortcut inside the Ubuntu/Gnome/??? Settings app. Albert
doesn't seem able to do this, even though it has a configuration option for it.
Fortunately, albert open
will open, raise, and focus Albert.
Albert includes a clipboard manager, but it didn't work as well as Alfred's. I think this is because Linux lacks a system-wide clipboard and/or has multiple clipboards. I eventually gave up on relying on it.
Password Manager

1Password on Mac

1Password on Linux
1Password worked greatā¦once I got it installed
Installing 1Password and Firefox from App Center resulted in the browser extension not working and caused 1Password to ask for 2FA every time I opened it. It was actually not easy to delete both apps from App Center, but once I re-installed them, they both worked fine.
On Linux only, the browser extension will randomly open up 1Password's web page and ask to me log in, though if I ignore this, everything still works. This is what it does on Safari on macOS (except there it just doesn't work).
Even now, the browser extension can no longer be unlocked with the fingerprint scanner and I have to enter my passphrase frequently. It's extremely annoying. But at least it works, unlike on Safari, which just does not.
App and Window Switching
Cmd-TabSwitch apps on Mac
Cmd-TabSwitch windows of all apps on Linux
In theory, the Gnome task switcher allows switching between apps like on macOS. In practice, because I could not get Neovide to run as a separate āappā in the eyes of Gnome, I could not Cmd-Tab to it. I would have had to Cmd-Tab to Ghostty, then Cmd-~ to Neovide.
Fast API Doc Lookup

Dash on Mac

A Mess on Linux
More on this below, but Zeal didn't work for me. I ended up using a hacky system of FirefoxPWA, DevDocs, and some config.
Fastmail

FastMail on Mac (as Safari Web App)

FastMail on Linux (as Firefox PWA)
More on FirefoxPWA below, but this worked great.
Calendar

Fantastical on Mac

Fastmail on Linux (as Firefox PWA)
More on FirefoxPWA below. I could not set a custom icon, but this works fine. FastMail's calender UI is pretty good.
Mastodon Client

Ivory on Mac

Mastodon.com on Linux (as Firefox PWA)
First time really using Mastodon's web UI and it's not very good. But works well enough.
Bluesky Client

Bluesky on Mac (as Safari Web App)

Bluesky on Linux (as Firefox PWA)
It's the same crappy UI in both.
Plex

Plex on Mac (as Safari Web App)

Plex on Linux (as Firefox PWA)
Plex is plex.
Streaming Music

Apple Music on Mac

Apple Music on Linux (as Firefox PWA)
Kindof amazed this existed and works! Firefox insists on "installing DRM" but also didn't seem to actually do anything. I think the Apple Music app is really just this web player. It works the same, and is still just as crappy as it was the day it launched as iTunes.
Messaging

Messages on Mac
š¢Nothing on Linux
Messages is an Apple-only thing, so I was stuck taking out my phone a lot. I just didn't interact with my friends on text nearly as much.
Maps

Maps on Mac

Wego Here on Linux (as Firefox PWA)
I have tried to avoid having Google in my life, and Apple's maps are pretty good, at least in the US. OpenStreetMap is servicable, but Wego Here is a bit nicer.
Keyboard Configurator

Keychron Launcher on Mac
š¢Nothing on Linux
Chrome could not access USB no matter what I did. I chmod
'ed
everything in /dev/
to be owned by me and it didn't work.
I ended up having to program the keyboard on my Mac, plug it into the Framework
to check it and switch it back. Ugh.
RSS

Reeder on Mac

Feedbin on Linux (as Firefox PWA)
Reeder has always required an RSS back-end. I initially used David Smith's excellent Feed Wrangler, but he sold it to Feedbin a few years back. I've never actually used the Feedbin web UI before, but it's pretty good! Installed as a PWA, it works great.
Light Image Editing

Preview on Mac

Krita on Linux
Preview is an underrated app. It's truly amazing and demonstrates what Apple isāor at least used to beācapable of. It views PDFs, lets you edit them, sign them, save them. It views images and lets you crop them, adjust their colors, and do a lot of the 80 in 80/20 changes.
Krita is more like a Pixelmator or Photoshop. I had to consult the documentation to figure out how to crop an image. It's coloring didn't respect my desktop light/dark mode, and it made me miss a hugely helpful thing almost every mac has: keyword search of menus.
How it Worked
To toot my own horn, every single dev environment built and passed tests without any changes. I pulled down a
repo, ran dx/build
to build images, ran dx/start
to start containers,
dx/exec bin/setup
to set up the app inside the container and dx/exec
bin/ci
to run all tests, which all passed.
Once I started actually making changes to my code, I did run into issues running all containers as root. I have sorted that out and the book will be updated to reflect this.
Aside from that, the experience was overall pretty great once I had installed everything and configured as much as I could to have keyboard shortcuts I could live with. To use this full time for software development, however, a few things would need to change.
Instead of āThe Good, The Bad, and The Uglyā, Iām going to list Dealbreakers, Papercuts, and Pleasntries.
Dealbreakers
There are three major issues that I would have to address to use Linux full time: clipboard craptitude, keyboard shortcut inconsistency, and API documentation lookup.
Clipoard Craptitude
Just do a web search for āCopy and Paste on Linuxā or āClipboards on Linuxā and you will find a stream of confusion about the clipboard situation on Linux. I mean, just read this.
On Mac (and on Windows, I believe), there is a single system-wide clipboard. When you copy something into it, it becomes available to paste anywhere. You can run an optional clipboard manager that stores the history of stuff you have copied and allow you to paste it.
On Linux, it absolutely does not work this way. There is a clipboard thatās filled when you select text (and there may be one for X11 apps and one for Wayland apps?). Thereās a system clipboard, too, but itās not always clear if youāve copied to it, or if you are pasting from it.
In Neovim, I could not tell what was happening. Usually :*p will paste and
:*y will yank. Neither seemed to do what I expected. I ended up mapping
Alt-C and Alt-V in NeoVimās configuration to do copy and paste. It worked better, but not 100% of the time. Update I also realized that +
is a better option than *
because unlike on Mac, *
on Linux is the āwhatever you had selected in X11ā and not āthe system clipboardā, which is +
. FML.
Iām sure the way copy and paste works on Linux can be learned, but I found myself failing to successfully copy and/or paste on numerous occasions. Eventually, I learned to always type # in the terminal before pasting, because I never knew exactly what was going to be pasted there.
Albertās clipboard manager didnāt allow pasting in all apps, and it didnāt store an accurate history of stuff I had copied (and pasted). Iām not sure how it works, but I just stopped using it after a while.
I cannot fathom why this clipboard behavior is the default, and I would probably need to go on a deep dive to understand and remedy it, if I were to use Linux full time. Itās hard to overstate how frustrating it is to not have copy and paste work. Christ, it works better on iOS, which I thought had the worst copy and paste experience ever created.
Keyboard Shortcut Inconsistency
On a Mac, there are certain keyboard shortcuts that every app responds to, even bad citizens like Firefox and Electron. Not so on Linux.
The source of this problem is, I guess, due to terminals relying on the Control key for non-alphanumeric sequences. The Control key was adopted by Linux GUI apps as the key to use when you want to invoke a shortcut.
On a Mac, this has historically been either the āApple Keyā or now the Command (Cmd) key. This key not only is irrelevant to any terminal emulator, it also is right under your left thumb.

This makes it ergonomically easy to use, even with other modifiers. Cmd-Shift or Cmd-Option are far easier to use than Control-Shift or Control-Alt.
I have a ton of muscle memory built up using the key under my thumb. On Mac, that key is Cmd or Super. On the Framework laptop, itās Alt. I rarely use Control, since itās almost never a modifier on Mac. I also have Caps Lock mapped as Escape, since I have not had a keyboard with Escape on it in quite a while (thus, I cannot use that for Control, which would be slightly better, ergonomically).
To make matters worse, apps on Linux do not have consistent keyboard shortcuts. Copying and Pasting in Gnome-Terminal is different than in Firefox. And to make matters even worse, Firefox provides no way to customize keyboard shortcuts. You have to use Ctrl-C to copy (e.g.).
What this means is twofold:
- Any new app I install, I have to inspect its configuration to see if I can configure the keyboard shortcuts I want. Namely, using the ākey under my thumb that is not Controlā as the modifier.
- When using Firefox, I have to internalize and use its Control-based shortcuts, since they canāt be modified.
To try to deal with this situation, I accepted that Linux uses Alt way more than Super, so I set the āWindows Modeā of my Keychron keyboard to have Alt as the ākey under my thumbā (which is the left space bar).

This meant switching from my desktop keyboard to the laptop wasnāt so jarring. It also meant, a few default shortcuts worked like on Mac.
For Firefox, the situation is dire, but I did find an extension that gave me some ability to control the shortcuts. I was able to get it to allow changing tabs with Alt-{ and Alt-}, however it only works 90% of the time.
Iām not sure how I would deal with this day-to-day. I guess Iād just build up muscle memory that when Iām in Firefox, I do things differently.
I do think this inconsistency is a contributor to some of my copy and paste woes. Iām sure I thought I copied something when I didnāt, only to paste whatever was last on the clipboard.
API Documentation Lookup
For my entire career, Iām used to being able to quickly go from a symbol in my editor (which has always been some form of vi) to API documentation. Yes, I wrote a Java Doclet that generates vimdoc for the Java Standard Library. Nowadays, I use Dash.
I use it in two ways. First, I can use Alfred to lookup something in Dash, say āmax-heightā, hit return, and have Dash show me the docs directly:

Second, I can do this directly from vim by placing the cursor on a symbol and hitting K. This brings up Dash, performing a search in the context of only Ruby documentation:

As you can see, itās very fast, and easy to get used to. Itās nice to have docs at your fingertips, and itās nice having them in another app/window. I find a documentation-reading-based approach encourages exploration of the docs, which can be a great way to learn new stuff you can do with your existing libraries.
One bit that you canāt see from these examples is that Dash allows you to install documentation for pretty much any Ruby Gem (or other code library). That means I can have esoteric stuff like the Ruby Playwright bindings or the Faker gemās RubyDoc available. Searching in Dash is far faster than web searching or trying to use GitHub.
First, I tried Zeal. Zeal did not seem to have a way to install documentation for arbitrary Ruby Gems. Worse, I could not ever get Zeal to get focus, raise to the top, and show me search results. I tried a lot of options and it just never worked.
Next, I tried DevDocs. I ran DevDocs in a FirefoxPWA (more on that
below), so it behaved like a separate app. I configured both Albert and Neovim to use
open
to open a magic URL that would search DevDocs and show the results in the
PWA.
This behavior works about 90% of the time (the other 10% it shows as different URL). DevDocs does not allow installing arbitrary documentation. You get whatever they have, and they arenāt looking to install docs for RubyGems.
This sucks for my workflow. I would have to sort this out. I guess devs today who arenāt letting AI write their code are just hitting Cmd-Space and seeing what VSCode shows them? I just canāt work that way.
Papercuts
These are issues that were annoying, but I could live with.
- Mouse/Trackpad scrolling speed cannot be adjusted. I could not find a way that worked on Wayland and X11.
- I did find a way to configure my extra mouse buttons and extra mousewheel, using input-remapper. It sometimes just stops working and needs to be restarted, but it did exactly what I wanted.
- Too many ways to install software. Sometimes you use App Center, sometimes you use
apt-get
, sometimes you download a file and dump it into your path, sometimes you do something else. This is how it was 20 years ago, and it still is like this and it sucks. - No system wide text replacement. I can type
dtk
anywhere on my Mac and it replaces it with my email address. I found a version of this for Linux and it just didnāt work. I ultimately programmed a macro into my Keychron keyboard. - The font situation is baffling. Iām going to set aside how utterly hideous most of the fonts are. For some reason, Linux replaces fonts in websites, making
font-family
totally useless. If I specify, say,Helvetica, 'URW Gothic', sans-serif
, and URW Gothic is installed, Linux will send Noto Sans, because that is a replacement for Helvetica. I canāt understand the reasoning for this. - No ApplePay on websites means using PayPal or swtiching to my phone.
- Cannot copy on iPhone and paste on Linux or vice-versa.
- Web-only access to iCloud. Apple is not good at web apps.
- Entering non-ASCII characters is either really weird or something I have to learn. Control-Shift-U-2026-Enter to type an ellipsis justā¦sucks. I think thereās a better way, so to be researched.
Pleasantries
I realize this is a lot of criticism, but I did actually miss just how fun it was to use an operating system that I could tweak, and that wasnāt being modified by whims of Apple designers looking to get promoted. While Apple is great at hardware, and good at software/hardware integration, their software has gotten much worse over the last 10 years, often foisting zero-value features on users.
The other thing that surprised me was just how many apps I use are web apps, and that those apps are pretty good, especially when run as a standalone āweb appā and not as a tab in Firefox.
Ironically, Apple provides a great UI for doing this via Safari Web Apps (itās too bad they also hamstring what a PWA can do on iOS). The situation on Linux is rather dire. Chrome supports it, but itās cumbersome, and Firefox, of all browsers, provides zero support for it. But, FirefoxPWA to the rescue!
Firefox PWA
The good and bad parts of Linux are both its flexibility and configurability. FirefoxPWA is no different. The general protocol of a āWeb App Running as a Standalone Appā is, in my mind:
- Separate app in the app switcher, complete with icon and title.
- Navigation within the appās website stays in the app.
- Navigating outside the appās website opens in the system browser.
- Activating or opening the app from another context (e.g. app launcher or command line) brings the app into focus, but does not reload the appās start page.
This is possible with FirefoxPWA, but requires some tweaking.
Once youāve created your app and relaunched it, it will use the Web Manifest to get icons and
names. It does not respect the scope
attribute, so by default all links open in the PWA and not Firefox. By default, when a PWA is launched or activated by the OS, it will reload the start page. It also wonāt allow you to override icons. Well, it will, it just doesnāt work.
Fortunately, the author(s) of FirefoxPWA have done a good job with configuration and
documentation. In any app, you can do Control-L to go to a URL and type
about:config
to get into the settings.
From there, to fix app activation, set firefoxpwa.launchType
to ā3ā. To ensure URLs outside the app are opened in Firefox, set firefoxpwa.openOutOfScopeInDefaultBrowser
to true, and set
firefoxpwa.allowedDomains
to the domains of the app.
I couldnāt figure out a way to make these the defaults, but this is all one time setup, so worked fine. Once I had this setup, Mastodon, Bluesky, Plex, and Fastmail all behaved like their own apps.
DevDocs
While DevDocs isnāt perfect, when used with FirefoxPWA, it is serviceable. DevDocs has a URL
format that will perform a search. Basically, devdocs.io/#q=keyword
will search all your
configured docs for ākeywordā, and devdocs.io/#q=ruby keyword
will search only Ruby docs for
ākeywordā.
Thus, I needed to be able to run open devdocs.io/#q=keyword
and have it open the DevDocs PWA
and load the given URL. This was somewhat tricky.
First, I had to change firefoxpwa.launchType
for DevDocs to ā2ā, which replaces the existing
tab with whatever the URL is. This requires setting āLaunch this web app on matching websiteā
for DevDocs and setting automatic app launching for the extension.
The result is that open devdocs.io/#q=ruby keywdord
will open that URL in regular Firefox,
which triggers Firefox PWA to open that URL in the DevDocs web app. And this works about
90% of the time.
FirefoxPWA installs Firefox profiles for each Web App, but I could not figure out how to use this to open a URL directly in the DevDocs PWA. There might be a way to do it that I have not discovered.
Other Cool Stuff
Alt-click anywhere in a window to drag it. Yes! I had forgot how much I loved being able to do this. Mouse over a window to activateābut not raiseāit. Makes it really handy to enter text in a browser window while observing dev tools.
I also missed having decent versions of UNIX command-line tools installed. macOSās versions are woefully ancient and underpowered.
Time will tell if I take advantage of Frameworkās upgradeability. At the very least, I can swap out ports if needed.
Where I Go from Here
I still need to update Sustainable Dev Environments with Docker and Bash, and I plan to do that entirely on the Framework laptop. My book-writing toolchain is Docker-based, so should work.
Depending on how that goes, I may spend more time addressing the various major issues and papercuts to see if I could use it for real, full time, for web development and writing.