How to best follow up on todo in notes

I am using org roam to write all of my research notes.
Often I have a note, which part of it is an idea or a question.
I tend to mark these in a section with a TODO tag, or IDEA tag, etc.
The question is: What would be the best practice in displaying say all “TODO” sections that I have in my org roam directory?

I saw this post, but I was not sure if this implements what I am looking for, and even if so if this is a good way of doing that.

I’m the author of the linked post in one of the comments. I continue to use that setup and it’s working well for me so far.

What have you tried?
What’s lacking from what you’ve tried?

Actually, I still did not really try something special for that.
Currently, I am using deft to find free text in notes, but since moving to org-roam v2, it doesn’t work so well.

I thought that marking sections or subsections with TODO, IDEA, etc., would make it easy to integrate with org-agenda later. But the problem is that I do not use org-agenda, so I’d have to learn that fast.
I recall that I read somewhere that org-agenda does not work so well when there are many files, so I think this is not the way to go.

I just saw this post about consult-ripgrep, and I am wondering if this is a good way. Though, I still did not figure out how to use consult-ripgrep.

What I want is to be able to see all notes in which I have an IDEA, or a TODO, or some other keyword, and be able to preview these notes easily.

something like org-ql may be able to help do what your after.

1 Like

Thanks! I will try that and update here with the results.

The performance issue isn’t so bad, really. I have an optimization that I use in mine which only adds files which have TODO entries to the agenda list.

My Emacs Configuration - Search in this page for “vulpea” which shows the relevant section.

Adding the text here for ease:

;; vulpea stuff from https://d12frosted.io/posts/2021-01-16-task-management-with-roam-vol5.html
(use-package vulpea
  :after org-roam
  ;; hook into org-roam-db-autosync-mode you wish to enable
  ;; persistence of meta values (see respective section in README to
  ;; find out what meta means)
  :hook ((org-roam-db-autosync-mode . vulpea-db-autosync-enable)))

(defun vulpea-project-p ()
  "Return non-nil if current buffer has any todo entry.

TODO entries marked as done are ignored, meaning the this
function returns nil if current buffer contains only completed
tasks."
  (seq-find                             ; (3)
   (lambda (type)
     (eq type 'todo))
   (org-element-map                         ; (2)
       (org-element-parse-buffer 'headline) ; (1)
       'headline
     (lambda (h)
       (org-element-property :todo-type h)))))

(defun vulpea-project-update-tag ()
    "Update PROJECT tag in the current buffer."
    (when (and (not (active-minibuffer-window))
               (vulpea-buffer-p))
      (save-excursion
        (goto-char (point-min))
        (let* ((tags (vulpea-buffer-tags-get))
               (original-tags tags))
          (if (vulpea-project-p)
              (setq tags (cons "project" tags))
            (setq tags (remove "project" tags)))

          ;; cleanup duplicates
          (setq tags (seq-uniq tags))

          ;; update tags if changed
          (when (or (seq-difference tags original-tags)
                    (seq-difference original-tags tags))
            (apply #'vulpea-buffer-tags-set tags))))))

(defun vulpea-buffer-p ()
  "Return non-nil if the currently visited buffer is a note."
  (and buffer-file-name
       (string-prefix-p
        (expand-file-name (file-name-as-directory org-roam-directory))
        (file-name-directory buffer-file-name))))

(defun vulpea-project-files ()
    "Return a list of note files containing 'project' tag." ;
    (seq-uniq
     (seq-map
      #'car
      (org-roam-db-query
       [:select [nodes:file]
        :from tags
        :left-join nodes
        :on (= tags:node-id nodes:id)
        :where (like tag (quote "%\"project\"%"))]))))

(defun vulpea-agenda-files-update (&rest _)
  "Update the value of `org-agenda-files'."
  ;;; Not yet fully on org-roam, so also include things in the top level directory
  (setq org-agenda-files (append
                          (remove-if
                           (lambda (x)
                             (string-match (regexp-quote ".#") x))
                           (directory-files org-directory t "org$"))
                          (vulpea-project-files))))

(require 'vulpea)
(add-hook 'find-file-hook #'vulpea-project-update-tag)
(add-hook 'before-save-hook #'vulpea-project-update-tag)

(advice-add 'org-agenda :before #'vulpea-agenda-files-update)
1 Like

I just have regular Org-roam nodes called TODO, IDEA etc., and I link to them from other nodes as appropriate. When I want a list of all my TODOs, I just open the TODO node and take a look at the backlinks. It’s nothing fancy, but it has the advantage of being quite performant, since it leans on the node indexing that Org-roam does anyway, precisely for performance reasons.

1 Like

What I personally do is display the TODO state of an item in the org-roam-node-find UI. This way I always know if a recent file has such a state. I define a cl-defmethod for this. Note that this isn’t necessary, but I dislike the format the existing defmethod uses, so I made my own variation.

(cl-defmethod org-roam-node-todostate ((node org-roam-node))
    "Modified version of org-roam-node-todo to look a bit better"
    (if-let ((state (org-roam-node-todo node)))
	    (format "Status: %s" state)))

Then you just add this to org-roam-node-display-template like this
(setq org-roam-node-display-template "${title:100} ${backlinkscount:6} ${todostate:20} ${directories:10} ${tags:25}")

Finally, I have a function which runs org-roam-node-find with a filter to only show items which have a todo state. This is rather easy to make

(defun org-roam-node-find-todos ()
  "Filtered view of org-roam-node-find which displays only nodes
with a todo state. All my fleeting notes typically have a todo
state indicating I need to work on them so this filter helps me
out"
  (interactive)
  (org-roam-node-find nil nil #'org-roam-node-todo))

This works well for me

Thanks very much for your tip.
The only thing is that I would like to find also section-items that are not org-roam-nodes
So I guess this method does not help me with that.

I have a question about your config.
You wrote that this method

(cl-defmethod org-roam-node-todostate ((node org-roam-node))
    "Modified version of org-roam-node-todo to look a bit better"
    (if-let ((state (org-roam-node-todo node)))
	    (format "Status: %s" state)))

is not really needed.
However, without it, the org-roam-node-find cannot recognize todostate. Why is that?

Thanks for the config!
I still did not catch on how to use agenda. I thought it might be one solution, but I need to understand it first.

The one org-roam has by default is org-roam-node-todo. So instead of todostate you need to put todo. But I personally disliked how it printed that.

Yeah, for non node items, I can’t say I have a solution. I just make fleeting notes exclusively in the org-roam directory so they always show up if they get a todo state.

Edit: Just saw your second message on agenda. I personally dont use it as I do all my “querying” through the org-roam completion UIs or org-ql if that is necessary

1 Like

There isn’t anything roam specific about agenda. It’s just the normal org mode thing. The snippet I shared just ensures that the variable the org agenda looks at to determine which files to scan is kept up to date.

1 Like