/ekg

The emacs knowledge graph, app for notes and structured data.

Primary LanguageEmacs LispGNU General Public License v3.0GPL-3.0

ekg

Quick intro

The ekg module is a simple but opinionated note taking application, for emacs. It is a substitute for such other emacs applications such as org-roam or denote. ekg stands for emacs knowledge graph.

Data is completely stored in a sqlite database. Notes are organized around tags, and you can view many notes by looking at one or more tags.

./screenshots/ekg-tag-view.jpg

Editing a note from one of these buffers, or capturing a new note, lets you edit both the note’s data and the text of the note itself in a buffer.

./screenshots/ekg-edit.jpg

ekg supports import from org-roam, and import and export to logseq. It also supports inline commands, which can be used for transclusion and any other functionality you may need.

Additionally, a video demonstration and explanation of ekg is on YouTube. This README has only the most basic information, but the full information can be found on the manual, which can be viewed in the Emacs info after installing.

Design of ekg

There are a few core ideas driving the design of ekg. The first is that a title and a tag are the same thing. This isn’t unique to ekg, other tools such as Logseq also consider tags to be equivalent to pages of the same name, although this functionality is limited since tags can only be just one word. In org-roam, a tag is just a tag, so you can have a note called “emacs” and a tag called “emacs”, but these are not related. ekg takes the idea a step further: there are (mostly) no titles, only tags. So, instead of writing text in a note called “emacs”, just write a note and tag it with “emacs”. There is no “title”, only tags. If you write another note about emacs, also tag it “emacs”, and maybe something else too. Or tag it something more involved, like an idea: “emacs’s power derives from putting all data in buffers, and making all commands deal with buffers.” That’s a perfectly fine tag, and if you notice a connecting idea, you can tag it with this as well.

The advantage of this method is that it solves something that has bothered me for a while about the recent suite of tools like org-roam: backlinks are non-symmetrical. If you enter a note in your org-roam daily about emacs, and link it to the emacs note, then when you go to the emacs note, you have to explicitly enable the backlinks buffer to see the daily entry where you first entered it. Systems such as Logseq and the original Roam have backlinks alongside normal content, but this doesn’t seem possible in emacs, where a buffer of a file is expected show the file, and tricks with overlays can’t solve the issue. Even if it could, I want a system in which it doesn’t matter where you enter the data, it shows up in the original place the same as everywhere else it is linked to, not as a backlink, but just as part of the content. Having notes with no title, only tags, makes this possible, because there is no longer a difference between linking and writing in the context in, both are denoted by tags.

As a consequence of this design, notes can be small, because to add another note to a subject, you don’t need to append to an existing note, you can create another note.

Additionally, ekg has another key difference: it uses sqlite instead of the filesystem. When notes are small and do not have titles, files don’t make a lot of sense anymore. Additionally, the filesystem is limited. Even in org-roam, which uses it, it needs to be augmented with sqlite anyway to enable fast querying of tags and other operations. The sqlite-only approach also means it is much easier to make certain kinds of changes, since they only involve changing the database and not the text as well. In general, text and data are separated as much as possible here, so there’s no need or desire for the text to have to store data as well, we leave that completely to the database.

Prefixed tags

Another concept, loosely applied in ekg is that of tags with standard prefixes. By default, date tags are prefixed with “date/”. This is a way to distinguish date tags from other kinds of tags. Most tags shouldn’t need it, but it often is useful to have prefixes to group tags in some way. For instance, perhaps all idea tags should be prefixed with “idea/”. In my ekg repository I use in my company, I have “person/” as a tag prefix for my coworker’s username.

The benefit of this is that it’s now possible to narrow in on just tags of a certain type if necessary.

There are a few other types of prefixes commonly used for tags. One is that titled resources have default tags that are prefixed with “doc/”, followed by the name of the document.

Warning

ekg is a fairly new package, and as such, there may be significant bugs. Testing is done, but this package has not yet had the wide use that will surface many kinds of bugs.

Installation

ekg is currently hosted on MELPA. It requires Emacs 28.1 or higher and the triples package, which is a way to express a graph in sqlite in emacs, alongside basic querying functionality. Emacs versions prior to version 29 are dependent on emacsql to provide sqlite functionality, which itself has a dependency on having a sqlite binary available on your system.

An example installation using use-package is below:

(use-package ekg
  :bind (([f11] . ekg-capture)))

Usage

To create a note, run ekg-capture to capture a text note, or ekg-capture-url to capture a website. The note will, by default, be tagged with the current date. This can be changed by changing the variable ekg-capture-auto-tag-funcs, which is a series of functions that are called and can add tags.

At the top of the note is a special section, which will be unfamiliar. This is the metadata section, where it stores and displays editable metadata, notably tags, but possibly other data such as URLs. If you want to change tags, just edit them in the metadata section. Tags should autocomplete based on the tags available to use.

The basic read operation in ekg is to show a list of notes according to some rule. An example is ekg-show-notes-with-tag. The notes displayed can be navigated between using n and p, and interacted with. The following section has a complete list of commands and keybindings.

Command summary

Global commands, can be run everywhere, and most should be bound to useful keybindings:

CommandDescription
ekg-captureCapture a new note
ekg-capture-urlCapture a new note about a URL
ekg-show-notes-with-tagOpen a tag buffer for notes matching the single tag given
ekg-show-notes-with-any-tagsOpen a tag buffer for notes matching any of the given tags
ekg-show-notes-with-all-tagsOpen a tag buffer for notes matching all of the given tags
ekg-show-notes-in-trashOpen a tag buffer that shows all notes with only trashed tags
ekg-show-notes-for-todayOpen a tag buffer that shows notes with today’s tag
ekg-show-notes-latest-capturedOpen a buffer that shows the latest notes that have been captured
ekg-show-notes-latest-modifiedOpen a buffer that shows the latest notes that have been modified
ekg-browse-urlOpen a URL stored as a resource to a note, completing by note title

These are also global commands, but for more occasional or specialized uses:

CommandDescription
ekg-global-rename-tagRename a tag, updating all references to it
ekg-upgrade-dbAfter upgrading, update any obsoletely stored data
ekg-clean-dbRemove unused data from the database, including empty tags

Commands relevant to capture buffers:

CommandDescription
ekg-change-modeChange note major-mode
ekg-capture-finalizeFinish and save (bound to C-c C-c)

Commands relevant to edit buffers:

CommandDescription
ekg-change-modeChange note major-mode
ekg-edit-finalizeFinish and save (bound to C-c C-c)

Commands relevant to note view buffers:

CommandDescriptionBinding
ekg-notes-tagOpen another tag buffer selecting from tags of current notet
ekg-notes-openEdit the currently selected noteo
ekg-notes-deleteDelete the currently selected noted
ekg-notes-removeRemove the tag buffer’s tags from the currently selected noter
ekg-notes-browseOpen the resource, if one existsb
ekg-notes-select-and-browse-urlSelect from the URLs in the current note buffer, and browse.B
ekg-notes-refreshRefresh the tag, refetching all the data displayedg
ekg-notes-createAdd a note with all the tags displayed in the bufferc
ekg-notes-nextMove selection to the next noten
ekg-notes-previousMove selection to the previous notep
ekg-notes-any-note-tagsOpen another tag buffer showing any of the tags in the current notea
ekg-notes-any-tagsOpen another tag buffer showing any of the tags in any note in the bufferA
ekg-notes-killKill a note from the current view (does not change the database)k