I am beginning to use org-mode as an electronic lab notebook, which is working very well. I work on a number of different projects, each of which has its own directory. When I use org-capture, I want the task, etc., to be written to an .org file in the directory for the current project.

So if I am working in my org lab notebook for Project A and I capture a task, I want that task to go to the capture.org file in the directory for Project A, but when I capture a task from my notebook for Project B, I want the task written to capture.org in that directory instead.

It seems like I could do this with different templates, using something along these lines.

(setq org-capture-templates
'(("t" "Todo" entry (file "~/project_a/capture.org")...)
  ("u" "Todo" entry (file "~/project_b/capture.org")...)
  ("v" "Todo" entry (file "~/project_c/capture.org")...)))

The downside of this is that I have to remember or check a lot of different templates each time, making it more distracting to capture something, especially when I'm working on a lot of different projects.

An alternative would be to always insert the capture into the buffer I'm currently working on, but I'd rather not do that.

I think I could also just have a small piece of executable code at the beginning of each notebook that defines all the captures, but there must be a better way than that.

I suspect that there may be some way to do this by giving the target as a function, but I can't figure out how to do that, and I'm not sure whether it's the best way.

What would be ideal is that any capture done in ~/project_a or any of its subdirectories would go to ~/project_a/capture.org, but I can easily live with the customization applying only to the specific file (~/project_a/notebook.org) that I use as my notebooks, since I'll almost always have that open.


2 Answers 2


You can do it with advice. The code below works and will actually just set the org capture directory to a relative path as in the original answer, but by changing the definition of my-org-capture-notes-file, you can define the org-default-notes-file to be whatever you want based on the file org-capture was called from.

Note that this code will crash if, for some reason, you call org-capture from a buffer without an associated file name (such as a shell), but you could easily fix that by checking if buffer-file-name is empty.

(defun my-org-capture-notes-file (path)
  ;write a function here to define your org capture file based on a path.
  ;toy example below for proof-of-concept (does same thing as relative path)
  (concat (file-name-directory path) "org/notes.org"))

(defun my-org-capture-notes-file-from-buffer (&rest args)
  (setq org-default-notes-file (my-org-capture-notes-file buffer-file-name)))

(advice-add 'org-capture :before 'my-org-capture-notes-file-from-buffer)
  • Thanks so much Zorgoth! Could you clarify what the last line does?
    – njc
    Apr 3, 2019 at 19:23
  • 1
    The last line adds "advice" that causes my-org-capture-notes-file-from-buffer to be called before org-capture, whenever org-capture is called. my-org-capture-notes-file-from-buffer will receive the same arguments as org-capture, which is the reason for the &rest args. We don't use any of these arguments in this particular application of advice, but if we didn't put them somewhere, we would get an error. For more about advice, see gnu.org/software/emacs/manual/html_node/elisp/…
    – Zorgoth
    Apr 3, 2019 at 19:57

This is an imperfect solution, but good enough for my purposes (and the only one I've been able to come up with).

When you set the location of your capture file in your .emacs file, you can set a relative path, which will start from the location of the org file.

So I added this to my .emacs file.

(setq org-default-notes-file "org/capture.org")

The downside is that the relative path has to be the same for all org files. This works for me, because I'm structuring all my project directories the same way, but if someone can come up with a more flexible solution, I'd love to hear it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.