emacs · org-roam

Task management with org-roam Vol. 6: Select a person and view related tasks

Building a utility function to select a person and view all related tasks in org-agenda, supporting aliases whilst leveraging vulpea's selection capabilities and org-mode's tag matching.

In previous articles - Vol. 3 to be precise - we discussed automatic setup of filetags, so each task in a note related to a person is automatically tagged thanks to tag inheritance. Then, in Vol. 4, we covered automatic tagging of tasks whenever a person is mentioned in either the title or the body of a task. This makes org-agenda's matching capabilities particularly useful when we want to see all tasks related to a specific person.

In this article, we're going to write a small utility function that asks the user to select a person and then presents an org-agenda buffer with tasks related to the selected person.

The introduction is actually longer than the implementation!

#2Change Log

  • [2025-11]: This series was written for vulpea v1 with org-roam. See Vulpea v2: breaking up with org-roam for context on vulpea v2, which no longer depends on org-roam. Updated guides are coming.
  • [2021-03-02]: Updated naming convention to match personal configurations.
  • [2021-05-10]: Updated post to reflect changes in org-roam v2. Previous version of this article is available on GitHub.
  • [2022-07-11]: Adapted code to changes in Org mode and new functions in vulpea. The combination of vulpea-select-from and vulpea-db-query-by-tags-some works faster than generic vulpea-select.

Related posts

Here's the function you can bind or call by name using M-x:

(defun vulpea-agenda-person () "Show main `org-agenda' view." (interactive) (let* ((person (vulpea-select-from "Person" (vulpea-db-query-by-tags-some '("people")))) (node (org-roam-node-from-id (vulpea-note-id person))) (names (cons (org-roam-node-title node) (org-roam-node-aliases node))) (tags (seq-map #'vulpea--title-to-tag names)) (query (string-join tags "|"))) (let ((org-agenda-overriding-arguments (list t query))) (org-agenda nil "M"))))

Here are some explanations:

  1. This code uses the vulpea library1 to select a person. You can achieve the same result without vulpea, of course, but this saves some effort. vulpea-select-from asks the user to select a note from a list of notes returned by vulpea-db-query-by-tags-some. In this case, we simply present only people notes. The same result can be achieved by using vulpea-select, which takes a predicate, but vulpea-db-query-by-tags-some works faster. See the Performance section of vulpea documentation.
  2. Once we have a selected vulpea-note, we can get all titles for that file (e.g. main title and aliases). This is important for alias users. For example, in some notes I want to use Mr. Frodo instead of Frodo Baggins, but I want to see tasks tagged as @Mr.Frodo and @FrodoBaggins at the same time. It's the same person after all (don't ask me about Gollum - better use M-x doctor)!
  3. We then convert those names into tags using vulpea--title-to-tag from Vol. 4.
  4. Next, we join the tags using the | separator into a single query string.
  5. The final step is to execute org-agenda with the M argument (match for tags, but list only TODO items). To pass a query to the relevant agenda function, we use org-agenda-overriding-arguments. I'm not sure if it's documented anywhere, but you can read the sources of org-agenda to work out how to use it. dlet is used here for dynamic binding. If you're not using lexical scope, you can use regular let instead.

That's it! Now see it in action again.

#1References


#2Footnotes

  1. Yikes, I advertise my own libraries on this blog!