README.org
July 13, 2026 · View on GitHub
#+OPTIONS: toc:nil
- Vulpea
#+begin_html
vulpea · vulpea-ui · vulpea-journal · vulpea-para#+end_html
A database layer for your org-mode notes. Vulpea indexes your notes and provides fast queries for tags, links, metadata, and full-text search - all without blocking your workflow.
** Why Vulpea?
Org-mode is powerful, but working with hundreds or thousands of notes becomes difficult. Finding notes, discovering connections, and querying your knowledge base requires tooling beyond what org-mode provides.
Vulpea solves this by maintaining a database of your notes that stays in sync with your files. You get:
- Fast note finding - Search by title, tags, or content across thousands of notes
- Connection discovery - Find what links to what, explore backlinks
- Rich queries - Filter notes by tags, metadata, links, or custom predicates
- Non-blocking sync - Database updates happen in the background, never interrupts your typing
- External change detection - Works with git, Dropbox, Syncthing - files changed outside Emacs are detected automatically
*** Use Cases
Personal knowledge management - Use =M-x vulpea-find= to navigate your notes, =M-x vulpea-insert= to create links between ideas. Vulpea handles Zettelkasten-style workflows where connections matter.
Building applications - Vulpea provides a foundation for note-based apps. [[https://github.com/d12frosted/vino][Vino]] uses Vulpea to manage wine collections with ratings, producers, and regions. The included journal module provides daily notes with widgets.
Large collections - Designed to scale. The async architecture and optimized queries handle 100k+ notes without degrading performance.
** Design Philosophy
Vulpea is designed as a foundation, not an application. Where tools like [[https://github.com/org-roam/org-roam][org-roam]] aim to replicate Roam Research in Emacs (and do it very well), Vulpea provides a stable API layer for building your own note-based workflows and applications.
Key differences:
- Schema as implementation detail - Vulpea's database structure is internal. The public API is functions and data structures, not SQL tables. This allows the backend to evolve without breaking user code.
- Library-first - Vulpea exposes clean abstractions like =vulpea-note= that don't leak internals. Build applications on top without coupling to implementation details.
- Coexistence - Vulpea and org-roam can run side-by-side; they use separate databases and don't interfere.
For a detailed comparison with org-roam and org-node, see [[file:docs/comparison.org][Comparison with Other Libraries]].
Vulpea originally started as a layer over org-roam, but v2 is a complete rewrite with its own database and indexing. For the full history and design rationale, see [[https://d12frosted.io/posts/2025-11-28-vulpea-v2-breaking-up-with-org-roam][Vulpea v2: a story of breaking up with org-roam]].
** Key Features
- 🌳 Files or headings - A note is any org node with an =ID=: a whole file, or a single heading inside a larger file
- 🚀 Actually async - File watchers, background processing, and an opt-in worker process (=vulpea-db-async-extraction=) that parses and writes off the main thread - saving a 100MB file blocks Emacs for about a millisecond
- 📊 Optimized queries - Hybrid database schema for fast reads
- 🔌 Extensible - Plugin system for custom extractors and tables
- 🏷️ Rich metadata - Type-aware metadata with automatic coercion
- ⚡ Scales - Tested with 100k+ notes
** Quick Start
#+begin_src emacs-lisp ;; 1. Configure (defaults to org-directory, so often not needed) ;; (setq vulpea-db-sync-directories '("~/org/"))
;; 2. Build database (first time only) (vulpea-db-sync-full-scan)
;; 3. Enable auto-sync (vulpea-db-autosync-mode +1)
;; 4. Start using ;; M-x vulpea-find - find and open notes ;; M-x vulpea-insert - insert link to a note #+end_src
Note: A note is any org node with an =ID= - a whole file /or/ a single heading. One file can hold many notes: keep every swim session as a heading in =swimming.org= and each one is a first-class, queryable note. Vulpea indexes exactly these ID-carrying entries; use =M-x org-id-get-create= to add one to the entry at point.
*** Best performance
Optional, but recommended once the basics work:
#+begin_src emacs-lisp ;; Parse and write in a background process: saving a note - even a ;; 100MB one - blocks Emacs for about a millisecond. (setq vulpea-db-async-extraction 'full)
;; Skip org-mode-hook during indexing (fine unless you rely on ;; hook-based per-file setup). (setq vulpea-db-parse-method 'single-temp-buffer)
;; Index only [[bracketed]] links. id: links are always bracketed, ;; so the note graph is unaffected; skips the expensive scan for ;; plain https://... links in prose. (setq vulpea-db-index-plain-links nil) #+end_src
Also install [[https://github.com/sharkdp/fd][fd]] and [[https://github.com/emcrisostomo/fswatch][fswatch]] - vulpea uses them for fast directory scans and external change detection. Then run =M-x vulpea-doctor=: it verifies the setup end to end and flags anything that quietly degrades performance (including extractor plugins that bypass the background worker). Details and trade-offs in [[file:docs/configuration.org][configuration]].
→ [[file:docs/getting-started.org][Full Getting Started Guide]]
** Installation
Available on [[https://melpa.org/#/vulpea][MELPA]]:
#+begin_src emacs-lisp ;; Using package.el (after adding MELPA to package-archives) (package-install 'vulpea)
;; Using use-package (use-package vulpea)
;; Using straight.el (straight-use-package 'vulpea)
;; Using elpaca (elpaca vulpea)
;; Using Doom Emacs - add to packages.el, then run 'doom sync' (package! vulpea) #+end_src
Doom users: see the [[file:docs/getting-started.org][Getting Started guide]] for a complete =config.el= example and a note about =doom env= (required for =fswatch= / =fd= detection).
Or clone manually:
#+begin_src bash git clone https://github.com/d12frosted/vulpea #+end_src
#+begin_src emacs-lisp (add-to-list 'load-path "/path/to/vulpea") (require 'vulpea) #+end_src
*** Dependencies
- Emacs 27.2+
- =org-mode= 9.4.4+
- =emacsql= 4.3.0+ (with =emacsql-sqlite-builtin=)
- =s= 1.12+
- =dash= 2.19+
*** Optional (Strongly Recommended)
For best performance, especially with large collections, install these external tools:
| Tool | Purpose | Impact | Install | |-----------+------------------------------------+---------------------------------------------------------+----------------------------------------------------------------------| | =fd= | Fast directory scanning | 15× faster than =find=, critical for polling mode | =brew install fd= / =apt install fd-find= / =pacman -S fd= | | =fswatch= | Reliable external change detection | Instant detection of git/Dropbox/external changes | =brew install fswatch= / =apt install fswatch= / =pacman -S fswatch= |
Without =fswatch=, Vulpea falls back to polling (periodic directory scanning). Without =fd=, polling uses =find= which is significantly slower. With both tools installed, external changes are detected instantly with near-zero overhead.
** Documentation
| Document | Description | |----------+-------------| | [[file:docs/getting-started.org][Getting Started]] | Installation, first steps, basic concepts | | [[file:docs/user-guide.org][User Guide]] | Daily usage, interactive commands, working with notes | | [[file:docs/configuration.org][Configuration]] | All options explained, performance tuning | | [[file:docs/api-reference.org][API Reference]] | Programmatic usage, query functions, data structures | | [[https://github.com/d12frosted/vulpea-journal][Journal Module]] | Daily notes with widgets and calendar integration (separate package) | | [[file:docs/plugin-guide.org][Plugin Guide]] | Writing custom extractors for domain-specific data | | [[file:docs/troubleshooting.org][Troubleshooting]] | Common issues and solutions | | [[file:docs/comparison.org][Comparison]] | How vulpea compares to org-roam and org-node |
** Ecosystem
Companion packages that extend Vulpea:
- [[https://github.com/d12frosted/vulpea-ui][vulpea-ui]] - Visual tools for your notes: a per-note sidebar of widgets (outline, backlinks, stats, and more) plus standalone views, with an easy API for your own widgets. Schemas get especially nice treatment here: a sidebar health widget that flags the current note's violations with one-key fixes, and a collection-wide schema dashboard that shows how every note measures up to the schemas that apply to it.
- [[https://github.com/d12frosted/vulpea-journal][vulpea-journal]] - Daily journaling with calendar integration. Creates one note per day with sidebar widgets for navigation, calendar view, and "on this day" from previous years.
- [[https://github.com/d12frosted/vulpea-para][vulpea-para]] - The PARA method (Projects, Areas, Resources, Archives) on top of Vulpea. A note's role is read from its tags rather than its folder, with a self-updating agenda, capture that files itself, and views for areas, projects, and people.
- [[https://github.com/fabcontigiani/consult-vulpea][consult-vulpea]] - Consult integration for Vulpea. Provides =consult-vulpea-find= and =consult-vulpea-insert= with live preview and consult's narrowing features.
- [[https://github.com/fabcontigiani/citar-vulpea][citar-vulpea]] - Citar integration for Vulpea. Minor mode for managing bibliographic notes, linking citation library entries to Vulpea notes.
- [[https://github.com/fabcontigiani/embark-vulpea][embark-vulpea]] - Embark actions and export for Vulpea notes.
- [[https://github.com/jwiegley/vulpea-field][vulpea-field]] - Extension for easily adding new database fields. Compatible with v1 only - it builds on the org-roam-backed =vulpea-db-define-table= mechanism; in v2 use the [[file:docs/plugin-guide.org][plugin system]] instead.
- [[https://github.com/d12frosted/publicatorg][publicatorg]] - Make your Vulpea notes public.
** Real-World Usage
Applications built on Vulpea:
- [[https://github.com/d12frosted/vino][vino]] - Wine cellar management with rich metadata
- [[https://github.com/majorgreys/claude-orgmode][claude-orgmode]] - Connects Claude with org-mode notes
- [[https://github.com/smclaren727/emacs-org-serve][emacs-org-serve]] - Go service that reads the Vulpea database directly and serves an Org vault as JSON + PWA to mobile devices
Notable user configurations:
- [[https://github.com/d12frosted/environment][d12frosted/environment]] - Personal configuration (13k+ notes), including the task management setup from the [[https://www.d12frosted.io/posts/2020-06-23-task-management-with-roam-vol1][Task Management]] blog series
- [[https://github.com/jwiegley/dot-emacs][jwiegley/dot-emacs]]
- [[https://github.com/chrisbarrett/emacs-d][chrisbarrett/emacs-d]]
- [[https://github.com/d4ncer/.emacs.d][d4ncer/.emacs.d]]
- [[https://github.com/benthamite/dotfiles][benthamite/dotfiles]]
** What's New in v2
v2 is a complete rewrite:
- No org-roam dependency - Standalone library with custom database
- Async-first - Non-blocking updates via file watchers
- Plugin system - Custom extractors with schema versioning
- Performance - Optimized for 100k+ notes
→ [[file:docs/migration.org][Migration Guide from v1]]
** Contributing
Contributions welcome! See [[file:docs/architecture.org][Architecture]] for design decisions.
Areas where help is needed:
- Performance testing with large collections
- Platform testing (Windows, Linux, macOS)
- Plugin examples
- Documentation improvements
** License
GPLv3
- Support
If you enjoy this project, you can support its development via [[https://github.com/sponsors/d12frosted][GitHub Sponsors]] or [[https://www.patreon.com/d12frosted][Patreon]].