How I’m managing my life with emacs org-mode (by alaric)
It's no secret that I'm a busy person; often, when I decide to do something, a few years pass before I actually get to do it. So the only way I keep afloat is by the judicious use of computers to track my task lists. I rely on automatic systems to make sure I always know what I need to do today, and what are the most important things I need to do "sometime" that I can do right now. There's no way I could keep all that in my head without forgetting about things and letting people down, or feeling stressed because I'm juggling too much in my mind, or not being able to find the best thing to do when I have a free moment.
As I've mentioned before on here, I want a personal information management system based on predicate logic, so I can express complex relationships between things easily, and tell the system how to infer knowledge automatically. However, "build one of those" has yet to hit the top of my TODO list, so for now I'm using emacs' legendary org-mode. This lacks the rich semantic power of my proposed PIM, but it's already implemented and has a nice editing interface 🙂
A few people have asked about what I've done, so here's my attempt to document it.
Principles
Here's the idea. I have a bunch of things I need to do. Some need doing at a specific point in time, either as a one-off or as a regular thing, such as taking Jean to Ju Jutsu. Some just need doing whenever I can; of those, some can't be done until a particular date (I'm waiting for warmer weather before I wash and repaint my workshop's interior, for example), and some have a deadline.
A lot of my tasks (but not all) are part of larger, organised, projects; but projects can have sub-projects, and groups of projects can go together, so in general, my tasks can be shoved into a tree structure to stop them being a formless see of scary obligation. Nonetheless, there is a list of projects, and tasks may be under a project or may be roaming free.
Every day, I want to see a list of things I need to do on that day, because they're scheduled for that day (either as a whole, or for a specific time slot on that day). That's the stuff I've committed to doing at particular regions of time, but between those regions, I get to choose what to do. And so next I need to see a list of TODOs for current projects.
Many of my tasks are idea for things I want to do, but there's no pressing urgency to do them any time soon. I want to track these, but I don't want to be overwhelmed by them on a daily basis. So many of my projects are "future projects", that don't need to appear in my daily list of things to do. I have a number of "background projects" that are always there - maintaining stuff like the car and the house and so on, usually as a container of regular scheduled things such as "take the recycling out", but often with TODOs added from time to time as well ("Replace headlight bulb"). And I have "current projects" that I'm working on.
Now, a current project might have a lot of TODOs, but only a few of them are really applicable as "things to do"; many of them depend on earlier tasks. So only a subset of my TODOs are "active"; the things that I can actually do now out of current or background projects, and ad-hoc TODOs that aren't part of a project.
So, my "daily report" needs to contain a list of things scheduled today (and I like to see the next few days, so I have a feel for what's coming up), and then a list of active TODOs. This shouldn't be a long list, because if I have too many things to choose from, I'll be spending too long on the choosing and not enough on the doing!
To make the choosing easier, I mark TODOs with a "context", indicating where I can do them. Mine are @HOME for things I need to be in the house for, @COMPUTER for things I just need to be at a computer for, @BUY for things to buy (when I have spare money), @TRIP for things I need to make a trip outdoors for (buying things I can't buy online, for instance, or visiting people), and @MEETING for stuff I can only do at a meeting (I have meetings with my Scout group leadership, and the Cheltenham Hackspace committee).
So my daily report needs to list active TODOs grouped by context, so I can just skim the list for the context(s) I'm in.
However, some TODOs are urgent, and override the context system; I need to make sure I create the context for them if it doesn't arise normally! So we list all the urgent TODOs first, then the TODOs grouped by context.
Finally, some TODOs are paused because I'm waiting for somebody or something else to finish. Rather than having them lingering in the active TODOs list and having to be skipped because I can't do them, while still keeping them visible so I notice if I've been waiting a long time for a response, I mark them as "stalled" and list them at the bottom of my daily report.
So, to conclude, the daily report lists:
- Today's scheduled things.
- Upcoming scheduled things/deadlines.
- Urgent TODOs.
- Active TODOs by context.
- Active TODOs that don't have a context assigned (either because I forgot, or because they really occupy an "other" context).
- Stalled TODOs.
This report is meant to be as compact as possible - listing things I must do today, then things I could do today. If I do some work on a TODO from a project, then I'll either leave it as a TODO if there's more work to do (I don't bother with an "in progress" flag; if there's still work to be done, it's still a TODO), or mark it as DONE if I'm done, or mark it as STALLED if I'm waiting for somebody else. If it becomes DONE or STALLED, then if there's other non-active TODOs in that project that can now become active, I'll mark them as active to ensure that the project can still progress.
Sometimes I need to make new projects, or delete finished ones, too. But when I have new information, or new things to do, coming into my system, I may not have time to correctly file them under projects and all that, so I also have a "holding area" for new stuff. This automatically classes as URGENT, because even if it's not an urgent task, filing it correctly is and will only take a few seconds when I get a chance later on. These things aren't necessarily TODOs; they might be information pertaining to a project, or useful reference information such as a useful link, or something like that. Either way, in the holding area, it counts as an urgent task to file it appropriately.
Now, this is a very focussed view, intended to mean I can quickly pick from a list of things I can actually do without needing to skip over lots of stuff that's not relevant when I'm looking for something to fill a five-minute gap in my day. This means it doesn't really take account any of my long-term goals, or allow for future projects to become current, or for me to sit back and have some perspective. So I also have a weekly report, which aims to do that. This shows a list of all my projects (with all the TODOs for each project listed for each), then all the background projects (likewise, with all TODOs) and then all the future projects (but there's no need to list the TODOs for these; I just want to be reminded of their existence, not going into their structure). And then, finally, I want to be reminded of a list of my current goals: not specific projects with TODOs, but more general directions in life.
The idea is that periodically (ideally once a week) I'll look over this list and do a bit of "pruning and tidying" of my overall TODO database - perhaps making some TODOs active that are now relevant, to make sure that each project can make some progress. And to remind myself of my goals and future projects.
And that's that - that's how I currently manage my life. But how have I built this in org-mode?
Implementation
This won't make very much sense until you've learnt the basics of org-mode. Read the org-mode guide if you don't feel you're there yet!
So, I have three org-mode files of importance. They are tasks.org
, schedule.org
and urgent.org
.
tasks.org
tasks.org
, despite the name, really is a database of my entire life. It has sections for things like each insurance I hold, with the policy numbers, a summary of the cover, and the numbers to ring for claims (and perhaps a scheduled TODO to renew it), sections for all the people in my life with phone numbers and postal addresses (and scheduled items for their birthdays), as well as the usual lists of projects and TODOs you'd expect. It also has a section for goals, which are headings marked with a :GOAL:
tag.
Projects are defined by headings with the tags :PROJECT:
for active projects, :BACKGROUNDPROJECT:
for background projects, and :FUTUREPROJECT:
for future projects. However, I freely use un-tagged headings to group projects, and to make structure within projects. I have those tags (and :GOAL:
) excluded from inheritance with org-tags-exclude-from-inheritance
; something being in a project doesn't make it into a project in its own right. I use C-c C-q
to pick tags for headings.
There's three kinds of dates that I use in org-mode.
Things like "Take out the rubbish on a Monday" or "Go and visit the Jones's on Sunday the 4th of October at 3pm" are implemented with headings that don't have a TODO marker, but have a timestamp in angle brackets, like so:
** <2013-01-21 Mon +1w> Take out the rubbish
** <2015-10-04 Sun 15:00> Visit the Jones's
Any extra information about the task (the Jones's address, for instance) go under that heading. That arrangement makes the heading appear in the daily calendar view, at the given date (and time, if applicable). I use C-c .
to enter the timestamps; in the calendar popup that appears, I can use shift with the arrow keys to move around by day or week (try it and see).
Most of my periodic things pertain to a background project, so are filed in tasks.org
under that project. Birthdays and anniversaries are filed under people's headings, too. One-off things like visiting people would tend to clutter my tasks.org
file up, so they go into schedule.org
, but I'll explain how that works in a moment.
The other two kinds go on TODOs, and often go together. If I have to renew my SSL certificate before the 11th of January 2016, I might write it like so:
*** TODO Renew SSL certificate DEADLINE: <2015-12-11 Bar> SCHEDULED: <2016-01-11 Foo>
This means that the TODO will appear on today's entry in the calender from the 11th of December onwards (until I mark it DONE), and the deadline on the 11th of January will also come up on that day (in red).
I use C-c C-s
to set a scheduled date, and C-c C-d
to set a deadline date.
Any task that isn't stuck to a specific day (or time region within that day) goes in as a TODO. I have three states configured - TODO
, STALLED
and DONE
. Most TODOs are not given a priority, but "active" TODOs are given either [#A]
or [#B]
to mark them as active; [#A]
is for things I want to push up the lists a bit, as they're important.
I use shift and the arrow keys to manage TODOs; shift plus left and right moves between TODO states, while shift plus up and down moves between priorities (and the "no priority" state for non-active tasks).
My contexts are, of course, tags I apply to TODOs, but I can also apply them to headings that group TODOs to make them apply to all the TODOs within, as they're not excluded from org tags inheritance. I can also tag things with :URGENT:
to make them urgent, and I tag some projects with :FOSSIL:
to note that they have an associated fossil repository (and then specify the path to it in the project description).
The top of tasks.org
has these headings:
#+TAGS: @HOME(h) @COMPUTER(c) @BUY(b) @TRIP(t) @MEETING(m) #+TAGS: { PROJECT(p) FUTUREPROJECT(P) BACKGROUNDPROJECT(B) } #+TAGS: FOSSIL(f) GOAL(g) URGENT(u) #+ARCHIVE: done.org_archive:: #+CATEGORY: tasks
That sets up my tags, makes org-archive put archived things into done.org_archive
, and categorises everything in here as coming from tasks.org
; I can't remember what that affects! I use C-c C-x C-a
to archive a subtree I've "done", pushing it into done.org_archive
for the record.
schedule.org
This is where I keep my schedule of things that pertain to particular dates; repeating things tend to live in tasks.org
. I also use it like a diary, creating historical entries for notable things that happened on particular days so I see them if I go back in the org calendar.
I have an org capture thingy set up to create scheduled items, which uses the file+datetree+prompt
capture type, to keep the file organised by date. More on that later.
The heading of schedule.org
reads:
#+ARCHIVE: done.org_archive:: #+FILETAGS: SCHEDULE #+CATEGORY: tasks
That makes it archive to done.org_archive
, just like tasks.org
does, and gives everything the same category - schedule.org
really just exists to offload one-off things from tasks.org
to keep it slim. However, I make sure that everything that comes from here gets an automatic :SCHEDULE:
tag so I know.
urgent.org
This is my INBOX of as-yet-unfiled things. I have an org capture thingy set up to put things in here, which we'll look at next.
I use refile (C-c C-w
) to move things from here to tasks.org
most of the time.
It has a heading like so:
#+FILETAGS: URGENT #+ARCHIVE: done.org_archive:: #+CATEGORY: urgent
Everything in here is automatically tagged :URGENT:
, and categorised as such; and anything archived goes to the usual place.
Org Capture
Org Capture is a thing to create new org-mode headings. You give it a list of templates, and then you can press C-c c x
to use the template you've called x
.
Mine are:
t
to create a task inurgent.org
.r
to create a task with a reference to where I am (filename and line, say) inurgent.org
l
to create a log entry (it puts it inschedule.org
with today's date)p
to create a log entry, but prompting me for the date.s
to create a schedule entry inschedule.org
, prompting me for the date/time.
Org Agenda
I use org's agenda facility to make my daily and weekly reports. Neither are exactly how I want them, but that's the price of using something off-the-shelf, and motivates me to sort out my proper PIM one day!
I have two custom block agendas configured. They look like this in my .emacs
:
(org-agenda-custom-commands (quote (("r" "Daily Review" ((agenda "" nil) (tags-todo "URGENT" nil) (tags-todo "+TODO=\"TODO\"+PRIORITY<>\"\"+@HOME" nil) (tags-todo "+TODO=\"TODO\"+PRIORITY<>\"\"+@COMPUTER" nil) (tags-todo "+TODO=\"TODO\"+PRIORITY<>\"\"+@BUY" nil) (tags-todo "+TODO=\"TODO\"+PRIORITY<>\"\"+@TRIP" nil) (tags-todo "+TODO=\"TODO\"+PRIORITY<>\"\"+@MEETING" nil) (tags-todo "+TODO=\"TODO\"+PRIORITY<>\"\"-@HOME-@COMPUTER-@BUY-@TRIP-@MEETING-URGENT" nil) (tags-todo "TODO=\"STALLED\"" nil)) nil ("~/tmp/daily-agenda.html")) ("w" "Weekly Review" ((tags "PROJECT" nil) (tags "BACKGROUNDPROJECT" nil) (tags "FUTUREPROJECT" nil) (tags "GOAL" nil)) ((org-tags-exclude-from-inheritance (quote ("PROJECT" "FUTUREPROJECT" "BACKGROUNDPROJECT" "GOAL")))) ("~/tmp/weekly-agenda.html")))))
Basically, the daily report shows a seven-day agenda view starting with today, then all my urgent todos, then TODOs with a priority (which marks them as "active") and each different context tag, then TODOs with a priority and none of the context tags, then STALLEDs.
This isn't perfect. Scheduled TODOs appear in the agenda as "things to do today"; I'd rather they appeared in the urgent/context sections like all other TODOs. I need to list all my contexts, and get big ugly headings for contexts with no TODOs in, rather than it just seeing what contexts are currently available and listing only those. Scheduled tasks with a priority appear in the todo section before their scheduled dates, so I need to not set priorities on scheduled tasks. But it suffices.
The weekly review is a lot cruder; it just lists current, then background, then future projects, then my goals. I'd like to list all the TODOs under each current or background project, then a list of TODOs that aren't in a project but I don't know how to do that. I'm saving that for my predicate-logic version!
Now, you'll notice that both have an html filename specified. The following shell script:
#!/bin/sh rm ~/tmp/daily-agenda.html ~/tmp/weekly-agenda.html DISPLAY="" emacs -eval '(org-store-agenda-views)' -kill scp ~/tmp/*-agenda.html love.warhead.org.uk:public_html/private
...tells emacs to generate those HTML files, and then uploads them to my Web server, into a password-protected directory. The daily schedule view is my browser homepage on all my devices (including my Android tablet), so it's in front of me when I'm not in front of emacs (where it can be had by typing C-c a r
).
Currently I run that from a script that syncs my org-mode files with the Fossil repo; when I have a working desktop computer, always-on, I plan to run that from cron so it's kept up to date each hour, as the marker for "now" in the daily calendar thing is often out of date on the online version!
.emacs
Here's the relevant bits of my .emacs
file:
(require 'org-install) (add-to-list 'auto-mode-alist '("\\.org$" . org-mode)) (define-key global-map "\C-cl" 'org-store-link) (define-key global-map "\C-ca" 'org-agenda) (define-key global-map "\C-cc" 'org-capture) (setq org-log-done nil) (setq org-log-into-drawer t) (setq org-todo-keywords '((sequence "TODO(t)" "|" "STALLED(s)" "DONE(d)"))) (setq org-reverse-note-order t) (setq org-refile-use-outline-path 'file) (setq org-refile-allow-creating-parent-nodes 'confirm) (setq org-refile-targets '(("~/alaric/var/todo/tasks.org" . (:maxlevel . 10)) ("~/alaric/var/todo/urgent.org" . (:maxlevel . 2)) ("~/alaric/var/todo/schedule.org" . (:maxlevel . 2)))) (setq org-blank-before-new-entry nil) (setq org-directory "~/alaric/var/todo") (custom-set-variables ;; custom-set-variables was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(org-agenda-custom-commands (quote (("r" "Daily Review" ((agenda "" nil) (tags-todo "URGENT" nil) (tags-todo "+TODO=\"TODO\"+PRIORITY<>\"\"+@HOME" nil) (tags-todo "+TODO=\"TODO\"+PRIORITY<>\"\"+@COMPUTER" nil) (tags-todo "+TODO=\"TODO\"+PRIORITY<>\"\"+@BUY" nil) (tags-todo "+TODO=\"TODO\"+PRIORITY<>\"\"+@TRIP" nil) (tags-todo "+TODO=\"TODO\"+PRIORITY<>\"\"+@MEETING" nil) (tags-todo "+TODO=\"TODO\"+PRIORITY<>\"\"-@HOME-@COMPUTER-@BUY-@TRIP-@MEETING-URGENT" nil) (tags-todo "TODO=\"STALLED\"" nil)) nil ("~/tmp/daily-agenda.html")) ("w" "Weekly Review" ((tags "PROJECT" nil) (tags "BACKGROUNDPROJECT" nil) (tags "FUTUREPROJECT" nil) (tags "GOAL" nil)) ((org-tags-exclude-from-inheritance (quote ("PROJECT" "FUTUREPROJECT" "BACKGROUNDPROJECT" "GOAL")))) ("~/tmp/weekly-agenda.html"))))) '(org-agenda-files (quote ("~/alaric/var/todo/schedule.org" "/home/alaric/alaric/var/todo/tasks.org" "/home/alaric/alaric/var/todo/urgent.org"))) '(org-agenda-ndays 7) '(org-agenda-show-all-dates t) '(org-agenda-skip-deadline-if-done t) '(org-agenda-skip-scheduled-if-done t) '(org-agenda-sorting-strategy (quote ((agenda habit-down time-up priority-down category-keep) (todo category-down priority-down) (tags priority-down category-keep) (search category-keep)))) '(org-agenda-start-on-weekday nil) '(org-capture-templates (quote (("t" "Task" entry (file "~/alaric/var/todo/urgent.org") "* TODO %^{Task} CREATED: %U %?") ("r" "Referenced Task" entry (file "~/alaric/var/todo/urgent.org") "* TODO %^{Task} CREATED: %U %? %a") ("l" "Log entry" entry (file+datetree "~/alaric/var/todo/schedule.org") "* %^{Summary} %?") ("p" "Post/Predated log entry" entry (file+datetree+prompt "~/alaric/var/todo/schedule.org") "* %^{Summary} %?") ("s" "Schedule entry" entry (file+datetree+prompt "~/alaric/var/todo/schedule.org") "* %^T %?")))) '(org-default-notes-file "~/alaric/var/todo/urgent.org") '(org-reverse-note-order t) '(org-tags-column -100) '(org-tags-exclude-from-inheritance (quote ("GOAL" "FUTUREPROJECT" "PROJECT" "BACKGROUNDPROJECT"))) ) (defun abs/visit-tasks () "Open my tasks.org file" (interactive) (find-file "~/alaric/var/todo/tasks.org")) (defun abs/visit-urgent () "Open my urgent.org file" (interactive) (find-file "~/alaric/var/todo/urgent.org")) (defun abs/visit-schedule () "Open my schedule.org file" (interactive) (find-file "~/alaric/var/todo/schedule.org")) (global-set-key [f12 ?t] 'abs/visit-tasks) (global-set-key [f12 ?u] 'abs/visit-urgent) (global-set-key [f12 ?l] 'abs/visit-schedule) (load "htmlize")
What next?
I still want to migrate to something based on predicate logic, but I can do it in stages, basing it on top of my org-mode setup.
What I'd like to do is to write an org-mode parser, which reads my org-mode files and converts them into predicates. Each heading would become some kind of object, depending on its tags and the presence of TODO markers and timestamps, and the tree structure would be represented by having child
relationships between them. Thus, all my org-mode data would automatically be visible in the predicate logic world.
However, I'd also parse special markers from within the bodies of headings to generate arbitrary predicates, written in native predicate syntax. That way I can turn my "person" headings into richer person objects in predicate-world, with their contact details marked as such rather than just body text, and their birthdate marked as such rather than just a random scheduled item within that person heading.
Given that, I'd be able to make much better daily and weekly reports, as well as providing easy programmatic access to address book information and the like. The downside of a report generated outside of emacs is that I can't then use the agenda commands to jump straight to the headings in my input files, or use C-c C-w
to refile straight from the agenda, and so on - but perhaps I can fix that by generating a .org
file for the reports with appropriate links, or something.
I'd also be able to fill a hole in the current system; I use the ticket trackers in fossil repos for projects I share with others, such as my open-source things on Kitten Technologies or the fossil repo that runs our home wiki (and the domestic TODO list I share with my wife). Those TODOs don't appear in my system, unless I manually make a proxy TODO in tasks.org
pointing at them. A predicate logic system, however, can spot my :FOSSIL:
projects and follow the link to the fossil repo and pull out the tickets, and also create task objects from them, thus integrating them automatically.
A predicate logic system can take its input predicates from any source I've written a converter for, so existing org-mode files, org-mode files with extra predicate data, online knowledge stores, and all sorts of data sources can be seamlessly integrated. If it becomes worth doing, I can migrate all of my org-mode files into an online knowledge store, losing emacs' snazzy org-mode editing features in the process (but gaining the ability to easily modify it from my own software). Or I can write something to take a predicate-logic knowledge base and generate an org-mode file from it by finding the child
relationships and pulling out a hierarchy of headings, and thus write scripts that pull in org-mode files, do something, and spit them back out again. One day!
And one other day, I'd really like all of this to migrate to a wrist-mounted computer, so I can access it all and add new information on the go. With a link to synch it to my big computers when possible, and perhaps containing a little USB mass storage thing so I can plug it into any old PC to make it boot into a workstation environment with my personal information synced from the attached wrist device in real time...
By John Cowan, Wed 21st Jan 2015 @ 3:39 am
Anacron might be your friend.
By andyjpb, Sun 1st Feb 2015 @ 9:13 pm
Can you write a fossil ticket -> org mode converter?