Two Text Files and a CLI

I like to-do lists and other ways of tracking what I have to do. I’ve been using various versions of them for over a decade, to varying degrees of success.

Some to-do lists I’ve used: Remember the Milk, Toodledo, Paper, 2Do (with Toodledo), Todoist, a half-assed bullet journal, Todoist (again). The way it usually works is: I decide to use a system, I use it really well at first, then my usage declines. Eventually I stop using it, and figure I can keep track of everything in my head. But inevitably, I realize that doesn’t work.

The problems inherent in the system:

  • Paper doesn’t handle recurring tasks very well. With any paper journal or diary, you have to remember to write down the recurring tasks repeatedly. Bullet journals do have a “monthly” page but I never used it well.
  • Digital ones confine me to what the service offers, and what I’m willing to pay for. I don’t want to pay for something I’m not going to use too much, but then I can’t do as much, creating a chicken-and-egg dilemma.
  • There’s also no way to bulk edit or things like that in most digital journals.

Your Worth Is Not Your Productivity!

Before we go on, a quick PSA: your worth is not measured by your productivity. You don’t have to “do” tons of stuff everyday to be a decent person!

But for me, I need a decent productivity system. Being on top of things gives me a dopamine rush. When I don’t manage things well, I start missing things, and eventually I have to start every email with “sorry it took me so long to get back to you.” It’s basically literally Bojack Horseman’s “Stupid Piece of Sh*t” episode.

Enter todo.txt

The thing I’ve been doing now is called todo.txt, which, shockingly, is basically just a text file, which you can name whatever you want but todo is the most intuitive. You probably also want a done.txt, which you move things to when you’re done.

As an example, to add an entry to the to-do list, add a line to the file e.g. “Write blog post.” To mark an item as complete, prepend it with an x, e.g. “x Write blog post.” You can also prepend the date it was completed, like this: x 2021-10-20 Write blog post

You can also do the following:

  • Assign priority with capital letters (A-Z)
  • Assign projects with +, and contexts with @
  • Arbitrary key:value pairs with a colon. None of them are “official,” but some are widely supported such as due: and url:.

Here is an in-depth example: (A) 2021-10-20 Write blog post +ACV @laptop due:2021-11-01

All of this is free, human-readable, and lightweight as heck. There are apps you can use: for Windows, SwifttoDo for iOS (and a few others), the official CLI app for Mac/Linux, and probably something for Android too. To sync between devices, use any file syncing solution. I use Nextcloud hosted on my NAS. I’ll focus on the CLI, because that’s what turns this from “simple but effective” into exactly what I need.

The todo.txt CLI

The CLI is a program called, which you can alias to t or todo. The commands it supports:

  • todo ls: see what’s in the file, sorted by priority
  • todo ls +ACV: filter by project (or context, or key, etc)
  • todo add “Write blog post +ACV”
  • Tasks are given a numeric ID, which is just their line number in the file
    • todo do 23 - mark a task as done
    • todo pri 413 V - set the priority of a task

Using and Making Plugins

The best thing about todo.txt is, it supports plugins! You can quickly go from “I wish it did X” to “oh cool it does X now.” Plenty of plugins exist already, but if you can do some scripting, you can make your own.

Making a plugin is simple. Define the TODO_ACTIONS_DIR environment variable in your setup. Have a file in that directory that’s executable, e.g. test (can be pretty much any language you want). todo test now works as a command. Your script will be given a bunch of environment variables, including the color scheme and file locations.

Here is a plugin I wrote called Summary that produces a quick, color-coded summary of what I did that day and what I have left. Notice the usage of the TODO_FULL_SH, TODO_FILE, and DONE_FILE environment variables.

Plugin Code

Here’s an example output:

Plugin Output

Due Dates and Recurring Tasks

Due dates are not officially supported, but lots of implementations do handle them. Matthew Zimmerman wrote a plugin that adds a due command. This reads the due:YYYY-MM-DD key-value pair, and it can list what’s overdue or due today, reschedule, or show you a weekly agenda.

Another thing I want are recurring tasks. There are some apps that support this, but there are some limitations. For example: rec:1m specifies a recurring task that recurs for a month, but you can’t tell it to ignore weekends. And this is where plugins came to the rescue yet again.

todo.txt allows you to make a plugin that has the same name as a built-in command. Accessing the built-in version can be done with todo command X, otherwise todo X defaults to your version. So I made a plugin called do to handle my recurring tasks. It conditionally creates a new task, and then calls command do to let the built-in functionality proceed as normal. My plugin handles rec:3d (recurring every 3 days) but also rec:mtwrf (recurring every weekday).

Here’s a list of plugins I make or use:

  • do: handle custom repeats
  • due (not mine): handle due dates
  • due2: an unfinished due date implementation
  • review: generates a weekly review, also creates a “trigger list” for thinking of new tasks summary: showed above
  • I also have a fairly functional time-tracking system working, sort of implementing Timewarrior with the todo.txt format

As you can probably tell, if I want a feature, I can make that feature happen, usually in an evening. I don’t even have to use the command-line system they made - it’s just a text file, I can use a text editor directly. There’s a vim plugin as well, though I didn’t like it. You can use cat, ack/grep, cut, etc - that’s what the CLI does behind the scenes, mostly.

Tips and Resources

Finally, I’ll leave you with some system-agnostic productivity tips:

  • “Productivity” systems only work for you as long as they work for you. If it works, great! If it stops, ditch it!
  • At the start of the day, think of what you have to do. Make a task for everything, unless making tasks would take longer than doing them.
  • It’s fine to not do everything or let things spill (unless it’s time sensitive but I’m not your boss).
  • If you keep putting something off: do you actually have to do it? Either do it or delete it.
  • Essentially: make a plan, stick to the plan, always deliver! Just like they say in Storks, that movie where the birds have teeth.

And some resources: