# Org-roam: a plain-text Zettelkasten inside Emacs

> Org-roam is an Emacs package that adds non-hierarchical note-taking and backlinks to Org-mode files. It suits people already living in Emacs, and it assumes you are willing to keep the database and your files in step.

**org-roam/org-roam** — Rudimentary Roam replica with Org-mode

- Repository: https://github.com/org-roam/org-roam
- Website: https://www.orgroam.com
- Stars: 6,034 · Forks: 489
- Language: Emacs Lisp
- License: GPL-3.0
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/org-roam-org-roam

## What Org-roam adds to a directory of Org files

Org-mode already handles outlines, TODO states and export. What it does not give you is a way to link two notes without deciding in advance which one is the parent. Org-roam borrows from the Zettelkasten method and from Roam Research to fill that gap: notes become nodes, links between them become edges, and the package renders the reverse direction, the backlinks, so you can see what points at the note you are reading. The README describes it as "a plain-text knowledge management system" and says it should work as a plug-and-play solution for anyone already using Org-mode as a personal wiki. That last phrase is the honest scope. If you do not already keep notes in Org files, Org-roam is not a starting point, it is an extension of one. The audience is the Emacs user with a notes directory and a growing sense that folders are the wrong shape for what they are writing.

## Nodes, the SQLite index, and why the database exists

The repository layout is instructive. Alongside org-roam.el sit org-roam-node.el, org-roam-db.el, org-roam-capture.el, org-roam-id.el, org-roam-migrate.el and org-roam-mode.el, with an extensions/ directory beside them. The split tells you the design: nodes are a first-class concept, and a database layer sits between your files and the commands you run.

The mechanism is a cache. Org-roam scans the Org files under org-roam-directory, extracts nodes, links, tags and titles, and writes them into a SQLite database through emacsql. Commands such as org-roam-node-find and the backlink buffer query that database instead of parsing every file on each invocation. This is why the README's configuration sample turns on org-roam-db-autosync-mode rather than leaving the index to be rebuilt by hand. It is also the source of the package's most common failure mode: the database is derived state, and derived state drifts. Edit files outside Emacs, or disable autosync, and the index can describe a version of your notes that no longer exists. The graph visualization and backlinks read from the same index, so a stale database produces confidently wrong output rather than an error.

## Installing Org-roam from MELPA and capturing a first note

The README gives several installation routes. The shortest is package.el against MELPA:

```
M-x package-install RET org-roam RET
```

After that, a minimal use-package configuration points Org-roam at your notes directory, binds a few keys and starts the automatic sync. The README's sample uses file-truename around the directory path, and it notes that this is only necessary when org-roam-directory is reached through a symbolic link, because Org-roam will not resolve the link itself.

```emacs-lisp
(use-package org-roam
  :ensure t
  :custom
  (org-roam-directory (file-truename "/path/to/org-files/"))
  :bind (("C-c n l" . org-roam-buffer-toggle)
         ("C-c n f" . org-roam-node-find)
         ("C-c n g" . org-roam-graph)
         ("C-c n i" . org-roam-node-insert)
         ("C-c n c" . org-roam-capture)
         ("C-c n j" . org-roam-dailies-capture-today))
  :config
  (org-roam-db-autosync-mode))
```

With that loaded, C-c n c runs a capture template to create a node, C-c n f finds an existing one by title, and C-c n i inserts a link to a node at point. C-c n l toggles the backlink buffer for the current note, which is where the payoff shows up: the notes that reference this one, listed without you having to search for them. C-c n j captures today's entry in the dailies series. If you install without a package manager, the README requires that you add both the package directory and its extensions/ subdirectory to load-path, and that you have org at version 9.6 or later, plus emacsql and magit-section.

Doom Emacs users take a different path. The :lang org module supports Org-roam but does not enable it by default; you add the +roam flag to the org module in $DOOMDIR/init.el, save, and run doom sync -u. Doom pins the package to a specific commit, and the README explicitly warns against unpinning it, asking users to request a bump instead.

## Where Org-roam is the wrong tool

The dependency on Org-mode is not incidental, and it is the first thing to weigh. Org-roam reads Org files; it is not a Markdown tool with an Org exporter bolted on. If your notes live in Markdown because other applications need to read them, this package does not meet you there.

The second constraint is Emacs itself. Every interaction runs through Emacs commands, keybindings and completion frameworks. The README's own configuration sample includes a line adjusting org-roam-node-display-template "if you're using a vertical completion framework", which is a small reminder that the quality of the interface depends on choices you made elsewhere in your configuration. There is no separate application, no browser client and no mobile story in what the project documents.

The third is the database. Because the index is built from files, any workflow that writes to those files without going through Emacs, a sync client, a script, another editor, creates a window where the index and the files disagree. Org-roam does not present this as a problem to solve, but it is the thing that bites people, and it is worth deciding how you will handle it before you have a thousand notes. The README does not document a rollback path for a corrupted index.

## Org-roam against Denote and Obsidian

Denote is the closest comparison in the Emacs world, and the difference is philosophical rather than functional. Denote's approach is file-name-as-identifier: the metadata lives in a predictable filename scheme, and the tools work over plain files with no index to maintain. Org-roam's approach is a database over the files, which buys faster search and a backlink view that scales, at the cost of the synchronization problem described above. If you want the smallest possible surface and no derived state, Denote's model is the cleaner one. If you want a graph and a queryable index, that is what Org-roam is for.

Obsidian sits outside Emacs entirely. It offers a similar linking and graph experience in a standalone application with a Markdown store, which means it works on platforms and for people that Org-roam does not reach. The trade is that you leave the Emacs editing environment and the Org ecosystem the README leans on. Choosing between them is mostly a question of whether Emacs is already where you write.

## Maintenance, licensing and what upgrading costs

Org-roam is licensed under the GNU General Public License version 3 or later, which the README states plainly and which is consistent with the rest of the Emacs ecosystem. For personal use this changes nothing. If you plan to redistribute a modified version or bundle it into a product, read the licence text rather than a summary; that is a question for your own counsel, not for this article.

The release history is uneven. v2.3.0 arrived on 2025-05-25 and v2.3.1 on 2025-06-26, but the release before them, v2.2.2, is dated 2022-04-25. That is a three-year gap between releases, and it is the most useful maintenance signal in the repository. The project is not archived and the last push was on 2026-04-27, so work continues on the main branch even when tagged releases are sparse. Practically, this means users who track MELPA get changes between releases, and users who track MELPA Stable get the tagged versions. Doom users get neither by default: they get the commit Doom pinned, which is the whole point of the pinning and also the reason a fix you are waiting for may not arrive until Doom bumps it.

Upgrade cost is dominated by the database rather than by the Emacs Lisp. The repository contains org-roam-migrate.el, which is where schema changes are handled, and the CHANGELOG.md at the top level is where the project records what changed between versions. Check that file before upgrading, particularly across a major version, and back up your notes directory first. The Makefile is aimed at CI and distributions: it drives Eldev for lint and test, and the doc/ subdirectory builds the manual through its own Makefile.

## Conclusion

Adopt Org-roam if you already work in Emacs and want plain-text notes with backlinks that stay in files you control. Do not adopt it if you want a standalone application, a mobile client or a Markdown-first editor; Org-mode is the substrate here, not an export target. Before committing, verify that your Org version is at least 9.6, that emacsql and magit-section are available, and that org-roam-db-autosync-mode is enabled, because the backlink buffer and node search read from the database rather than from the files directly.

## FAQ

### How do I install Org-roam?

The README gives package.el as the shortest route: run M-x package-install RET org-roam RET against MELPA or MELPA Stable. Without a package manager you clone or download the release, add both the package directory and its extensions/ subdirectory to load-path, and make sure org 9.6 or later, emacsql and magit-section are present.

### How do I install Org-roam in Doom Emacs?

Doom's :lang org module supports Org-roam but does not enable it by default. Add the +roam flag to the org module in $DOOMDIR/init.el, save the file, and run doom sync -u in your shell.

### Is Org-roam dead?

The repository is not archived and the last push was on 2026-04-27, so the project is not abandoned. The release cadence is uneven, though: v2.3.1 is dated 2025-06-26 and the release before v2.3.0 was v2.2.2 in 2022.

### What is Emacs Org-roam?

It is an Emacs package described in its README as a plain-text knowledge management system that brings Roam's features into the Org-mode ecosystem. It borrows from the Zettelkasten method to support non-hierarchical note-taking, with backlinks and a graph view over Org files.

### How does Org-roam differ from Denote?

The Org-roam README does not cover Denote, so a direct feature comparison is not something the project documents. What the repository does show is that Org-roam maintains a SQLite index over your Org files through emacsql, which is the design decision that shapes its behaviour.

## Sources

- [License: GPL-3.0](https://github.com/org-roam/org-roam/blob/main/LICENSE)
- [org-roam/org-roam on GitHub](https://github.com/org-roam/org-roam)
- [Project website](https://www.orgroam.com)
- [README](https://github.com/org-roam/org-roam/blob/main/README.md)
- [Releases](https://github.com/org-roam/org-roam/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/org-roam-org-roam
