Skip to content

Latest commit

 

History

History
689 lines (525 loc) · 25.6 KB

File metadata and controls

689 lines (525 loc) · 25.6 KB

A Day with Supertag — One Person’s Complete Workflow

1 How to Use This Document

This is not a feature list. This is one person’s real daily workflow with Supertag, documented in the style of Bernt Hansen’s legendary org-mode tutorial.

Every section shows:

  1. What I actually do
  2. The exact commands and Elisp I use
  3. Why I chose this way over alternatives

You can load this file in Emacs and tangle it with C-c C-v C-t to extract all the Elisp examples into supertag-workflow.el, then include it in your init.el.

This document assumes you have Supertag installed. See the README for installation.

中文版:Supertag 的一天(中文)

2 My Setup

2.1 My Org Files

I keep my life in a handful of Org files under ~/org/. Each file has a clear purpose, and Supertag treats them all as one unified knowledge base.

FilePurpose
inbox.orgCapture bucket — everything lands here first
projects.orgActive projects, each a level-1 heading
research.orgPapers, reading notes, literature reviews
meetings.orgMeeting notes with decisions and actions
journal.orgDaily journal entries, ideas, reflections

Why separate files? Because Supertag queries across all of them. The file division is for my brain — Supertag doesn’t care which file a heading lives in. A #task in meetings.org and a #task in projects.org appear side by side in the Table View.

2.2 Vault Configuration

I use a single vault for everything. If I wanted work/personal separation, I’d use:

