Skip to content
yibiePublic

About

Implement a modern note-taking app style in Org-mode.

Topics

Resources

Contributing

Stars

378 stars

Watchers

5 watching

Forks

Latest commit

 

History

90 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

中文: README_CN.md

Version line: Supertag V2 starts at v0.1.1. Earlier v5.x/v6.x releases belong to the previous product line; the new number is not a code downgrade. Database format versions are independent and unchanged.

Where V2 came from

I use Emacs and Org. In V1 I kept adding features to Supertag, and each one added a layer of paperwork to writing: first decide where the note belongs, then its title, its tags, whether to create a node now. As the features grew, one day I noticed I was spending far more time developing the system than writing notes — the opposite of the original intent.

So V2 exists for one goal: make recording notes enjoyable, as if you had pressed do-not-disturb.

Concretely, V2 removes fields and the dedicated supertag-capture. Fields go because of the cost of defining, configuring and maintaining them; structured notes themselves are fine. The dedicated capture made recording carry too much filling-in.

supertag-view-table goes as well. It did two jobs: browsing nodes under a tag, and handling fields values. Browsing was taken over by supertag-view-stream; the fields-value half retired together with fields.

What remains is the database part: search, link discovery and views read from it instead of rescanning every file. Org properties are not removed — they are still ordinary text in your source files, and existing properties and historical data are not deleted because of this.

Writing flows

Recording now uses Org's own M-x org-capture. The templates are still yours: write it down first, and decide file, title and category later; Supertag adds the ID and tags only when you need them.

The difference for me: I used to think about which file a note goes into, what type it is, and whether to create a node right now. Now I drop it first and decide while organizing. Both ways work; they differ only in when the decision happens — classify first or write first. The latter suits me better.

Completion. Type # in an Org note to complete an existing tag; keep typing a new name and select [New] to create it in place. Type [[ to complete an existing note title or create a new note from the same list. What remains in the file is still an ordinary #tag or Org ID link.

Nested tags. Type a path such as #emacs/package/elpa, and completion builds the emacs › package › elpa hierarchy. The source receives the leaf tag #elpa, while Supertag records the parent relationships. A Stream or descendant query for emacs can then include notes under package and elpa as well.

One thing to be clear about: this is not zero initial configuration. Your org-capture template still has to name a target file; you also set the sync directory in init before (require 'supertag) and run the first scan once. That is done once, and the template is in doc/setup.md.

On what counts as a note: plain text can be written directly, and the scan will not create an ID for a heading that has none; only headings carrying an Org ID (an :ID: property) enter the nodes. When a heading should become a node, add the ID by hand with M-x org-id-get-create, or let org-capture add it on finalize (the optional integration; doc/setup.md again).

Organizing, made easy

Organizing happens after recording, and you can stop at any point.

Tag after the fact. M-x supertag-add-tag adds a #tag to a heading; tags are ordinary text.

Turn a keyword into a note. Select text, or put point on a heading, and run M-x supertag-promote; pick a template keyword, and it creates a new node or reuses an existing note per that template, replacing the selection with an ordinary Org link.

Customizing promote is a core idea, and the configuration has two layers: template data, and wrapping a template into a command.

(setq supertag-creation-templates
      '((:key "concept" :name "Concept"
         :target-file "~/Documents/notes/concepts.org"
         :tags ("concept"))))
