I am a big fan of:
- simple note taking for keeping track of details that don't fit into my short-term memory
- ultra-simple TODO lists
After several years of writing custom apps to do this (too much work), trying Wunderlist (which doesn't have good, programmer-quality sub-tasks in their free version, in my opinion), and working with paper notes (more difficult to re-order notes than in a text editor), I've found a solution that seems to be working great for me.
It allows the benefits that all good note taking solutions need:
- Keep yourself sane and focused on the right priorities
- Don't forget little details
- Easy to re-organize and share
- Absolute minimal (or ultra-reliable) technology
- If technology is involved, then those notes need to be reliably backed up without relying on some 3rd party cloud service that could be gone tomorrow or have an outage at a critical time when I really need my notes
Using technology for notes was actually a hard decision
Let me say right up front that I rarely draw diagrams or use images in my notes, and when I do they're best stored on paper or a whiteboard. I'm a programmer, and using something like EverNote (while powerful, and ubiquitous - I gave it a real try several times over 2-3 years) for the 99% of my notes that are just plain text, in order that I could also have image support wasn't worth it. Jumping into EverNote was more of a pain than jumping to my ever-present friend, my text editor. What I really wanted was simplicity, no reliance on 3rd parties required, and a timestamp on notes if I really wanted to know when they were written (this is seldom important, but kind of nice).
On the other hand, I also wanted a solution that would capture all types of my notes, so that's why I tried (and re-tried) EverNote so many times.
I was also initially dubious of using technology to solve my problem, since it's just not as simple as paper notes. There is a lot to be said for a simple notepad and a pen or pencil. In fact, for the last several years I've been using this artist sketchbook paper to keep all my temporary notes; it has no lines, is easy to recycle, and features tear-out pages.
However, I largely moved away from using paper when I started managing a ton of little details on projects, and diving into particularly tricky algorithms over a period of days or weeks. I found myself thinking of things I needed to remember to review, write tests for, or ensure were still working before deploying my code; and I needed not to forget any of those little details days or weeks after the initial insight. So, while capturing these details on paper worked pretty well for a long time, when I wound up with 100 details that then needed to be organized, re-organized, and priorities into a TODO list when I got back to my desk, paper just wasn't ideal.
The three simple, small pieces of my workflow
DISCLAIMER: If you're not already using
git or another SCM like
mercurial or something modern, then just stop here. This post is written by a programmer, for programmers,
To solve my note taking dilemma, and in conjunction with my fairly recent move to full-time Linux and vim usage, I started keeping all my notes in text files, automatically backed up by
git to my own
git server. Of course, if you don't want to use or host your own
git server, then GitHub will work fine (except that they're a 3rd party you must rely on - it's a tradeoff).
1. a simple, combined format for notes and TODOs
I use the following format for nearly all notes:
Here's a free-form note that isn't a TODO. It might, for example, describe the purpose of this list, or describe some design philosophy or something. Pending ======= - Something to be done / Something complex, that is partially completed - With multiple sub-steps - Some of which still need to be done | And some of which are complete Done ==== | Writing this blog post, for example, is done. You can continue multiline notes with simple indentation rules that are similar to how you already write code. Lines that are indented and begin with "-", "/", or "|" are sub-items, while lines that are just more text are a continuation of the previous line
The following, simple conventions are followed:
- Use "-" for something that needs to be done
- Use "/" or "\" for something that's partially done (and/or has sub-steps that aren't yet done)
- Use "|" for something that you believe to be done
- Free-floating notes are just written out as needed and not prepended with any symbols.
- Split "pending" and "done" tasks into separate sections. Technically these labels are redundant since the symbols already indicate the state of an item. However, I found that visually splitting up the list helped me to know how much progress I was making as the "Done" section got longer.
These five simple rules make for an as-detailed-as-you-need-it-to-be list that doesn't involve all the overhead of ticket or task tracking systems, it's sharable with your colleagues if that's necessary via your SCM tool (though I find it really useful for my own notes that constitute tiny implementation steps that aren't necessary to share with anyone), and it's extremely quick to see what's done and what isn't at a glance.
A real-world example may look something like this:
Dependency resolution project for new package manager. Pending ======= / Dependency resolution code | Handle simple dependencies - Handle circular dependencies - Finish test suite - Write unit tests - Write speed tests - Try it on a simple package install - Did it work? - Were there errors? - Did anything unexpected happen? - Try it on a complex package install - Did it work? - Were there errors? - Did anything unexpected happen? Done ==== | Flesh out design with coding partner | Estimate tasks and update ticket tracker | Send updated estimate to client
2. a simple script to commit and push changes
Here's the script that I use to auto-commit and push my notes changes. It adds a simple commit message that indicates that the script made the commit, as opposed you making a commit by hand, which you can still do. This script should work unaltered on OS X and Linux:
#!/bin/bash # NOTE: This auto-commit script must be executable cd /path/to/my/notes/repo/ git add . git commit -m "Automatic commit: $(date)" # Nothing is committed/pushed if nothing has changed. # You can detect this via the exit code from the # 'git commit ...' command. # # Also, since this is a simple note taking repo you # really don't need anything beyond the 'master' branch. if [[ $? -eq 0 ]] then git push origin master fi
cron job to periodically run the script
# Auto commit and push every 10 minutes */10 * * * * /path/to/my/notes/repo/auto-commit
The are only four, small gotchas that I've run into after using this method for about 6 months, all of which are minor concerns for me.
gitserver you're pushing to must be accessible at least once in a while (once a day at worst?) for your commits to get backed up, but who isn't online most of the time these days?
- The commit script won't remove files that have been deleted or moved/renamed. I consider this perfectly fine, since renaming and removal of files from my notes repo is something I periodically do by hand, and it's not a big deal since I don't want the
auto-commitscript to be deleting files from the repo without my personal intervention.
- If the
cronjob doesn't run you might not know that it failed. This isn't a huge problem for me since I'm in my notes and I remember to check the
git logevery few days, so I know it's committing and pushing, but if you're the forgetful type this might catch you in a bind. Also,
crontends to be hyper-reliable so long as you have a properly written
cronjob, so I don't worry about
cron's reliability in this respect.
If you're sharing your notes repo with colleagues (I don't, typically - it's for my personal use), then the commit script won't handle merges and such. I suppose you could add the following line to the script (before the commit line) to address that, however:
git pull origin master
Just don't branch on your notes repo and life will remain simple and beautiful.