;; Single vault (my setup)
(setq supertag-sync-directories '("~/org/"))

;; Multi-vault alternative — separate DBs for work and personal
;; (setq supertag-sync-directories '("~/org/work/" "~/org/personal/"))
;; (setq supertag-sync-directories-mode 'vaults)

2.3 Sync Configuration

I want sync to run automatically but not aggressively. 60-second intervals strike a good balance — I never wait long for new content to appear, and Emacs stays responsive.

;; Auto-sync every 60 seconds
(setq supertag-sync-directories '("~/org/"))
(setq supertag-auto-sync-interval 60)

;; Only do full validation every 10th tick (saves CPU)
(setq supertag-sync-maintenance-every-n-ticks 10)

;; Snapshot guard: if a directory is unavailable (network drive),
;; skip destructive operations instead of treating files as deleted
(setq supertag-sync-snapshot-guard t)

2.4 Tag Hierarchy — My Knowledge Schema

I’ve thought carefully about my tags. They form a hierarchy with inheritance — child tags automatically get the parent’s fields.

;; ── Top-level tags ──
;; #project   → has fields: status, priority, deadline, owner
;; #task      → extends nothing, has fields: status, priority, due, project
;; #paper     → has fields: authors, year, venue, status, rating, topic
;; #meeting   → has fields: date, participants, decisions, action-items
;; #idea      → has fields: status, feasibility, related-project
;; #person    → has fields: role, email, notes

I define these in the Schema View (M-x supertag-view-schema) — not in code. But here’s what the data structure looks like under the hood:

;; Example: registering a tag and its fields programmatically
;; (Normally done via Schema View UI — this is just to show the structure)

;; supertag-tag-create creates a tag
;; supertag-schema--add-field-at-point adds a field to a tag in the Schema View

;; #paper fields defined:
;;   authors  : text
;;   year     : number
;;   venue    : text
;;   status   : select → unread | reading | done
;;   rating   : number 1–5
;;   topic    : text

Why inheritance matters: If I later create a #paper/ai tag that extends #paper, it automatically gets authors, year, status, etc. I only need to add AI-specific fields like model or dataset.

3 Morning: Review and Plan (08:00–08:15)

3.1 Open the Table View for Today’s Tasks

I start every morning with one command: M-x supertag-view-table, choose tag task.

What I see: a spreadsheet-style view of all #task nodes across all my Org files. Columns: status, priority, due, project, plus any custom fields I’ve defined.

;; Key bindings I use in Table View:
;;   o           → jump to the heading in its Org file
;;   C-o         → jump to referenced node
;;   e           → edit current cell
;;   s           → sort by current column
;;   /           → filter rows
;;   TAB         → expand/collapse row details
;;   ?           → help (all keybindings)

3.2 Filter to What Matters

First thing I do: filter to status ! done=, sort by priority.

;; In the Table View:
;;   / → filter → status → != done
;;   s → sort → priority (ascending)

;; Equivalent from Elisp:
(supertag-search
 '(and (tag "task")
       (not (field "status" "done"))))

I scan the top 10 items. If anything is overdue (due before today), I either reschedule it or move it to the top of the list. Editing a cell takes one keystroke.

3.3 Capture Anything on My Mind

Sometimes during review I remember things. Instead of switching context, I capture:

;; M-x supertag-capture
;; Choose tag: task
;; Fill fields: title, status=todo, priority=medium
;; → Instantly appears in the table

Fifteen minutes, and I know exactly what I’m working on today.

4 Throughout the Day: Capture Without Breaking Flow

This is the biggest win of Supertag over plain Org-mode. Capture is fast and structured — I don’t need to remember field names or syntax.

4.1 Capture a Task Mid-Work

I’m deep in coding, a thought pops up: “need to update the API docs.” I don’t switch buffers. I don’t find the right file. I just:

  1. M-x supertag-capture
  2. Select tag task
  3. Type title: “Update API docs for v2.1”
  4. Set priority=high, project=backend
  5. C-c C-c → done. Back to coding. 8 seconds.

The task is in my inbox.org (my configured capture file) with all fields populated. It appears in the Table View automatically after the next sync cycle.

4.2 Capture a Meeting Note

In a meeting, I open my meetings.org and type:

* Weekly Standup 2025-06-12 #meeting
** Updates
   - Backend: API v2 deployed, monitoring looks good
   - Frontend: PR #234 under review
   - DevOps: CI pipeline speed improved by 30%
** Decisions
   - Move release date to June 20
   - Use PostgreSQL 16 for the new service
** Action Items
   - @alice: draft release notes
   - @bob: run load tests on staging

Supertag reads this and:

  1. Extracts the #meeting tag
  2. Uses the extractor pipeline to pull todo keywords, scheduled, etc.
  3. Makes it queryable alongside all other #meeting nodes

Later, I’ll add structured fields (date, participants, decisions) through the Node View. But during the meeting, I type naturally.

4.3 Automation: Let Rules Fill the Gaps

I’ve set up automation rules so I don’t have to manually populate every field. Here are the rules I rely on:

;; Rule 1: When a #meeting node is created, auto-set the date to today
(supertag-automation-create
 '(:name "auto-date-for-meetings"
   :trigger :on-node-create
   :condition (tag "meeting")
   :actions ((update-field "date" (format-time-string "%Y-%m-%d")))))

;; Rule 2: When a #task's status changes to "done", record the completion time
(supertag-automation-create
 '(:name "record-done-time"
   :trigger :on-field-changed
   :condition (and (tag "task")
                   (property-changed "status"))
   :actions ((when (equal (field-value "status") "done")
               (update-field "completed-at"
                             (format-time-string "%Y-%m-%d %H:%M"))))))

;; Rule 3: New #paper auto-sets status to "unread"
(supertag-automation-create
 '(:name "new-paper-unread"
   :trigger :on-node-create
   :condition (tag "paper")
   :actions ((update-field "status" "unread"))))

How to manage rules:

  • M-x supertag-view-table → choose tag → ?A (automations) → see all rules for this tag
  • Enable/disable rules without deleting them: supertag-automation-enable / disable
  • Dry-run a rule to test it: see doc/AUTOMATION-SYSTEM-GUIDE.md

Why automation matters: I define the logic once, and Supertag applies it every time. No more “oops, forgot to set the date on that meeting note.”

5 Working: Views That Feel Like Apps

5.1 Table View — My Primary Interface

I spend 60% of my Supertag time in the Table View. It behaves like a lightweight database client, but it’s all Emacs.

Things I do regularly:

ActionHow
Sort by any columns → pick column
Filter (e.g., status=active)/ → status → = active
Bulk edit (mark rows, set field)m to mark, then B to batch-edit
Add a new columnM-x supertag-view-table-add-column
Save this view as a named viewM-x supertag-view-table-save-current-view-as-named
Switch between named viewsM-x supertag-view-table-switch-view
Export to Org fileM-x supertag-search-export-results-to-file

Named views are a game-changer. I have:

  • today-tasks: #task, filtered to status ! done=, sorted by priority
  • reading-queue: #paper, filtered to status = unread, sorted by year desc
  • active-projects: #project, filtered to status = active
  • recent-meetings: #meeting, filtered to date > -7d=
