Kei's dev logs

As an attempt to gently get myself back to coding after ending a period of employment (and maybe have some fun in the meantime), I coded Todoist for Spoonies, which is a little self-hosted service that makes “spoons” tracking using Todoist more convenient.

What is “spoon theory”, and why are you tracking your “spoons”?

According to Wikipedia, Spoon theory “is a concept used to represent how individuals manage limited energy”. Basically, spoons are used as a metaphor for the amount of energy or capacity. A person may have a limited number of “spoons” in a day, depending on their physical and mental health condition, and each activity they do over the day would consume “spoons” from the pool. This concept has been used in a wide range of communities, including people with chronic conditions, disabled and neurodivergent people, and people living with mental health issues. People who align with this concept sometimes call themselves “spoonies”.

Personally, I am living with both neurodivergence and on-and-off digestive health conditions. Over the years, I have learned how many spoons each task would cost me, in addition to my “baseline” daily number of spoons. The knowledge has been crucial for me to have a good mental picture when planning my days. For example, I can reschedule or cancel social plans when I have spent a large number of spoons at work. I can also choose to do house chores on the days when I have a bit more capacity.

However, counting spoons in one's head is energy-consuming on its own, and I have been figuring out a way to use technology to help with it for a long time.

The evolution of my workflow

Really old user of Todoist

Since my college days, I have been using Todoist to organize and track my tasks. I love its simple UI and well-designed features, and even in 2026 it largely hasn't been infected by enshittification (the team just recently retired a major testing feature to ensure quality!).

Todoist is a great tool for getting (more) tasks done, but for people with limited spoons, its design focus can lead to anxiety and burnout: “I have been feeling pretty drained, but there is still a full list of tasks for me to do.”

Through both successes and struggles as a Todoist user, I have learned that for spoonies like me, focusing on what have been done is equally (if not more) important as what lies ahead.

And the default Todoist interface is lacking in this part. It has good activity logging, but the details are quite hidden in the UI, and there is no way to quantify spent capacity apart from the number of complete tasks. In addition, a Todoist task is designed to be scheduled, time-blocked, and completed only once or in fixed intervals, while in reality, tasks that consume spoons are sometimes frequent, flexible, or unexpected. It would be a hassle to add those tasks in the app and then complete them.

My attempt to solve these problems has eventually lead me to explore Todoist automations.

sample template project

To start with, I made a list of labels (sp-1, ..., sp-5, etc) for each task's spoon consumption, and when I create tasks, I can tag them knowing how much energy they are going to use. I also created a “template” project to put those potentially spoon-consuming unscheduled daily tasks in (Example screenshot above). The automation should do two things:

  1. Automatically add the task back after completing a task in “template” project.
  2. Count the spoons in completed tasks, and provide a way for me to view them.

I first built the automation two years ago, using Zapier connectors with Todoist. Telegram was used to send scheduled messages about daily spoon counts. It mostly worked over several months, but it was buggy, slow and very expensive, requiring a $30/month Zapier subscription. So after a while I cancelled it and resorted back to manually tracking with the Todoist labels.

Until when I decided to code my own Todoist automation.

Developing this project

I started first by looking at the Todoist API documentations. The webhook approach seems the best fit for this use case compared with polling its APIs. So I began by coding a simple HTTP server that could complete Todoist authentication and receive webhook requests.

I knew that I would need to run a Telegram bot alongside the HTTP server, and in addition separate loops are needed for Todoist token refresh and the daily scheduled messages. Designing a pattern that could put these different components together turned out to be the most challenging part of this project. I used Robyn initially for the HTTP server, but later realized that its underlying Rust runtime makes it very hard to control in a Python async event loop.

Turns out using aiohttp for HTTP client/server is a great choice. The Telegram bot, HTTP server and background loops can be chained together elegantly using good old async Python.

After figuring the architecture out, the rest of the implementation (choosing a data store, implementing the webhook handlers and Telegram commands) is straightforward. In total, I spent three afternoons working on this project, and deployed it on one of my VPSs.

The messages from the automation look like this:

sample daily message

The code is available. Although probably few people would use the same Todoist workflow, you are welcome to reference or fork it if it's helpful.