I’ve had a few really good coding days in a row here, which has meant not as much blogging this week. I figure Friday is a great time to offer a quick overview of how I manage coding projects with TaskPaper and a few command line scripts, since I’ve been doing a lot of that this week.

This system is for people working on projects that involve time in Terminal. That’s going to be mostly programmers and web developers, I think. Everyone else should probably just wait for my next fun post on mind mapping or something…

The system

I keep a TaskPaper file for each project in the root of the project folder. This gets included in a git repo, syncing to everywhere I work on the project, and allows me to go nuts with todos for a particular project without terribly cluttering up OmniFocus. I’ve been doing this for a long time and it’s always worked really well.

When I start a new project, I just run td (info below) to create a base skeleton. I can edit this directly in TaskPaper or in any text editor (or TaskMator on my iPhone).

While I’m working, I add new todo items to my Inbox using na. Often todo items are bugs reported via my ticketing system, so they’ll be a quick description with priority level and a link to the ticket. Sometimes I notice a bug while working on another one, and I’ll add it as a todo so I don’t get off-track. Same with new ideas for the roadmap (or feature requests from users).

When I cd into a project folder, na shows me my top todo items via a prompt_command hook. I can also type na at any time to see what’s up next. na works with sub-projects, listing them recursively, and even with seeing what’s next in a project in any other folder where I’ve used na before. Global todo lists.

Priorities

Tags in TaskPaper are created with an @tag syntax, and you can add a value to a tag using parentheses, e.g. @priority(5), which is how I quickly sort my roadmaps and bug reports. My priority system uses 1-5, with 5 being the highest. It translates to:

  • 1 and 2: Very low priority, but still intend to do when possible. 2s are things that I think I should tackle before 1, but still considered unimportant.
  • 3: Important but not urgent. They definitely need to be tackled. Eventually.
  • 4: Top priority, but not roadblocks for the current release.
  • 5: Urgent, and must be completed in order to release this version.

I regularly review the items in each priority, modifying them based on changing circumstances. Because I only work for myself (and my customers), I rarely have to deal with other people defining my priorities. Something that originally seemed like a 4 can quickly become a 2 as things change in the roadmap.

After a release, all of the tasks with @priority(5) should have been cleared and archived. Then it’s time to review the 4s and see what should be bumped up to top priority for the next release. A lot of level 4 priority tasks are urgent, but weren’t roadblocks to the current release. If I’m trying to get a release out, I’ll also review the 5s to see what can be demoted to a 4 for now, revisiting them after shipping.

Other Tags

I rarely overload these project files with tags. My Next Action tag is @na, and na uses it to list what to work on from the command line (obviously, that’s why it’s called na). Because na adds the @na tag to every new task unless I tell it not to, this tag is reviewed regularly from a TaskPaper search. I just click the @na tag and sort through what’s actually a “next action,” adding priorities where needed.

The other tag I always use is @maybe. This one is for tasks that have no priority, usually ideas I have while working on something else, or requested features that would be kind of cool but need further consideration.

The tools

Here’s an overview of the tools I’ve mentioned thus far.

td

My td function simply looks for a TaskPaper file in the current directory and opens it in TaskPaper. If one doesn’t exist, it creates one with my default skeleton. It names it based on an argument, or just uses the current directory name. na actually has this functionality built in if you use it to add a task when there’s no TaskPaper file, but td is a simple way to both create a file and/or open the current project in TaskPaper. Here’s the script:

# [Create and] open project todo
# If you don't pass a name as an argument, it's pulled from the directory name
td() {
	if [[ -n $1 ]]; then
		proj=$1
		todofile=$proj.taskpaper
	else
		proj=${PWD##*/}
		todofile=$proj.taskpaper
		todofile=${todofile#.}
	fi
	if [ ! -e $todofile ]; then
		touch $todofile
		echo -e "Inbox:\n$proj:\n\tNew Features:\n\tIdeas:\n\tBugs:\nArchive:\nSearch Definitions:\n\tTop Priority @search(@priority = 5 and not @done)\n\tHigh Priority @search(@priority > 3 and not @done)\n\tMaybe @search(@maybe)\n\tNext @search(@na and not @done and not project = \"Archive\")\n" >> $todofile
	fi
	open -a TaskPaper $todofile
}

Now, from a directory called myNewProject, I can just type td and it will create myNewProject.taskpaper, filling it in with:

I get an Inbox and an Archive, some basic categories common to all my projects, and some default search definitions for TaskPaper 3.

na

Note: if you already use na, be sure to update your script from the GitHub repo. I just pushed a new version this morning with all of the local changes I’ve made as I’ve been working over the last couple of years.

I actually use na more often than TaskPaper itself while I’m working on a project. I won’t go into full detail as this is all documented, but I’ll give you an overview.

I can add new tasks with na -a. If you include a task description, it will just add that task directly to the inbox: na -a "write about my TaskPaper project management system". That will add the task along with the @na tag to my Inbox. If you don’t include the task description, it will prompt you for it with readline.

I can also set a priority immediately when adding a task with the -p flag, e.g. na -a -p 5 "another thing to do". If I want to include additional tags, I can put them right in the task description, na -a "one more thing @maybe". If the task needs a note or a link, I just use the -n switch, which will prompt me for an additional note before adding the task, attaching it to the task in TaskPaper format (no leading ‘-‘).

Using na for listing tasks is just as easy. Running na with no arguments will list all @na tasks in the current project. It allows you to have other task files in subfolders as well, and you can list everything within the current project at once with na -r. For example, I have a separate task file for the help documentation in Marked, in the Docs subfolder. (I don’t really remember how this happened, but it’s never been an issue to separate the two.) I can see all of my next actions between Marked and its documentation combined.

You can list tasks based on tags other than @na. na -t maybe finds all @maybe tasks. You can even search for specific values by tagging on a -v VALUE, so listing all @priority(5) tasks, even without the @na tag, looks like na -t priority -v 5. There’s a shortcut for @priority, though: na -p 5.

(In case you’re wondering, g is my alias for Bashmarks.)

TaskPaper

TaskPaper makes managing, reviewing and organizing these project files much simpler than a command line tool. The search definitions I include make it easy to quickly see priorities and edit them. I can move tasks from the inbox to a section with ⌘\ (the Move to Project shortcut). I can add tags manually or using various scripts that I have as shortcuts.

I can also just click on a tag in a task and see everything with that tag. That makes it easy to remove that tag from other tasks as needed. As an obvious example, I can click @na and then remove the next action tag from any that aren’t actually next actions.

TaskPaper makes it easy to navigate and drill into the sections of the project file. It makes it easy to add new tasks and sections. It makes it easy to flip tasks from one section to another. And the search/filter features make it easy to reference the task file in ways that na can’t.

Side note: I also have a few keybindings for TaskPaper tags that allow me to quickly add tags like @done and @priority() in any app (e.g. nvALT or Vim). Here’s the relevant section of the DefaultKeyBinding.dict file.

I do also recommend Taskmator on iOS, and the PlainTasks package for SublimeText is top notch.

Back to Work

Ok, now that I’ve shared all that, I have a list of bugs to squash (I see them every time I cd bitwriter or cd marked). I hope this was at least interesting to other coders… share your own thoughts in the comments!