How to auto-generate org-ID following org-roam-find-file(-immediate)?

I would like to generate automatically org-ID for a file upon creating with org-roam-find-file or org-roam-find-file-immediate. I have org-roam-prefer-id-links set to t, with the idea that I prefer to use ID links to files. But, at present, I have to manually create org-ID for each new file.Is there a way to include a function call (e.g., to org-id-get-create) as part of an org-roam-capture template? I thought I might add org-id-get-create as a hook to org-capture (the mechanism by new org-roam files are generated), but from a Google search (see 1,2 below), that sounds like it might be problematic. I believe org-roam-v2 will do this sort of thing, but I haven’t switched over yet.

  1. incompatibility with org-id-get-create · Issue #472 · org-roam/org-roam · GitHub
  2. Bug: `org-id-get-create` hook causes an error that prevent completing capture process · Issue #420 · org-roam/org-roam · GitHub

I suppose one option is to generate an ID with a date-time stamp (e.g., %U). This will be unique (barring time travel or super-speed multi-tasking). But, a potential downside is that creating IDs without using org-id functions, such as org-id-get-create, will probably break how org-id keeps track of IDs and their file location.

1 Like

I use my own time stamp (yyyy-mm-ddThhmmss) for ID. I don’t think using a custom way to generate an ID “break[s] how org-id keeps track of IDs and their file location”. But you are right in that this way does not get the generated ID stored in org-id-locations-file.

I recently learned that you can run org-id-update-id-locations with a filename as an argument to get org-id-locations-file updated. The command accepts a list of filenames, so you need to do something like (org-id-update-id-locations '("path/to/")).

Alternative to a custom ID generation, you can use %(sexp) in org-capture and org-roam-capture, so you could add %(org-id-new) in the :head property of the capture template; however, org-id-new does not seem to call a function to update the id locations, so in any case you’d need to call (org-id-update-id-locations) separately (manually, or in some hook).

Perhaps others have better ideas.

Edit: It looks like V2’s “capture” (via org-roam-node-insert) does seem to add a property drawer with an ID automatically generated… I don’t know how it is done technically, if someone can find it out, you could probably copy the same way in V1.

Edit 2: OK… I am answering my own question.
I am not sure anymore if this is V2 only, but it adds a function to org-capture-prepare-finalize-hook; it gets run in the capture process after C-c C-c and the new file’s buffer gets presented for you. In this hook, function org-roam-capture--install-finalize is called. It kinda does something to add another function. This function generates the property and ID (source). I think that this “something” is to ensure that this function is called only once for the file generation, but not sure as the hook gets removed.

It looks to be a little too involved for a simple copy and paste into V1 (it might be easy, but I don’t know).

1 Like

Can you give the code snippet for including that timestamp as an ID in the capture template? noob here

Sure. What have you tried so far, and what part of that does not make sense to you?

I haven’t tried anything because I doubt I’d get it right without any good examples from the manual, not knowing elisp, and I’m trying to focus on all the other things to learn about org-roam to even get started writing my first note.

I got it

(setq org-roam-capture-templates
  (quote (
    ;; Override default to set timestamp to UTC
    ("d" "default" plain (function org-roam--capture-get-point)
     :file-name "%(format-time-string \"%Y%m%dT%H%M%SZ--${slug}\" (current-time) t)"
     :head ":PROPERTIES:
:ID:    %(format-time-string \"%Y%m%dT%H%M%SZ\" (current-time) t)
:TITLE: ${title}
     :unnarrowed t))))

now that’s amazing :star_struck:

Question on the template above. Does it make any difference whether the title is put into the properties drawer at the top of the file, as it is in that template, or into a #+TITLE line immediately after the properties drawer, as it is in my template? :slight_smile:

Yes. File-level property drawer is very new since Org 9.4 (“Property drawers allowed before first headline”). The keyword syntax has been the conventional way to define a title of a file (#+TITLE – lower case equivalent #+title: seems to be also recent change).

This more practically means that many Org packages recognise only the conventional keyword syntax for file titles (lower case seems to be well supported by Org Mode itself now).

Org-roam V1 currently supports both.

V2 currently does NOT. Not sure if @jethro has a plan to add back the support for file titles in the property drawer at the top of file – I believe he indicated that he did not plan to do so in one of the recent exchanges with me in a GH issue.

Thank you @nobiot, that makes me think I’ll stick with the way I currently do it then! :slight_smile:

1 Like

V1’s support was incidental: Org itself doesn’t support title within the property drawer. If this becomes a thing in Org, I’d reconsider.


The question about the title is a great example of why I asked for a snippet. I was asking myself the same question and I just picked one at random. As luck would have it, I picked wrong. What I really want to spend more of my experimentation time budget on, rather than customizing org-roam, is workflows, which I know will take a long time to hone. I’d love to see more examples of people’s init scripts to save time.

Not sure why you think you picked the wrong one. All you need to do is to change the title part from a property to a keyword.

That’s what I mean: the keyword is the right one for most intents and purposes, and the property is the wrong one. Anyway, minor. Thanks :slight_smile:

1 Like

What does having a property drawer before the first headline do (as opposed to somewhere else)?

Also I’m still confused about custom_id vs id. Why are there 2 and what’s the difference?

Property drawer before the first headline is to set properties for the file, not headlines.

For CUSTOM_ID vs ID, someone else had a very succinct explanation somewhere in this Discouse forum.

For the purpose of Org-roam, use ID. CUSTOM_ID is not recognised by Org-roam.

CUSTOM_ID is meant to be for manual ID, and Org Link recognises one with # syntax for file links as in [[file:path/to/]].

ID is meant to be generated automatically via Org-ID package (part of Org now), and tracked by its own cache mechanism (file and hash table). ID has its own link type as in [[id:uuid]]. With the Org-ID cache mechanism and Org Link syntax, links would work independent of file paths (so that you can move files and headlines around as long as IDs are constant).

1 Like

I know this is a bit old, but it might be useful to others. Org allows you to use timestamps in the creation of IDs by default. You can control control the format. See below:

#+begin_src emacs-lisp   :exports both
(setq org-id-method 'ts)
(setq org-id-ts-format "id-%Y%m%d-%H%M%S")