5.3.2 Tracking TODO state changes
You might want to automatically keep track of when a state change occurred and maybe take a note about this change. You can either record just a timestamp, or a time-stamped note. These records are inserted after the headline as an itemized list, newest first1. When taking a lot of notes, you might want to get the notes out of the way into a drawer (see Drawers). Customize the variable org-log-into-drawer
to get this behavior—the recommended drawer for this is called ‘LOGBOOK
’2. You can also overrule the setting of this variable for a subtree by setting a ‘LOG_INTO_DRAWER
’ property.
Since it is normally too much to record a note for every state, Org mode expects configuration on a per-keyword basis for this. This is achieved by adding special markers ‘!
’ (for a timestamp) or ‘@
’ (for a note with timestamp) in parentheses after each keyword. For example, with the setting
(setq org-todo-keywords
'((sequence "TODO(t)" "WAIT(w@/!)" "|" "DONE(d!)" "CANCELED(c@)")))
To record a timestamp without a note for TODO keywords configured with ‘@
’, just type C-c C-c
to enter a blank note when prompted.
You not only define global TODO keywords and fast access keys, but also request that a time is recorded when the entry is set to ‘DONE
’, and that a note is recorded when switching to ‘WAIT
’ or ‘CANCELED
’3. The setting for ‘WAIT
’ is even more special: the ‘!
’ after the slash means that in addition to the note taken when entering the state, a timestamp should be recorded when leaving the ‘WAIT
’ state, if and only if the target state does not configure logging for entering it. So it has no effect when switching from ‘WAIT
’ to ‘DONE
’, because ‘DONE
’ is configured to record a timestamp only. But when switching from ‘WAIT
’ back to ‘TODO
’, the ‘/!
’ in the ‘WAIT
’ setting now triggers a timestamp even though ‘TODO
’ has no logging configured.
You can use the exact same syntax for setting logging preferences local to a buffer:
#+TODO: TODO(t) WAIT(w@/!) | DONE(d!) CANCELED(c@)
In order to define logging settings that are local to a subtree or a single item, define a ‘LOGGING
’ property in this entry. Any non-empty ‘LOGGING
’ property resets all logging settings to nil
. You may then turn on logging for this specific tree using ‘STARTUP
’ keywords like ‘lognotedone
’ or ‘logrepeat
’, as well as adding state specific settings like ‘TODO(!)
’. For example:
* TODO Log each state with only a time
:PROPERTIES:
:LOGGING: TODO(!) WAIT(!) DONE(!) CANCELED(!)
:END:
* TODO Only log when switching to WAIT, and when repeating
:PROPERTIES:
:LOGGING: WAIT(@) logrepeat
:END:
* TODO No logging at all
:PROPERTIES:
:LOGGING: nil
:END:
- See the variable
org-log-states-order-reversed
.↩ - Note that the ‘
LOGBOOK
’ drawer is unfolded when pressingSPC
in the agenda to show an entry—useC-u SPC
to keep it folded here.↩ - It is possible that Org mode records two timestamps when you are using both
org-log-done
and state change logging. However, it never prompts for two notes: if you have configured both, the state change recording note takes precedence and cancel the closing note.↩