;; Named views are stored in supertag--view-configs.
;; They can be saved to file and shared:
(supertag-view-config-save-to-file "~/org/supertag-views.el")
;; On another machine:
(supertag-view-config-load-from-file "~/org/supertag-views.el")

5.2 Kanban View — When I Need to See Flow

For #task and #project, the Table View is great for querying, but the Kanban is better for doing.

M-x supertag-view-kanban → choose tag task → columns by status

┌──────────┬──────────┬──────────┐
│  TODO    │  DOING   │   DONE   │
├──────────┼──────────┼──────────┤
│ Fix auth │ Rewrite  │ Deploy   │
│ bug      │ sync     │ v2.1     │
│ Update   │ layer    │          │
│ docs     │          │          │
└──────────┴──────────┴──────────┘

I drag tasks between columns as they progress. Supertag updates the status field automatically. If I have automation rules on status change (like recording completion time), they fire immediately.

5.3 Node View — Detailed Editing with Completion

When I need to fill in a single node’s fields in detail, I use the Node View:

M-x supertag-view-node

This opens a side panel showing every field for the current node, with:

  • Text fields: type freely
  • Select fields: choose from a dropdown
  • Number fields: validated input
  • Date fields: Org date picker
  • Reference fields: C-o to jump to referenced node

I use this for papers (filling authors, year, venue, abstract) and for meetings (adding participants, decisions post-meeting).

5.4 Virtual Columns — Computed Data Without Storage

Some information I want to see but don’t want to store. Virtual columns compute values on the fly.

;; Virtual column: "overdue" — true if due date is in the past and task isn't done
(supertag-virtual-column-register
 :name "overdue"
 :tag "task"
 :compute (lambda (node)
            (let ((due (plist-get node :due))
                  (status (plist-get (supertag-field-value node "task" "status"))))
              (and due
                   (not (equal status "done"))
                   (time-less-p (date-to-time due) (current-time))))))

;; Virtual column: "progress" — percentage of subtasks done
(supertag-virtual-column-register
 :name "progress"
 :tag "project"
 :compute (lambda (node)
            (let* ((subtasks (supertag-get-children node))
                   (total (length subtasks))
                   (done (cl-count-if (lambda (s) (equal "done" (plist-get s :status)))
                                      subtasks)))
              (if (> total 0) (round (* 100.0 (/ done total))) 0))))

Virtual columns appear in the Table View just like regular fields. The difference: they’re computed fresh every time you open the view — zero storage, always up to date.

See doc/VIRTUAL_COLUMNS.md for the full API.

6 Connecting Knowledge: References and Relations

6.1 Quick Reference: Link Two Ideas Together

I’m reading a paper and realize it’s directly relevant to a project. Instead of copy-pasting links, I use:

M-x supertag-add-reference

This writes one forward Org link in the current node. The target’s backlink is derived from that link, so the reference appears in both nodes’ Refs views without inserting reciprocal text into the target file.

;; The source Org [[link]] owns the reference.
;; Supertag projects it as a queryable :reference relation:
;;   1. The target file is never modified
;;   2. Backlinks are derived by querying relations-to
;;   3. It appears in the Table View Refs column
;;   4. C-o in Table View jumps to the referenced node

6.2 Schema Relationships — Parent-Child Tags

When I define a tag hierarchy (#paper/ai extends #paper), I’m creating a schema relationship. All #paper/ai nodes are also #paper nodes — they inherit fields and appear in #paper queries.

;; In Schema View (M-x supertag-view-schema):
;;   - Navigate to #paper/ai
;;   - M-x supertag-view-schema-set-extends → choose #paper
;;   - #paper/ai now inherits: authors, year, venue, status, rating, topic
;;   - Add AI-specific fields: model, dataset, metrics

Why this matters: I query #paper to see all papers. I query #paper/ai to see only AI papers. Both queries work because of inheritance.

6.3 The Knowledge Board — Visual Exploration

When I want to see how my notes connect spatially, I open the Board UI:

M-x supertag-board-open

This opens a web-based canvas (React Flow) in my browser. It shows:

  • Nodes as cards with title, tags, and fields
  • Edges as lines between related nodes, colored by relation type
  • Groups as visual containers for organized clusters

Features I use:

  • Click a tag on a card → expand to see field values
  • Expand card → see full note content with scroll
  • Drag nodes into groups for visual organization
  • Search bar at top (Ctrl+F) → highlight matching nodes, dim others
  • Layout button → auto-arrange nodes with Sugiyama algorithm
  • Double-click edge → edit relation label
  • Click × on edge → remove relation

The Board UI is best for exploration and sensemaking — when I’m trying to understand how ideas connect, not when I’m filling in data.

7 Evening: Review and Query (17:00–17:15)

7.1 Search for Today’s Decisions

At the end of the day, I want to see what I decided today. Structured search makes this trivial:

M-x supertag-search

;; Today's meetings
(supertag-search
 '(and (tag "meeting")
       (after "-1d")))