;; supertag-define-promote-command is a macro; place it after (require 'supertag) so it expands.
(supertag-define-promote-command my/supertag-promote-concept "concept")
;; From then on M-x my/supertag-promote-concept turns the selection into a concept node

Make connections. Open Node View (M-x supertag-view-node); it has an unlinked-mentions section listing literal candidates: other notes' bodies mention the current node's title or aliases but have not written a link yet. Each source offers three actions: Link replaces that single occurrence, Link all replaces every occurrence in that source, and Ignore in node stops showing it. This section appears only for concept nodes — headings that live in your templates' target files and carry a persistent ID; ordinary note nodes do not show it.

If you like, you can also start typing [[ to complete a note title and add a connection directly.

Discover related notes along the way. With local Ollama or a compatible embedding service installed (optional), Node View lists semantically similar notes; installation and privacy notes are in "Optional: Similar notes" below. M-x supertag-mention-mode marks known concept titles and aliases in the body, as hints only, writing no links. When you really want to move a note, use M-x supertag-move-node.

Reviewing, at the right moment

M-x supertag-view-stream is the stream of every node, newest first; narrow it to one theme with f tag:prj, which gives the same stream as the tag (including sub-tags). M-x supertag-view-stream-find opens the stream of any query directly, and M-x supertag-stream-agent-open the stream a Stream agent lays out, from any Org file. Inside a stream, f adds one more condition and opens that substream, u goes back to the stream it came from. At the f prompt, type words, each of which must appear somewhere in the title, body, tags or property values (a part of a word is enough); tag:prj asks for that tag or a tag that extends it, and STATUS:todo for a property value, when some node has that property; text starting with ( is a query expression such as (tag "prj"). Discovery's s reads the same input. C-u f builds the condition step by step. Nodes are listed newest first (supertag-view-stream-order). A long stream shows its newest 200 nodes (supertag-view-stream-max-nodes); m shows twice as many. Archived nodes stay out of Stream, Discovery and Summary panels, as Org keeps them out of the agenda: a heading tagged ARCHIVE (or under one), every node of the file org-archive-location names, and denote files whose name carries the keyword archive. They remain in the Store, so links and backlinks to them work; in Stream and Discovery A shows or hides them (supertag-view-include-archived).

M-x supertag-discovery flips out a batch of notes with their full bodies instead; press s to search the whole vault, and a quote you pick can be inserted back into the note you started from.

When to review is up to you; Supertag does not schedule revision.

Getting started

;; Install with straight.el (this assumes you already use straight)
(straight-use-package '(textui :host github :repo "yibie/textui"))
(straight-use-package '(supertag :host github :repo "yibie/supertag"))
;; Set before require: Supertag installs its config guard when it loads.
(setq supertag-sync-directories '("~/Documents/notes/"))   ; where your Org files live
(require 'supertag)
(global-corfu-mode 1)   ; the completion UI for #tags; skip if it is already on

Requires Emacs 29.1. Everything Supertag needs is listed under Dependencies.

  1. Set the sync directory in init (before (require 'supertag); the file-level ID source is optional and can change any time), then run M-x supertag-sync-full-rescan once; template in doc/setup.md.
  2. M-x supertag-menu: a menu grouped into write, organize, find and maintain; look here when you cannot recall a command name.

No API key, no database server to run; your existing Org files work as they are.

Dependencies

Required. These are the packages in Supertag's Package-Requires:

Dependency Version Source Used for
Emacs 29.1 or newer
Org 9.6 or newer Built into Emacs 29.1 Your notes
ht 2.4 or newer MELPA Hash tables in the database
TextUI 0.9.0 or newer GitHub only Rendering Discovery and summary panels
Corfu 1.0 or newer GNU ELPA The completion UI for # tags
  • ht and Corfu come from package archives, so a package manager that reads Package-Requires installs them with Supertag. ht needs MELPA among your archives.
  • TextUI is in no package archive. Give your package manager its repository, as the straight recipe above does. With package-vc, install TextUI from its repository before you install or update Supertag.
  • Corfu has to be turned on with (global-corfu-mode 1). It shows a nested tag as its emacs › package › elpa path. Company completes tags too, but cannot display these paths.

Optional. Each is needed only for the feature beside it:

Feature Needs
Git backup and sync The git program
Similar notes curl and an embedding service: Ollama, or any OpenAI-compatible one (LM Studio, vLLM, llama.cpp)
At-point actions Embark; Supertag registers its actions when Embark loads
AI commands The superchat package, loaded before you run them
Summary panels and Stream agents Superchat or gptel; see supertag-summary-provider

Advanced features

Optional: Git backup and sync

Git can auto-commit and push Org text, Tag definitions (aliases and inheritance), and automation rules under your sync directory. Other machines pull and rebuild their own notes; a local commit is a version record, not a remote backup.

Portable metadata travels in .supertag-metadata.eld. The full database, machine-local paths, indexes, sync state, and other settings remain local — keep a separate database backup. On the first machine, M-x supertag-git-setup creates the repository; on the second, M-x supertag-git-clone clones and rebuilds; after that, M-x supertag-git-sync-mode turns on automatic sync (it is not persistent — enable it again after a restart, or put it in init). Manual sync is M-x supertag-git-sync-now. The full mechanics and configuration are in doc/sync.md.

Similar notes

An optional feature, off by default. It needs curl on the machine, an embedding service, and an embedding model ready on that service (bge-m3 by default). Two request formats are supported. Ollama (the default):

(setq supertag-semantic-endpoint "http://localhost:11434")
(setq supertag-semantic-model "bge-m3")

Any OpenAI-compatible /v1/embeddings service — LM Studio, vLLM, the llama.cpp server, or a hosted one:

(setq supertag-semantic-api 'openai)
(setq supertag-semantic-endpoint "http://localhost:1234/v1")  ; with or without /v1
(setq supertag-semantic-model "text-embedding-nomic-embed-text-v1.5")
;; Only for a service that wants a key; a function keeps it out of your config:
(setq supertag-semantic-api-key
      (lambda () (auth-source-pick-first-password :host "api.example.com")))

supertag-semantic-endpoint takes the root address; Supertag adds /api/embed or /v1/embeddings. A model that wants a task prefix gets it through supertag-semantic-input-format, for EmbeddingGemma "task: sentence similarity | query: %s". The similarity floor (supertag-semantic-min-similarity, 0.55) was tuned on bge-m3; models score on different scales, so another model needs its own floor (EmbeddingGemma 2 puts unrelated notes near 0.74, so about 0.82). Changing the model rebuilds the index.

Then M-x supertag-semantic-rebuild. It first asks whether to enable similar notes for future sessions; after you agree it probes the service and model, and only a successful probe writes that choice into your configuration — an unreachable service leaves nothing "enabled". It then indexes nodes in the background, and Node View shows a "Similar" candidate section. M-x supertag-semantic-status shows progress, M-x supertag-semantic-stop pauses, M-x supertag-semantic-resume continues; changing the model requires rebuilding the index.

Two things to keep in mind. On what is sent: each request to the service carries the title, the outline path and the beginning of the body (1500 characters by default); requests go to your local machine by default, and pointing the address at a remote service means sending that text to that machine — think twice before using a public or third-party service. On bounds: similar candidates are hints only; they never create links automatically and never rewrite your Org files.

Query

A query is an S-expression; it can live in an Org Babel block or a dynamic block, or run from the query entry in M-x supertag-menu. Day to day, the most common filter is by tag and TODO state:

#+BEGIN_SRC supertag-query-block :results raw
(and (tag "task") (todo "TODO"))
#+END_SRC

Combine conditions with and, or, not, and use (property "KEY" "value") for Org properties. The fuller operator set and composition rules are in doc/query.md.

Automation

Automation is rule-driven; the easiest way to make a rule is from a ready-made template:

  1. M-x supertag-automation-insert-template, then pick a template;
  2. fill in the parameters it asks for (e.g. which tag, which value to set);
  3. look at the preview, confirm, and it is created.

To see which templates exist first, use M-x supertag-automation-list-templates.

The engine runs by default, but it modifies no file without rules; when a rule runs, it writes back to the source Org file. The current triggers, conditions, actions and templates are in doc/automation.md.

Command list

Common commands grouped by purpose. Every row is a command you can invoke with M-x (org-capture is Org's own).

View entry commands remain globally available. Actions such as refresh, navigation, marking, editing, and quitting require an initialized instance of their own view. With Emacs's standard command-completion filtering, these local commands appear only in the appropriate context. Even if filtering is disabled or a command is called directly, invalid-context calls are rejected before prompts or changes.

Group Command Effect
Capture & organize org-capture Org's own command; record from a template, and with :supertag t finalize can add the ID (doc/setup.md)
Capture & organize supertag-menu task-grouped command menu; look here when you cannot recall a name
Capture & organize supertag-add-tag, supertag-remove-tag-from-node add a tag to a heading, remove one
Capture & organize supertag-promote turn the selection or the heading at point into a node via a creation template
Capture & organize supertag-move-node, supertag-move-node-and-link move a node to another file; the -and-link variant leaves a link behind
Capture & organize supertag-add-link, supertag-find-node insert a node link; find and jump to a node by title
Capture & organize supertag-tag-rename, supertag-delete-tag-everywhere rename a tag; delete a tag across the vault
Find & review supertag-view-node the node page: unlinked mentions, similar notes, and more
Find & review supertag-view-stream / supertag-view-stream-find the stream of every node / of any query; f narrows, u goes back
Find & review supertag-discovery flip out random notes; s searches the whole vault, and a picked quote can be inserted back
Find & review supertag-mention-mode mark known concept titles and aliases in the body as hints only
Query & automation supertag-add-query-block, supertag-query-build, supertag-query-describe-syntax insert a query block; assemble a query interactively; show the syntax reference
Query & automation supertag-automation-insert-template, supertag-automation-list-templates create a rule from a template; browse templates (doc/automation.md)
Maintain supertag-sync-full-rescan full rescan; run once after initial setup
Maintain supertag-semantic-rebuild, supertag-semantic-status, supertag-semantic-stop, supertag-semantic-resume similar notes (optional, off by default): rebuild the index, check status, pause, continue
Maintain supertag-migrate-status, supertag-migrate-preview migration status report; preview before retired fields are written back to Org (doc/migration.md)
Maintain supertag-git-setup, supertag-git-clone, supertag-git-sync-mode, supertag-git-sync-now Git backup and sync: create the repository / clone and rebuild / toggle auto-sync / sync now (doc/sync.md)

Customization list

The most-changed options, with defaults taken from the source; the full list by feature group is in doc/customization.md.

Option Default Effect
supertag-sync-directories nil directories to sync; nil means not configured yet — set before (require 'supertag) in init (the wizard is retired)
supertag-file-id-source 'auto file-level ID source: org-roam, supertag, denote, auto, disabled
supertag-sync-auto-interval 900 auto-sync interval (seconds)
supertag-sync-idle-delay 1.0 idle seconds before sync runs
supertag-db-backup-interval 86400 daily database backup interval (seconds); retention in supertag-db-backup-keep-days
supertag-git-sync-commit-debounce 30 Git auto-sync: quiet seconds before committing; pull interval in supertag-git-sync-pull-interval
supertag-org-capture-auto-enable nil org-capture integration; off by default, enable when needed
supertag-creation-templates nil creation presets shared by Add Link, Find Node and Promote; nil uses the built-in Concept preset
supertag-view-style-color-by-name t colour inline tags by name
supertag-view-node-side 'right which side the Node View side window takes
supertag-view-node-side-size 0.33 Node View side-window width ratio
supertag-discovery-initial-sample-size 10 random notes shown by Discovery
supertag-mention-max-results 300 maximum sources listed for unlinked mentions
supertag-semantic-enabled nil similar-notes switch; off by default, needs a working embedding service

Documentation

About

Implement a modern note-taking app style in Org-mode.

Topics

Resources

Contributing

Stars

378 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages