Projects
August 16, 2026•8 min read 

Todoist for Omarchy: Putting Your Tasks Back in the Bar

Todoist for Omarchy: Putting Your Tasks Back in the Bar
Hyprland
Quickshell
QML
Todoist API
Moving to Omarchy — Arch Linux, Hyprland, and a shell built entirely around Quickshell — meant rethinking almost every habit I had. New keybinds, a new bar, new ways of switching windows, new everything. Most of the old workflow just got replaced, and honestly, most of it got better. Except one thing kept dragging me back to the mouse: checking Todoist. Omarchy's bar is full of small, glanceable widgets — bluetooth, audio, network, the clock — each one answering a question before you even have to ask it. My task list wasn't one of them. Every time I wanted to know what was due, I had to break flow, open a browser tab, wait for it to load, and then close it again. On a desktop where everything else was one keypress away, that felt like a workflow bug I was responsible for fixing. There wasn't an official Todoist widget for Omarchy. So I built one. The bar shows a checkmark and a number — how many tasks are due today or overdue. Click it (or hit your shortcut) and a popup drops down with the full list: a checkbox to complete each task, a box to quick-add new ones, and tabs for Today, Inbox, and everything else. A few details I cared about more than I probably should have:
  • Quick-add uses Todoist's own parser. Type p1 finish the deck #Work tomorrow at 5pm and it's parsed exactly like typing into Todoist itself — priority, project, due date, all of it. No custom syntax to learn.
  • Today splits into Overdue and Today. Two clearly separated sections instead of one blurry list, because "overdue" and "due today" are not the same kind of urgent.
  • Priority is color-coded — p1 red, p2 yellow, p3 blue — so the list is scannable at a glance, not just alphabetically true.
  • The popup is a fixed size, not something that resizes itself around your task count. Content scrolls instead of the window lurching every time you add a task.
None of these are groundbreaking on their own. What makes the plugin feel right is that every one of them works exactly the same way with a keyboard as it does with a mouse. This was the actual design constraint, not a checkbox I ticked afterward. Omarchy's whole culture is keyboard-first — Hyprland users don't reach for a mouse unless something's gone wrong. A plugin that only tolerates a keyboard doesn't belong there. So every part of this thing is fully operable without one: Tab/Shift+Tab cycles views and, inside Settings, walks every control in order — token field, save button, filter field, keybind recorder, all of it. Arrow keys move a selection cursor through the task list. Enter opens a task, Space completes it, e edits a title in place, x deletes with confirmation. Getting there took more debugging than the feature list suggests. Quickshell's PanelKeyCatcher only intercepts keys centrally while it holds real focus — the moment a button genuinely takes keyboard focus, that central interception silently stops working, and Tab starts doing whatever Qt's own default focus chain wants instead of what you told it to do. The fix was building an explicit, ordered focus chain by hand and walking it myself, control by control, filtering out anything currently disabled (a disabled control silently rejects a focus request in Qt Quick — it doesn't error, it just does nothing, which is a fun one to debug blind). Here's the part of this build I'd rather not have needed, but I think it's the most honest one to write about.
Built & ValidatedI built a full task editor — title, priority, due date, project, labels, all from one keyboard-navigable form. It passed every structural check I had: the plugin validator, a clean runtime log with zero new warnings, careful re-reading of every function. I shipped it.
Shipped Then BrokenIt didn't work. Not "had a bug" — didn't work at all, for the one thing it existed to do. The keyboard navigation I'd carefully designed around two shared UI components that don't expose their internal focusable element for an external system to hook into turned out to be exactly the kind of thing that looks correct on paper and fails the moment a real person tries to actually use it with a keyboard.
Reverted Same DayI reverted it the same day, in a single clean commit, no trace left behind.
The lesson stuck: a clean log tells you the code ran. It tells you nothing about whether the interaction actually works. If a feature's entire value is its keyboard behavior, the only real test is a keyboard, in someone's actual hands — not a validator, and not my own confidence reading the code back. Todoist's REST API is well-documented, but "well-documented" and "documented in the specific place I need" aren't the same thing. Before building anything that touched task editing, I pulled the actual OpenAPI spec directly rather than guessing from memory or a half-remembered blog post — and it paid off immediately.
Early on, the panel refreshed on a timer and hoped for the best. Add a task, and you'd wait for the next poll to see it land. That's not good enough for something meant to feel instant. Every action that changes something — adding, completing, editing, deleting — now triggers an immediate refresh instead of trusting local state alone. But "immediate" needed a few guardrails: if a refresh is already in flight when another one gets requested, the request doesn't just vanish — it gets remembered and re-fired the moment the first one finishes, so nothing gets silently dropped and nothing runs twice. Completing a task strikes it through and dims it before it disappears, so the refresh happens after that animation settles, not in the middle of it — otherwise the row would just vanish outright instead of visibly completing. Small detail. Took longer to get right than it has any business taking. The build reinforced something I keep relearning on every project: verification isn't one thing. "It validates," "it logs clean," and "it works" are three different claims, and it's very easy to only prove the first two and assume the third. The other half is smaller but just as real — the best productivity tools don't ask you to change how you already work. They just show up in the place you're already looking. I didn't need a new app to check. I needed the app I already trusted to stop requiring a context switch to reach. It's the same idea behind my next bar widget, Waynergy, which shares one keyboard and mouse between my Mac and my Omarchy desktop. The plugin is free and open source. Setup takes under a minute:
  1. Open the panel — with no token saved, it opens straight to Settings
  2. Grab a personal API token from Todoist → Settings → Integrations → Developer
  3. Paste it in, hit Save
That's it. The bar starts showing your count, and everything else — quick-add, completing tasks, the whole keyboard layer — just works from there.
"A tool that only tolerates your keyboard isn't keyboard-first. It just hasn't been tested by someone who never touches a mouse."
—Aryan Techie

Share this post: