todo cli

I wanted to manage my todos via the command line and didn’t know of any obvious solution. I really didn’t want to use anything that was too complicated or overkill. I basically just wanted to manage todos as easily as I would if I were just editing markdown files. So I made something painfully simple and it works really well for me.

markdown files

I started with a directory of markdown files.

mkdir ~/todo
vim ~/todo/
vim ~/todo/

shell script

Cool, now I can just edit those guys. Great. But I didn’t want to have to type vim ~/todo/ every time I wanted to edit a file. So I made a script.

I created /usr/local/bin/todo:


echo editing: $1
vim ~/todo/$

Then made it executable:

chmod +x /usr/local/bin/todo

And now I can simply:

todo work

It’s nice because if the file already exists I’ll edit it and if not it will automatically create a new one. Simple functionality.


Once I started getting tons of files in my ~/todo directory, I wanted to enable autocomplete, especially so I wouldn’t have to type out long names. Turns out this is p easy.

In my ~/.bash_profile:

# simple todo autocomplete
    local cur opts
    opts="$(ls ~/todo | sed -e 's/\.md//g')"
    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
    return 0

complete -F _todo_autocomplete todo

Now I can type todo [TAB] and see all options.

Basically, autocomplete seems like it’s a bunch of garbage boilerplate with the only really important part being what you set for the opts variable. In my case, I wanted to remove the .md extension from anything in my list because that’s just how I want to interact with these files:

opts="$(ls ~/todo | sed -e 's/\.md//g')"


I wanted to share my active and files with my PM at work so he knows what I’m working on at any given time. So I made a github gist that I can then commit the files to, and they’re formatted all pretty because it’s markdown.

So I made a ~/todo/todo-gist directory and added the following script (


cp ~/todo/ ~/todo/todo-gist/
cp ~/todo/ ~/todo/todo-gist/

echo $d

cd ~/todo/todo-gist
git add .
git commit -m "$d"
git push origin master

And to make my life even easier just added an alias to my bash profile to fire this guy off:

# push todo to gist
alias push="~/todo/todo-gist/"


Now my workflow for managing todos looks like this:

todo work
todo done

It’s extremely extensible and painfully simple. No external dependencies - just editing text files. 🙏