;; High-priority tasks still open
(supertag-search
 '(and (tag "task")
       (field "priority" "high")
       (not (field "status" "done"))))

;; Papers I read today (if I updated the status)
(supertag-search
 '(and (tag "paper")
       (field "status" "done")
       (after "-1d")))

I can save search results to a file:

M-x supertag-search-export-results-to-file → produces an Org file with all matching headings and their fields.

7.2 RAG: Ask Questions About My Notes

Sometimes I don’t know the right query. I just have a question. That’s where the RAG (Retrieval-Augmented Generation) feature shines:

M-x supertag-rag-ask

> What decisions did we make about the API architecture this month?

Supertag:
- Searches all #meeting nodes from the past month
- Finds relevant passages about API architecture
- Generates a structured answer with citations
- Displays it in a *Supertag RAG Answer* buffer

For this to work, you need an LLM provider configured:

;; Option A: OpenAI
(setq supertag-rag-provider
      (llm-make-openai "gpt-4o" :key "sk-..."))

;; Option B: Gemini (free tier available)
(setq supertag-rag-provider
      (llm-make-gemini "gemini-2.5-flash" :key "..."))

;; Option C: Ollama (fully local, no API key)
(setq supertag-rag-provider
      (llm-make-ollama "llama3.2" :host "localhost:11434"))

;; Option D: Set global default for all llm.el applications
(setq llm-chat-default-provider
      (llm-make-openai "gpt-4o" :key "sk-..."))

RAG has three modes:

  • :smart (default): searches notes first, falls back to general AI if nothing found
  • :rag-only: strictly local notes only
  • :general-only: skip search, ask AI directly

7.3 Custom Dashboard — My Evening Review View

Using the View Framework, I’ve built a custom dashboard that shows everything I care about in one buffer:

