org-roam-ui

An External Brain

I have a terrible memory…

And like most folks dealing w/ software architecture, I have to deal w/ a humongous amount of information.

So I take notes. Lots of them.

In fact I’ve extended this practice to every subjects I work on / study, with extensive cross-referencing.

The trick is not to remember stuff but to find it back quickly.

My current setup1 is pretty straightforward: I use Org mode inside Emacs. To quickly search a piece of information I use deft or sometimes deadgrep.

The combination of these tools + my collection of notes act like an external brain.

Digital Gardening & Zettlekasten

My notes are organized in a very specific way.

I organize them hierarchically under subfolders.

I like mid-sized files, only splitting them when they attain a critical mass in term of size or complexity.

This practice of building and maintaining a personal wiki, as old as the world itself, is now getting qualified of digital gardening2. Indeed, you just don’t add content but have to regularly reorganize it, like you would clear a patch of soil.

I also stumbled upon the Zettelkasten Method and liked its idea of bidirectional links3 but quickly rejected one aspect of its philosophy: creating many many small files, one for capturing each incoming thought.

Indeed, bidirectional links allow for a very fluid way to structure information (akin to what you may find in a graph database).

Still, I like to impose some structure, a taxonomy loosely based on how I mentally represent things. Having to deal with a gazillion files would not imped finding information back, but would discourage me from regularly gardening my notes.

So while I adhered to the digital gardening philosophy, I rejected (my understanding of) Zettelkasten.

Org-Roam

I discovered Org-Roam through its accompanying visualization tool: Org-Roam-UI.

It’s an extension to Org to provide it a similar feature set to Roam, the most famous Zettlekasten software.

Even if I didn’t buy to the Zettlekasten philosophy, the ability to graph all the notes relationships dynamically was tempting.

I took a quick look around and realized that the implementation isn’t too intrusive:

Furthermore, in its latest iteration it supports:

So I didn’t see any reason not to try it.

Indexing an Existing Notes

Things worked smoothly, but I was struggling to find a command to register existing notes in Org-Roam’s DB.

Calling org-id-get-create would allow generating an org id for current file / outline. But that wasn’t sufficient to make it appear.

Indeed, I also had to register it in the org-id-locations-file by passing the current file path to org-id-update-id-locations.

Finally, I needed to call org-roam-db-update-file for Org-Roam to update its DB entry for the current file.

This gives:

(defun prf/org-roam/add-index-current ()
  "Add index to file of currently visited buffer, if applicable."
  (interactive)

  (unless (and (buffer-file-name)
		       (file-exists-p (buffer-file-name)))
    (user-error "Current buffer is not visiting a file that exists on disk."))

  (unless (prf/org/file-path-indexable-p (buffer-file-name))
    (user-error "Current buffer is not visiting an indexable file."))

  (unless (org-id-get)
    (org-id-get-create)
    (call-interactively #'save-buffer))

  (org-id-update-id-locations (list (buffer-file-name)))

  (org-roam-db-update-file))

Forcing Index of All Files

Sometimes I like to massively rename / move / delete note files and Org-Roam doesn’t seem to be super happy about this.

Using the same logic as above, I came up w/ the following command:

(defun prf/org-roam/rescan ()
  "Force rescan of whole `prf/dir/notes'."
  (interactive)
  (prf/org/index-rescan-all)
  (org-roam-db-sync))

(defun prf/org/index-rescan-all ()
  "Populate `org-id-locations' by rescaning recursively all files in `prf/dir/notes'."
  (interactive)
  (let ((buffs-snapshot (buffer-list)))
    (org-id-update-id-locations
     (f-files prf/dir/notes #'prf/org/file-path-indexable-p t))
    ;; NB: `org-id-update-id-locations' opens all matching files, we close them after processing
    (mapc #'kill-buffer
          (-difference (buffer-list) buffs-snapshot))))

Conclusion

I’m pretty happy with this setup.

The Org-Roam-UI helps me visualize the current structure of my notes and has helped me discover patterns and anomalies I had no idea existed.

Notes

  1. I originally started w/ Tomboy, then moved to MediaWiki, Markdown and finally to Org as soon as I started using Emacs. 

  2. It’s more than an empty buzzword. Lots of effort has been put on studying and qualifying this phenomenon. Don’t hesitate to browse the rest of Maggie Appleton’s site to learn more. 

  3. Not supported natively by Org as of writting. I was circumventing this limitation by creating a link in each of the 2 cross-referenced files. 

  4. This DB is just a cache, a derived data systems (i.e. materialized view). The system of record are the org files themselves. Hence there is no risk of unrepairable corruption.