Skip to Content

Using org-mode for meeting minutes

Due to an unfortunate series of events, I'm back in the business of taking meeting minutes. After a meeting I want to know:

  1. what was discussed

  2. what was decided

  3. what are the next tasks and who is taking care of them

Well, I thought, there is nothing really too hard if you have org-mode in your tool chest. I searched for some prior art and found an old thread on the mailing list where this very issue is discussed. The consensus at the time was that note taking (1.) is very well covered by org-mode. The requirement to automatically extract the action items into a tabulated report (3.) was also mentioned, but no solution was presented.

So I picked up the discussion again and got some very interesting responses. This feedback made me have another look at the standard dynamic block columnview. Wouldn't it be nice if columnview had some kind of filtering capability? The manual does not mention it, but lo and behold the docstring of org-dblock-write:columnview mentions a :match argument1. That is exactly what we need, as it allows us to filter by any tag or property.

But how does that help us in getting a tabulated report of all the action items? Well, by using the :match argument of columnview we can easily extract a list of all tasks with their owner and due date. With the :format argument we can even pick appropriate column names as shown below:

* Actions
#+BEGIN: columnview :id global :match "/TODO|DONE" :format "%ITEM(What) %TAGS(Who) %DEADLINE(When) %TODO(State)"
| What                     | Who          | When            | State |
|--------------------------+--------------+-----------------+-------|
| Inventory of equipment   | :@Fred:      |                 | TODO  |
| Definition of main goals | :@Sara:      |                 | TODO  |
| Talk to companies        | :@Lucy:@Ted: | <2020-03-01 So> | DONE  |
#+END:

If we tag all the decisions with a specific tag Decision for example, then we can use the very same technique to extract a list of all decisions:

* Decisions
#+BEGIN: columnview :id global :match "Decision" :format "%ITEM(Decisions)"
| Decisions                       |
|---------------------------------|
| Last meeting notes are approved |
| A new person will be hired      |
#+END:

Assigning people to tasks

Initially I was using TODO keywords for people as outlined in the manual. However Karl Voight convinced me to drop the idea and instead simply use tags to assign a task to people. That way we can also assign more than one person to a task as you can see in the following example:

*** Discussion
**** TODO Inventory of equipment                                      :@Fred:
**** TODO Definition of main goals                                    :@Sara:
**** DONE Talk to companies                                      :@Lucy:@Ted:

Conclusion

As we have seen, org-mode can be used very well to produce meeting minutes. Take your notes as usual, mark action items as TODO items and tag them with the person that is responsible for that item. If you also want a list of all decisions, then tag the headline for the decision with a specific tag, for example Decision.

To get tabulated reports of all action items and all the decisions taken just insert two columnviews as shown above. And that's it, you have the meeting minutes including a list of what was decided and a list of the next tasks. You can then export the minutes to any format you please2 and share them with your coworkers.

Complete example

Let's have a look at a complete example of how my typical org-mode meeting minutes look like:

* Project meeting
** Present at meeting
  - [X] Peter
  - [X] Sarah
  - [X] Lucy
** Agenda
  - Comments and corrections to last meeting notes
  - Reports from the sub teams
  - Discussion
** Notes
*** Last meeting minutes are approved                              :Decision:
*** Discussion
**** TODO Inventory of equipment                                      :@Fred:
**** TODO Definition of main goals                                    :@Sara:
**** DONE Talk to companies                                      :@Lucy:@Ted:
DEADLINE: <2020-03-01 So>
**** A new person will be hired                                    :Decision:

* Actions
#+BEGIN: columnview :id global :match "/TODO|DONE" :format "%ITEM(What) %TAGS(Who) %DEADLINE(When) %TODO(State)"
| What                     | Who          | When            | State |
|--------------------------+--------------+-----------------+-------|
| Inventory of equipment   | :@Fred:      |                 | TODO  |
| Definition of main goals | :@Sara:      |                 | TODO  |
| Talk to companies        | :@Lucy:@Ted: | <2020-03-01 So> | DONE  |
#+END:

* Decisions
#+BEGIN: columnview :id global :match "Decision" :format "%ITEM(Decisions)"
| Decisions                         |
|-----------------------------------|
| Last meeting minutes are approved |
| A new person will be hired        |
#+END:

Footnotes


1

Is something an undocumented feature if it is mentioned only in a doc string but not in the manual? The discoverability in this case is very low as the function name is not immediately clear from the name of the dynamic block (org-dblock-write:columnview vs columnview). I would argue the manual should contain something about this.

2

as long as it is one of the formats supported by the org-mode exporter or pandoc.