(supertag-view-define-from-config
 (list :id 'evening-review
       :name "Evening Review Dashboard"
       :tag "task"
       :widgets
       (list
        (list :type :section :title "✅ Tasks"
              :children
              (list
               (list :type :stats-row
                     :stats
                     (lambda (context)
                       (list (cons "Total"
                                   (length (plist-get context :nodes))))))))
        (list :type :toolbar
              :items '("M-x supertag-view-refresh" "q quit-window")))))

(supertag-view-select-and-render "task")

See doc/VIEW_FRAMEWORK_DEV_GUIDE.md for the full View Framework API.

8 Weekly: Maintenance and Refinement (Sunday, 30 min)

8.1 Sync Health Check

M-x supertag-sync-status shows me:

  • When the last sync ran
  • How many files are tracked
  • How many nodes are in the database
  • Whether any sync errors occurred

If anything looks off:

;; Rebuild Org projections from a complete snapshot
M-x supertag-reindex-org

;; This only reads your Org files.  Semantic Facts in the database
;; are preserved; restore them from backup if the DB itself was lost.

8.2 Schema Refinement

I review my tags in the Schema View (M-x supertag-view-schema) and ask:

  • Are there fields I never use? → Remove them
  • Are there fields I wish I had? → Add them
  • Should any tags be merged or split?
  • Is the inheritance hierarchy still right?

8.3 Database Backup

Supertag auto-saves snapshots daily (configurable):

(setq supertag-db-auto-save-interval 300)   ; auto-save every 5 minutes
(setq supertag-db-backup-interval 86400)    ; daily backup
(setq supertag-db-backup-keep-days 3)       ; keep 3 days of backups

Backups are stored in ~/.emacs.d/supertag/backups/.

8.4 Automation Review

I check whether my automation rules are still doing what I want:

  • M-x supertag-view-table → ? → A → see all automations for this tag
  • Disable rules that are causing noise
  • Add rules for new patterns I’ve noticed

9 My Complete Elisp Configuration

This section contains every Elisp setting referenced above, in one place. Tangle this file with C-c C-v C-t to produce supertag-workflow.el, then:

(load "~/path/to/supertag-workflow.el")
;;; supertag-workflow.el — My Supertag daily workflow configuration

;; ── Installation ──
;; (straight-use-package '(supertag :host github :repo "yibie/supertag"))

;; ── Sync ──
(setq supertag-sync-directories '("~/org/"))
(setq supertag-auto-sync-interval 60)
(setq supertag-sync-maintenance-every-n-ticks 10)
(setq supertag-sync-snapshot-guard t)

;; ── Persistence ──
(setq supertag-db-auto-save-interval 300)
(setq supertag-db-backup-interval 86400)
(setq supertag-db-backup-keep-days 3)

;; ── RAG (AI Queries) ──
;; Uncomment and configure ONE of these:
;; (setq supertag-rag-provider (llm-make-openai "gpt-4o" :key "sk-..."))
;; (setq supertag-rag-provider (llm-make-gemini "gemini-2.5-flash" :key "..."))
;; (setq supertag-rag-provider (llm-make-ollama "llama3.2" :host "localhost:11434"))

;; ── Automation Rules ──

;; Rule 1: Auto-set meeting date
(supertag-automation-create
 '(:name "auto-date-for-meetings"
   :trigger :on-node-create
   :condition (tag "meeting")
   :actions ((update-field "date" (format-time-string "%Y-%m-%d")))))

;; Rule 2: Record task completion time
(supertag-automation-create
 '(:name "record-done-time"
   :trigger :on-field-changed
   :condition (and (tag "task") (property-changed "status"))
   :actions ((when (equal (field-value "status") "done")
               (update-field "completed-at" (format-time-string "%Y-%m-%d %H:%M"))))))

;; Rule 3: New papers default to unread
(supertag-automation-create
 '(:name "new-paper-unread"
   :trigger :on-node-create
   :condition (tag "paper")
   :actions ((update-field "status" "unread"))))

;; ── Virtual Columns ──
(supertag-virtual-column-register
 :name "overdue"
 :tag "task"
 :compute (lambda (node)
            (let ((due (plist-get node :due))
                  (status (plist-get (supertag-field-value node "task" "status"))))
              (and due
                   (not (equal status "done"))
                   (time-less-p (date-to-time due) (current-time))))))

(provide 'supertag-workflow)
;;; supertag-workflow.el ends here

10 Command Quick Reference

This is my most-used commands, not the full list. For the complete reference, see the README.

CommandI use it for…Frequency
M-x supertag-view-tableMorning review, paper queue, project overviewDaily
M-x supertag-captureQuick task/idea capture without leaving flowDaily
M-x supertag-searchFinding things across all filesDaily
M-x supertag-view-nodeDetailed editing of one node’s fieldsWeekly
M-x supertag-view-kanbanDragging tasks through workflowDaily
M-x supertag-view-schemaAdding/removing fields, tag hierarchyWeekly
M-x supertag-add-referenceLinking two related ideasDaily
M-x supertag-add-tagTagging a heading for the first timeDaily
M-x supertag-rag-ask“What did I decide about X?”Weekly
M-x supertag-board-openVisual knowledge explorationWeekly
M-x supertag-sync-statusHealth checkWeekly
M-x supertag-reindex-orgRebuild Org projectionsMonthly
M-x supertag-sync-cleanup-databaseFix inconsistenciesAs needed

11 Key Bindings I Actually Use

(global-set-key (kbd "C-c t") 'supertag-view-table)
(global-set-key (kbd "C-c k") 'supertag-view-kanban)
(global-set-key (kbd "C-c c") 'supertag-capture)
(global-set-key (kbd "C-c s") 'supertag-search)
(global-set-key (kbd "C-c r") 'supertag-add-reference)
(global-set-key (kbd "C-c g") 'supertag-add-tag)

12 Things I Tried and Don’t Use (Anymore)

I document what I stopped using so others don’t waste time:

  • supertag-sync-directories-mode 'unified with 10+ directories → switched to vault mode. Too slow scanning everything every tick.
  • Automation rule with :on-store-changed trigger → too noisy. Switched to specific triggers (:on-field-changed, :on-node-create).
  • Manual sync only → missed too many updates. Auto-sync with 60s interval is the sweet spot.
  • Trying to define all fields upfront in Schema View → better to add fields as you discover you need them.

13 Further Reading