Minimal TODOs for Linux

Up until now I’ve just used bits of paper for my TODO system. This has served me quite well, but the problem is that bits of paper are too easily lost or mislaid. So, after reading Minimally Awesome TODOs I wanted to set something similar up for my Ubuntu box. Minimally Awesome TODOs describes a very simple TODO system for the Mac that displays your TODOs on the desktop. With a few tweaks, I got a very similar system working on Linux, which looks like this:

To add a todo you just use a simple terminal command:

$ todo example blog todo

To complete a todo:

$ todone 3

It was pretty easy to port the system from Mac to Linux (I did it on Ubuntu Unity, but it should work for pretty much any Linux distro with a few minor changes) by following the instructions in the post and follow-up comments, but I’ll repeat them here to save others effort. Firstly, create the following shell scripts:

$ cat /usr/local/bin/todo
if [ $# == "0" ]; then cat $TODO; else n=$(($(tail -1 $TODO | cut -d ' ' -f 1) +1)); echo "$n ⇾ $@" >> $TODO; fi

$ cat /usr/local/bin/todone
sed -i -e "/^$*/d" $TODO;

UPDATE: Improvements to these scripts can be found in the comments. Or, even better, try Todo .txt, which has a similarly minimalist interface but some more advanced features. There is also a page on setting it up with conky, similar to what is done below. (I found that I had to rename todo.cfg to config to get Todo .txt to work correctly though). Thanks to Fred for suggesting Todo .txt.

Remember to set them to be executable (chmod +x /usr/local/bin/todo). You then need to set a TODO environment variable to wherever you want to keep your TODO file (i.e. add something like export TODO=~/todo.txt to your .profile). If you want to sync your TODOs over several machines, you could point it to a dropbox folder or similar.

For the next step, you need to install conky, a utility for displaying info (more normally system monitor stuff) on the desktop (you should be able to grab this from your package manager). To get the same set-up as me, use the .conkyrc in this gist – I had to play around with the basic config to get it to display properly in Unity, you may face different problems in other window managers.

Finally, you should set conky to run on startup – in Ubuntu just open Startup Applications and add it to the list. UPDATE: I had a problem with the conky window staying on top of all other windows. To fix this I needed to launch conky from a script which first did sleep 10 to give the window manager time to finish starting up.

I can’t take credit for any of this stuff, all I did was put together a bunch of hints from the internet.

15 Responses to “Minimal TODOs for Linux”

  1. Moses Moore Says:

    What happens if I `todo` four items, `todone` items 2 and 3, then add another item? My list is numbered 1,4,5. That could get awkward after a while. The command in /usr/local/bin/ will also do weird things if you have a user on your system that does not or forgot to export ${TODO}.

    Try these instead:
    [ “$TODO” ] || TODO=”$HOME/.todo.txt”
    [ -f “$TODO” ] || touch $TODO
    [ ! “$1” ] && awk ‘{printf(“%3s – %s\n”,NR,$0)}’ $TODO || echo “$@” >> $TODO

    [ “$TODO” ] || TODO=”$HOME/.todo.txt”
    if [ -f “TODO” ] || [ ! $1 -gt 0 ];then exit 1; fi
    awk ‘NR != ‘$1′ {print;}’ $T && mv -f $T “$TODO”

  2. Fred Says:

    Check out the open source todo.txt project at:

    Supports priority, project, context and description in your to do list.

    Their CLI utility runs on Linux and Mac and Windows (with Cygwin). And apps for Android and iOS. The todo.txt file syncs with Dropbox. Works great! On Mac OS X you can display the file on your desktop with Geektool.

  3. Khaja Minhajuddin Says:

    Here is a TODO cli app with simple tagging and repetitive tasks

  4. Beetle B. Says:

    Personally, I use Emacs’s org mode. However, for CLI, try Task Warrior:

  5. reader_1000 Says:

    Thanks for script
    I updated your script a little bit

    # to add
    todo do things you do not like
    1 ⇾ do things you do not like
    There are 1 things to do.

    #to remove
    todo del 1
    todo rm 1

    #to remove multiple items
    todo del 1 2 3

    # to remove everything
    todo truncate

    if [ -z “$TODO” ]; then
    export TODO=~/todo.txt
    if [ ! -f “$TODO” ]; then
    touch “$TODO”

    if [ $# == “0” -o “$1” == “list” -o “$1” == “ls” ]; then
    cat “$TODO”;
    n=$(wc -l “$TODO” | cut -d ‘ ‘ -f 1)
    tput setf 4
    echo “There are $n things to do.”
    tput setf 0
    elif [ “$1” == “del” -o “$1” == “rm” ]; then
    for var in “${@:2}”;
    sed -i -e “/^$var/d” “$TODO”;
    n=$(wc -l “$TODO” | cut -d ‘ ‘ -f 1)
    echo “There are $n things left”
    elif [ “$1” == “truncate” ]; then
    echo -n “” > “$TODO”
    echo “Everything done.”
    n=$(($(tail -1 “$TODO” | cut -d ‘ ‘ -f 1) +1));
    echo “$n ⇾ $@” >> $TODO;
    n=$(wc -l “$TODO” | cut -d ‘ ‘ -f 1)
    tput setf 2
    echo “$n ⇾ $@”
    tput setf 0
    echo “There are $n things to do.”

  6. Aximilation Says:

    I second Beetle on I used it a while ago and remember it being clean and elegant, but also able to support projects and GTD style organizaion. It would be very simple to put together a script or two to display the tasks in conky. Check it out!

  7. reader_1000 Says:

    although this is neither nice nor efficient way of doing, I added the following code to the script so that it will re-index the items in the todo list

    elif [ “$1” == “reindex” -a $# == “1” ]; then
    while read line
    old_index=$(echo “$line” | cut -d ‘ ‘ -f 1)
    sed -i “s/$old_index/$i/” “$TODO”
    i=$(($i + 1))
    done reindex todo
    3 -> do it now
    5 -> are you still waiting

    running “todo reindex” will convert it to
    1 -> reindex todo
    2 -> do it now
    3 -> are you still waiting

  8. bitigchi Says:

    Is it possible to do this in Mac OS X?

  9. Adrian Mouat Says:

    @Moses Moore, @reader_1000, thanks for the suggested improvements! I’ll try them out and update the post if that’s ok.

    @bitigchi, the post has the MacOS app which this is a port of. It is very similar, but doesn’t use conky and puts everything in bash functions rather than /usr/local/bin scripts.

    @Beetle B, @Aximilation, I’ll check out taskwarrior. But I really want to keep things as simple and low impedance as possible.

  10. Paul Beckingham Says:

    Adrian Mouat says:

    > But I really want to keep things as simple and low impedance as possible.

    This really is the most critical part. TODO software needs to be as minimal as possible when it comes to the four basic operations: add, done, delete, list. Beyond that, it helps to have automatic installation, man pages if you need them, and tutorials.

    Nice article Adrian.

  11. Adrian Mouat Says:

    Thanks for all the comments. Task Warrior is bit more complex than I’m looking for, but Todo .txt looks great – it has an equally minimalist interface but some extra features should you need them.

  12. Zhang Huangbin Says:

    Slightly improved.

    *) Don’t hard-code line number. Use ‘cat -b’ to get actual line number.
    *) Delete task with sed.

    # .bash_profile
    export TODO=~/.todo
    todo() {
    if [ X”$#” == X’0′ ]; then
    [ -f $TODO ] || touch ${TODO}
    cat -b $TODO
    echo “$@” >> $TODO

    todone() {
    export line=”${1}”
    sed “${line}d” ${TODO} > ${TODO}.tmp
    mv ${TODO}.tmp ${TODO}

  13. Zhang Huangbin Says:

    Add function to top a task: todotop.

    todotop() {
    sed -n “${1}p” ${TODO} > ${TODO}.top
    todone ${1}
    cat ${TODO} >> ${TODO}.top
    mv ${TODO}.top ${TODO}

  14. Adrian Mouat Says:

    Thanks Zhang. I’ve move to Todo.txt, but hopefully someone else will find that useful. My current problem is that conky doesn’t seem to play nice with Ubuntu and Chrome – I quite often end up with conky either disappearing completely or on top of all the windows.

  15. Zhang Huangbin Says:

    Todo.txt? will have a look later, thanks for your sharing. :)

    I improved the shell code today, It now supports multiple projects/files, with 3 actions available:

    – Create a new task in project “prj”: td prj task
    – Delete third task: tddone prj 3
    – Move third task on the top: tdtop prj 3

    Shell script is available here:

Leave a Reply