Can I reuse the capture buffer when I make a new capture

Sometimes I start a capture to a pre-existing note, write some work into it, then go away and look at something else (like a pdf which I’m taking notes on) without closing the buffer. If I then capture again to the same note, a new capture buffer is opened. This clutters my buffer list and means that unused capture buffers hang around after I’ve finished writing (and closed whichever one I’m in at the time).

Is there a way to reuse the capture buffer for a note which already has an open capture buffer, when capturing to it again (i.e. just open that buffer, rathet than creating a new one and opening it)?


I don’t find it easy to get the program to determine if you are really opening a capture for the same notes buffer that a capture is already open for – you could have multiple capture buffers open for many notes, for example. How can a program tell which one I am capturing for?

But the following crude way might work for you. Tested OK on my end.

Note that it will automatically finalize (C-c C-c) any capture buffer open, so you might not like it. But you can ensure that there will always be only one capture open (if you only use this command).

(defun my/org-roam-capture (&optional GOTO KEYS &key FILTER-FN TEMPLATES INFO)
  "Finalize any open capture buffer then call `org-roam-capture'."
    (let* ((case-fold-search nil) ; Make `string-match' below look for
                                  ; CAPTURE and not capture
            (seq-find (lambda (b)
                        (string-match-p  "^CAPTURE*." (buffer-name b)))
      (when capture-buffer
        (pop-to-buffer capture-buffer)

I worked out a way to do this in exactly the way I wanted. I do it by keeping track of the capture buffers in a variable and advising org-roam-capture-. Code:

(defvar my/org-roam-capture-buffers nil
  "Alist of roam node ids and buffers.")
(defun my/org-roam-remove-buffer-capture-list ()
  "Remove current buffer from `my/org-roam-capture-buffers'."
  (setf (alist-get (org-roam-capture--get :id)
		   nil 'remove)
(defun my/org-roam-push-buffer-capture-list ()
  "Push current buffer to `my/org-roam-capture-buffers'.

Car is id of current capture org roam buffer. Cdr is the capture

When not in an org-roam capture buffer, return nil."
  (when (org-roam-capture-p)
    (setf (alist-get (org-roam-capture--get :id) my/org-roam-capture-buffers)
	  (marker-buffer (plist-get org-capture-plist :begin-marker)))))
(defun my/org-roam-capture--switch-advice (&rest keys)
  "If NODE has a capture buffer, switch to it.

Otherwise, capture to it directly."
  (if-let ((node (plist-get keys :node))
	   (id (org-roam-node-id node))
	   (buffer (alist-get
		    id my/org-roam-capture-buffers
		    nil nil #'string=))
	   (_ (buffer-live-p buffer)))
      (org-switch-to-buffer-other-window buffer)))

Then add my/org-roam-push-buffer-capture-list to org-capture-mode-hook and advise org-roam-capture- with my/org-roam-capture--switch-advice, using :before-until as the HOW.

Hope this is useful for someone!