Some Org Mode agenda views for my GTD weekly review
GTD Weekly review
I am an extremely lazy and messy person. As such, in order to survive, I need a system to find my way out of bed in the morning, have something to eat in the fridge, don't forget to pick my children at school, feed the cat and things like that.
More than 15 years ago, when I already was an Emacs user, I heard about Getting Things Done (GTD for short), a book and a personal productivity system that promised to save my life. I bought the book and started implementing the system right away. If you don't know anything about GTD, reading the Wikipedia entry will give you a good overview. In short, the action management part of the system relies on the following steps:
- Capture everything you have to remember or solve.
- Periodically empty your inboxes (what you have captured, and any other input you get as e-mail, physical stuff, etc.).
- Transform every input into either actionable things, reference material or trash. Actionable things can be projects (need more than one action), next actions (everything is ready to do what you need to do) or things to delegate.
- Maintain lists for actions and projects.
- Periodically review your lists.
- Don't forget to do some of your actions from time to time!
This is a crude description of the system, but it will be enough for the rest of this article.
The funny thing is that one could imagine that, as an avid Emacs user, I looked for ways to implement GTD with it. But the real story is that I discovered GTD because, when I was looking for ways to manage actions with Emacs I found what I think is the absolute reference on the use of Org Mode to get organized, and GTD is cited there.
Implementing GTD with org-mode
My implementation is much inspired by Bernt Hansen's suggestions in the above-mentioned site. For actions, I use the following states:
(setq org-todo-keywords (quote ((sequence "TODO(t!/!)" "NEXT(n!/!)" "STARTED(s!)" "|" "DONE(d!/!)") (type "PROJECT(p!/!)" "|" "DONE_PROJECT(D!/!)") (sequence "WAITING(w@/!)" "SOMEDAY(S!)" "|" "CANCELLED(c@/!)"))))
The meaning of these states is:
- an action that I need to do, for which I have estimated the effort, and for which I have everything to start acting.
- an action that I need to do but that I don't want to see in my next actions list.
- a next action for which some progress has been made.
- a finished action.
- an action to be done, but for which I am waiting for some input or some action from somebody else.
- an action that could be interesting to do, but on which I don't want to commit yet.
- an action that I decided that I finally don't need to do.
The projects are just containers for related actions.
Next actions are very important. They are what allows to achieve progress even in periods of crisis or low energy. All my actions have tags for contexts. These can be general (work, admin, errands) or specific (the name of a particular project or person, a type of activity (reading, programming, writing). This allows to easily generate lists of actions which match a set of tags. The final thing that makes a next action special is the effort estimation. Using Org Mode properties, I assign an effort estimation to each next action, so that I can also filter by estimated duration when I have limited time available.
Since I spend most of my time in Emacs, using the Org Agenda makes being organised an easy and pleasant experience. The Org Agenda is my main dashboard that I trigger with
C-c a. I think this is the default key binding, but I have this in my Emacs config:
(define-key global-map "\C-ca" 'org-agenda)
My Org Agenda is built from more than 60 Org Mode files.
The GTD weekly review
One key part of maintaining a clean GTD system is the weekly review. Once a week, I sit down for 90 minutes to 2 hours and I go through this checklist:
[ ]Re-schedule / re-deadline today's tasks
[ ]Collect loose papers and materials
[ ]Mental collection
[ ]Get ins to zero
- Questions :
- What is it?
- Next action?
- 2minutes? (do it)
- delegate? (waiting for)
- defer it to a specific date?
- or next action to do it ASAP (tag next)
- Is it multiple actions?
- Next action?
- Reference material (tag reference)
- Incubate (remind me later) (tag incubate)
- Trash it
- What is it?
- Questions :
[ ]Get current
[ ]Review next actions list
[ ]what might have been important may not be it anymore
[ ]check that we have effort for all
[ ]Go back to previous calendar data
[ ]things which got rescheduled or should
[ ]actions which were not done
[ ]Review upcoming calendar
[ ]Review waiting for list
[ ]Stuck projects
[ ]Look at project list
[ ]Review relevant checklists
[ ]Get creative
[ ]review someday/maybe
[ ]generate new ideas
For some of these steps, I have Org Agenda custom commands or specific agenda views which are very useful. I am sharing them below.
Reschedule / redeadline today's tasks
After a week without reviewing my system, undone actions begin to pile-up and my dashboard is very crowded. The first step is therefore reschedule or cancel some actions. For that, I generate a Daily Action List with the following Org Agenda custom command:
(setq org-agenda-custom-commands (quote (("D" "Daily Action List" ((agenda "" ((org-agenda-span 1) (org-agenda-sorting-strategy (quote ((agenda time-up category-up tag-up)))) (org-deadline-warning-days 7)))) nil) ;; [....] )))
C-c a D, I get all the actions for the current day and all undone things which were scheduled earlier or for which the deadline has passed, will also appear. The actions with a deadline in the coming 7 days will also show up.
The first step in getting current, is looking at the list of all next actions. For this, I have a group of custom commands. There is one for all actions, and 2 others which select only work or only home actions respectively:
Review next actions list
(setq org-agenda-custom-commands (quote ( ;; [....] ("n" . "Next Actions List") ("nn" tags "+TODO=\"NEXT\"|+TODO=\"STARTED\"") ("na" tags "+home+admin+TODO=\"NEXT\"|+home+admin+TODO=\"STARTED\"") ("nh" tags "+home+TODO=\"NEXT\"|+home+TODO=\"STARTED\"") ;; [....] )))
I can see all my next actions (with TODO state being NEXT or STARTED) by typing
C-c a n n.
Check that we have effort for all
As I said above, I want to have an effort estimate for all my next actions. I use org-ql to generate an agenda view with all next actions that don't have
Effort property. I display that with the following interactive command:
(defun my/show-next-without-effort () (interactive) (org-ql-search (org-agenda-files) '(and (todo "NEXT") (not (property "Effort")))))
Go back to previous calendar data and Review upcoming calendar
One crucial exercise in the weekly review is to have a look at the past week and the coming ones so that we see what we have done, what we should have done but didn't, and what's coming ahead.
For this, I also generate an agenda view with 24 days, starting 10 days ago. This way I see the last week and a half and the next 2 weeks. I have built the following interactive command to do that:
(defun my/generate-agenda-weekly-review () "Generate the agenda for the weekly review" (interactive) (let ((span-days 24) (offset-past-days 10)) (message "Generating agenda for %s days starting %s days ago" span-days offset-past-days) (org-agenda-list nil (- (time-to-days (date-to-time (current-time-string))) offset-past-days) span-days) (org-agenda-log-mode) (goto-char (point-min))))
Putting the agenda in log mode, allows to see the tasks marked as DONE at the corresponding time of closing. If, like me, you clock all your working time, the task will appear also every time it was worked on. This is great to get a sens of what was accomplished.
Review waiting for list
Reviewing all the actions that are blocked because they are delegated or need an input from someone else is important. Org Mode allows to generate an agenda view for that with the standard agenda dispatcher. Typing
C-c a T generates an agenda view with all tasks matching a particular TODO keyword. I enter WAITING at the prompt and that's all!
Sometimes, a project (that is, something that needs several actions to be done) gets stuck. Org Mode has a concept of stuck project (see the description of the variable
org-stuck-projects), but I found it difficult to configure to my liking. I use org-ql again to generate a custom command like this:
(setq org-agenda-custom-commands (quote ( ;; [....] ("P" "Stuck Projects" ((org-ql-block '(and (todo "PROJECT") (or (not (descendants)) (and (not (descendants (or (todo "STARTED") (todo "NEXT")))) (descendants (and (or (todo "TODO") (todo "WAITING")) (not (deadline)) (not (scheduled))))) (not (descendants (or (todo "NEXT") (todo "TODO") (todo "WAITING") (todo "STARTED"))))))))) ;; [...] )))
For me, a stuck project is a headline with a PROJECT keyword that does not have a next action, or for which the non next actions don't have a deadline or a scheduled time slot.
Look at project list
To generate the list of projects, I use the same approach as for the list of next actions.
(setq org-agenda-custom-commands (quote ( ;; [....] ("p" . "Projects List") ("pp" tags "+TODO=\"PROJECT\"") ("pw" tags "+TODO=\"PROJECT\"+work") ("ph" tags "+TODO=\"PROJECT\"+home") )))
C-c a p p gives me the list of all my projects.
Having a list of things you may want to do someday is exciting. You can add whatever you want knowing that you don't have to commit to it unless or until you feel like it. However, sometimes you forget for too long about all those things and reviewing them can give new ideas or put you in the mood to commit.
The main problem with a someday/maybe list is that it keeps growing, so you can't review it weekly. Mine contains more than 2650 items! What I do is that I randomly jump to one point in the list and review items for 5 minutes. I use the following interactive command:
(defun my/search-random-someday () "Search all agenda files for SOMEDAY and jump to a random item" (interactive) (let* ((todos '("SOMEDAY")) (searches (mapcar (lambda (x) (format "+TODO=\"%s\"" x)) todos)) (joint-search (string-join searches "|") ) (org-agenda-custom-commands '(("g" tags joint-search)))) (org-agenda nil "g") (let ((nlines (count-lines (point-min) (point-max)))) (goto-line (random nlines)))))
It seems a little convoluted, since I could have done the same thing as for the waiting for list, but with this command I can use other TODO states by adding them to the list in the first line of the
let. Also, the jump to a random point is cool.
As you can see, I have a custom set of commands and functions to make my weekly review easy. This is important. Until I automated this things, I would tend do skip the review too often. Now that I have a streamlined workflow I am much more disciplined with my weekly reviews and this results in an increased peace of mind.
My elisp code may need cleaning and improvements. Do no hesitate to send me some feedback by e-mail if you have any suggestion or tricks to share.