Happy 9th birthday, qutebrowser!

qutebrowser is turning 9 today! I’ll use the opportunity for a – perhaps slightly tl;dr – overview of how it all came to be. As you might notice by the length of this post, stopping to write once I started writing something like this… isn’t exactly my forte! Hopefully the wall of text will be interesting nevertheless :).

The death of dwb

Back in 2013, I was a happy user of dwb, but it became apparent that the project would die at some point. It was clear that dwb would need to make the switch to WebKit2, but the author (portix) didn’t have the bandwidth to do so – as far as I remember, they said it’d basically be a full rewrite, and it’s not going to happen.

While dwb lived on for another 3 years or so, many dwb users – including me – were looking for alternatives. There were things like uzbl or luakit, and addons like Vimperator, but for some reason or another, those just didn’t fit the bill.

Back then, WebKit – especially WebKit 1, still used by most of those projects – was plagued by frequent hangs and crashes (and it being a single-process model, a renderer crash meant that your whole browser did go down with it).

A new browser on the horizon

I toyed with the idea of taking over dwb maintenance – however, it was a C/GTK codebase. While I was writing microcontroller firmware for a living in C for a couple of years, it always seemed an odd choice to me for more OOP-like GUI programming. With projects like Wireshark or LXDE wanting to switch to Qt at the time, it also became clear that GTK wasn’t what I wanted things to be based on. The only real alternative to build a web browser was Qt (Electron was only 5 months old!).

With plans about a new Chromium-based QtWebEngine already on the horizon, this seemed like a great choice. In terms of programming language, the choice was between Python and C++. C++ is the “native” Qt language, and Python bindings have been around since 1998 (!) and were maintained very well. Anything else was out of the question pretty much. Since I had some more Python knowledge than C++ knowledge, and C++ is… quite a beast, I decided to go with Python.

And thus, with thoughts along the lines of “eh, there are good libraries for it, how hard can it be?”, exactly 9 years ago today, I started qutebrowser.

It initially was focused on dwb “refugees”, and much of that is still visible today: The look of the UI, almost all keybindings, the split between book- and quickmarks (probably a bad idea), the idea of having external userscripts (probably a bad name), etc. etc. In other areas, qutebrowser most likely had a pioneering role: As far as I know, it was the first vim-like browser to introduce a more shell-like command interface, with things like :open -t or :open -w rather than separate :open, :winopen and :tabopen commands. Others like Tridactyl later followed suit.

Towards the first release, and then some more

It took a lot of work until, exactly a year later, v0.1 was finally released. Later, Vimperator died with Firefox dropping XUL extensions, and between 2014 and 2019 or so, more and more people switched to qutebrowser (up to around 10% of all Archlinux users participating in package statistics).

More recently, I was able to work on qutebrowser during my study summer break in 2016, again in 2018, and finally for a longer time as a part-time job since 2019. I’m humbled by all the support, it’s what still keeps me going – it’s fair to say that I probably would have burned out and/or stopped by now if I was employed 100% still. Turns out, after all, a web browser isn’t exactly an easy thing to do as your first big open source project. Big kudos to all the other projects which have been going for years if not decades: It’s not easy, and the occasional entitled user who’s pushy or angry at you for their favourite feature™ still not being implemented certainly does not help. Thankfully, those cases are rare: All in all, I’m thankful for the qutebrowser community being so understanding, patient and helpful! <3

Another big transition

It’s probably fair to say that dwb died during the transition from WebKit 1 to 2. Such major upgrades – while often reasonable and needed – tend to use a lot of energy and effort.

In 2016, qutebrowser had its own first big migration, when QtWebEngine finally was ready enough to add support for it. Nowadays, QtWebKit is still supported, though mostly for historical reasons. Chances are big it will be all gone for the v3.0.0 release.

