Tags are a way to link various org roam nodes. I’m currently using them to mark things as “I should share this publicly”. Given I have many notes, this is difficult to retroactively apply so I’ve written a script for this.

import sqlite3
from collections import defaultdict
from pprint import pprint
 
con = sqlite3.connect(os.getenv("APPDATA") + '/.emacs.d/org-roam.db')
cur = con.cursor()
 
output = defaultdict(list)
 
unshared = cur.execute("select id, title, file, tags from (select n.id, n.title, n.file, group_concat(t.tag, ', ') as tags from nodes n left join tags t on n.id = t.node_id where n.file not like '%daily%' group by n.id) where tags is null order by title;").fetchall()
 
for _id, title, filename, tags in unshared:
    try:
        with open(filename[1:-1]) as f:
            lines = f.readlines()
    except:
        print("Passing on ", filename)
        continue
    print('=====')
    print(''.join(lines[:10])) # they already have \n's in them.
    print("Which tags should this have (comma separated)?")
    tags = input()
    if ',' in tags:
        tags = tags.split(',')
    else:
        tags = [tags]
    for tag in tags:
        output[tag].append((_id, title, filename))
 
output = dict(output)
 
for tag, nodes in output.items():
    if tag == '':
        continue
    for node in nodes:
        print(f'("{tag}" . {node[2]})')
 
 
# Now take the output and run this in elisp:
"""
  (dolist (elt thelist)
    (let ((tag (car elt)) (filename (cdr elt)))
      (message (concat "Tagging " filename " with " tag))
      (find-file filename)
      (org-roam-tag-add (list tag))
      (save-buffer)
      (kill-buffer)
      ))
"""
select n.title, n.file, group_concat(t.tag, ', ') from nod
es n left join tags t on n.id = t.node_id where n.file not like '%daily%' group by n.id;