Nowadays, qutebrowser is in a somewhat similar big transition again: It desperately needs to migrate to Qt 6 to keep things up to date, but – while not quite a rewrite – doing so is a bunch of work. With qutebrowser getting older, more popular, and also getting lots and lots more contributions (often in slighly chaotic ways, as things go with open source), this transition is probably the most challenging of them all yet! There are many more things to take into consideration than there have been six years ago. Still, much of it has been going on ever since Qt 6.2 with QtWebEngine was released in September 2021, with a branch with almost 300 commits being nearly finished. If you haven’t yet, you should probably give it a try!

Looking forward towards qutebrowser v3

There are still some challenges to overcome on the development side of things, and some other stuff I’d like to at least look at for the v3.0.0 release. Last year, my job situation changed as well: Instead of being employed 40% over the entire year (often taking a lot more energy and mind-space than those 40%), I’m now busy teaching between September and February. On the flip-side of the coin, that means I don’t have anything other than open source (qutebrowser, pytest, and the occasional paid pytest company training) to worry about between March and August. Last year has shown that this works out much better, especially for big chunks of work like this.

Even though things are still very busy dayjob-wise now (and will be until March), I’m hoping we can still work on some of the remaining Qt 6 blockers, and then I’m hoping to still be able to finish v3.0 early next year. Thanks also to everyone who keeps the ball rolling while I might be busy with other stuff for a while – especially @toofar, who has been doing amazing and steady work over the last couple of years!

Onwards, and already looking forward to qutebrowser being a decade old in late 2023!

All posts

  1. Better nightly builds on CI, state of Qt 6 support, and steps towards v3
  2. CVE-2021-41146: Arbitrary command execution in qutebrowser on Windows via URL handler
  3. qutebrowser moving to Libera Chat
  4. Paying it forward
  5. Paving the road towards qutebrowser v2.0
  6. 2019 qutebrowser crowdfunding - reminder
  7. qutebrowser meetup Berlin (2019-11-28)
  8. 2019 qutebrowser crowdfunding with shirts, stickers and more!
  9. Current qutebrowser roadmap and next crowdfunding
  10. Crowdfunding 2019 ideas
  11. Happy birthday, qutebrowser!
  12. CVE-2018-10895: Remote code execution due to CSRF in qutebrowser
  13. qutebrowser v1.3.3 released (security update!)
  14. qutebrowser v1.2.0 released!
  15. T-Shirts shipped, initial implementation of per-domain settings
  16. Current state of per-domain settings
  17. qutebrowser v1.0.0 released!
  18. qutebrowser v1.0.0 is coming closer
  19. New config merged!
  20. Config revolution - Part 1 finished
  21. Refactoring more things, a working YAML config, and more!
  22. Refactoring all the things!
  23. First week
  24. First 2 days
  25. Getting started again
  26. Second qutebrowser crowdfunding launched!
  27. qutebrowser v0.10.0 released
  28. Wrapping up and looking at the future
  29. Days 39/40/41: Lots of features!
  30. Days 37/38: Hints in master, tests
  31. Day 36: Hints!
  32. Days 33-35: Mouse functionality, and rewriting hints
  33. Days 31/32: More web elements
  34. Days 29/30: Web elements
  35. Days 27/28: Settings and web inspector
  36. Day 24-26: Refactoring the WebElement API
  37. Day 21-23: After Europython and releases
  38. Day 19/20: Bugs everywhere!
  39. qutebrowser v0.8.0 released
  40. Day 18: Javascript
  41. Day 17: Printing and searching
  42. Sending out qutebrowser and pytest stickers
  43. Day 15/16: Merged!
  44. Day 13/14: Almost merged!
  45. Day 12: Tests running!
  46. Day 10/11: Refactoring!
  47. Day 9: A bit of everything
  48. Day 8: More fixing and pytest sprint/training
  49. Day 7: Fixing things
  50. Day 6: Branching off
  51. qutebrowser v0.7.0 released
  52. Day 4: Playing whack-a-mole
  53. Day 3: Last pull requests and managing requirement files
  54. Day 2: More pull requests and nicer test output
  55. Day 1: Merging pull requests, and a stupid bug
  56. About and Timeline