Project Overview
Org-Inc brings SuperMemo-style incremental learning directly into Org-mode. It turns your Org headings into reviewable topics, schedules spaced repetitions, and overlays reminders—all without leaving your notes.
Value Proposition
- Seamless integration: Work within Org-mode, no external apps or exports.
- Incremental mastery: Apply proven spaced-repetition algorithms to any heading.
- Lightweight cache: Store per-topic metadata in
org-inc-directory
. - Visual cues: Overlay mode highlights upcoming reviews in your buffer.
- Flexible workflows: Create, continue, extract, prioritize, or dismiss topics on demand.
Key Features
- Topic Creation (
org-inc-create
)
Convert any heading into a scheduled review topic. - Review Sessions (
org-inc-continue
)
Walk through due topics in order of priority. - Cloze Extraction (
org-inc-extract
)
Generate fill-in-the-blank quizzes from headings or lines. - Overlay Reminders (
org-inc-overlay-mode
)
Highlight headings with pending reviews or overdue topics. - Priority Management (
org-inc-priority
)
Adjust review weight to focus on difficult topics. - Dismissal (
org-inc-dismiss
)
Remove topics from future sessions without deleting notes. - Custom Algorithms
Swap or advise built-in scheduling functions viaorg-inc-algorithm
.
Typical Use-Cases
- Student Notes
Schedule regular reviews of lecture summaries, formulas, or definitions. - API Learning
Incrementally master library functions by embedding usage examples in Org. - Language Acquisition
Create vocabulary topics withorg-inc-extract
for active recall quizzes. - Long-Term Projects
Track and revisit design decisions, TODO checklists, or research findings. - Team Knowledge Base
Ensure collective memory by scheduling shared documentation reviews.
Quick Start Example
Add to your Emacs config:
(use-package org-inc
:after org
:hook (org-mode . org-inc-overlay-mode)
:bind (:map org-mode-map
("C-M-<return>" . org-inc-create)
("C-c i c" . org-inc-continue)
("C-c i e" . org-inc-extract))
:custom
(org-inc-directory (expand-file-name "org-inc/" org-directory))
(org-inc-default-interval "1d"))
Restart Emacs or evaluate the snippet.
Open an Org file, place the cursor on a heading, and press C-M-<return>
to schedule your first topic.
Getting Started
Follow these steps to install Org-inc, mark up your first topic, and run a review session in under five minutes.
Installation
Install from MELPA via package.el or use-package.
;; init.el
;; 1. Enable MELPA archive
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
;; 2. Install Org-inc if needed
(unless (package-installed-p 'org-inc)
(package-refresh-contents)
(package-install 'org-inc))
Or with use-package:
(use-package org-inc
:ensure t
:after org
:config
;; Optional: adjust default extraction
(setq org-inc-default-extraction-method 'subtree))
Configuration
Bind the most-used commands in org-mode
:
(with-eval-after-load 'org
(define-key org-mode-map (kbd "C-c i c") #'org-inc-create)
(define-key org-mode-map (kbd "C-c i n") #'org-inc-continue)
(define-key org-mode-map (kbd "C-c i e") #'org-inc-extract)
(define-key org-mode-map (kbd "C-c i d") #'org-inc-dismiss)
(define-key org-mode-map (kbd "C-c i a") #'org-inc-abort))
Creating Your First Topic
Open (or create) an Org file, e.g.
~/org/biology.org
:* Photosynthesis Process by which plants convert light energy into chemical energy.
Place point on the heading and run:
M-x org-inc-create
Org-inc adds SRS properties under the heading:
* Photosynthesis :PROPERTIES: :INC_CREATED: [2025-08-04 Mon 12:00] :INC_LAST-REVIEW:[2025-08-04 Mon 12:00] :INC_INTERVAL: 1d :END:
(Optional) Raise priority so it surfaces sooner:
M-x org-inc-priority RET 5 RET
Starting a Review Session
Invoke the core review loop:
M-x org-inc-continue
;; or use your keybinding, e.g. C-c i n
Org-inc jumps to the next due topic or quiz item. Follow the prompts until no items remain.
Navigating and Rating
Read each topic in your buffer.
When a ratable flashcard appears, press 1–5 to rate recall quality.
To skip an irrelevant item forever:
M-x org-inc-dismiss
To abort and leave remaining items for later:
M-x org-inc-abort
Extracting Sub-items
Turn a passage into a new sub-topic or quiz item:
Narrow to the passage:
C-x n n
Select the region.
Run:
M-x org-inc-extract
Org-inc creates a child heading, initializes its SRS properties, and schedules it for review.
Checking Pending Items
Outside of a session, view all due items:
M-x org-srs-list-due-items
Now you’re set. Create, prioritize, review—and let Org-inc handle your spaced-repetition schedule.
Core Concepts
Org-Inc builds a spaced-repetition layer on top of Org-mode. It treats Org headings as “items” with attached SRS metadata (due timestamps, priorities, A-factors, review logs), schedules them via a SuperMemo-style algorithm, caches priority scans for speed, and visualizes status with overlays. Understanding these core abstractions clarifies what each Org-Inc command manipulates.
Items: Org Headings ↔ SRS Entries
- Each Org heading becomes an Org-Inc item with properties:
•
:id
– unique identifier
•:due
– next review timestamp
•:prio
– priority (0.0–1.0 float)
•:log
– review history in a LOG drawer - API
•(org-inc-entry-items)
→ list of item plists under current subtree
•(org-inc-item-with-current ITEM …)
→ bind ITEM toorg-inc--current-item
•(org-inc-item-get :due)
/:prio
/:id
Example: list due timestamps for items in this heading
(dolist (item (org-inc-entry-items))
(org-inc-item-with-current item
(message "ID=%s due=%s"
(org-inc-item-get :id)
(org-inc-item-get :due))))
Priority Model
- Represent priorities as floats in [0.0–1.0], stored in headline tags “[#0.75]”
- Internally pack floats into big-endian u64 for lexicographic sorting
- Key functions
•(org-inc-priority)
read float at point
•(org-inc-priority-set FLOAT)
insert/update “[#FLOAT]”
•(org-inc-priority-next CUR)
next higher existing priority
•(org-inc-priority-previous)
next lower existing priority
•(org-inc-priority-balance)
evenly redistribute all priorities
Example: bump current heading halfway toward next higher priority
(let ((cur (org-inc-priority))
(nxt (org-inc-priority-next (org-inc-priority))))
(when nxt
(org-inc-priority-set
(org-inc-priority-between cur nxt))))
Review Scheduling Algorithm
Org-Inc computes intervals and adjusts priorities after each review:
(org-inc-algorithm-next-interval PREV-INTERVAL QUALITY A-FACTOR)
(org-inc-algorithm-scale-priority CUR-PRIO QUALITY)
A typical review session uses these to update an item’s :due
and :prio
, then logs the action:
(org-inc-item-with-current item
(let* ((prev-iv (org-inc-item-get :last-interval))
(quality 0.7)
(a-factor (org-inc-item-get :a-factor))
(next-iv (org-inc-algorithm-next-interval prev-iv quality a-factor))
(new-prio (org-inc-algorithm-scale-priority (org-inc-item-get :prio) quality)))
(org-inc-item-update
:last-interval next-iv
:due (org-inc-timestamp-add (org-inc-item-get :due) next-iv)
:prio new-prio)
(org-inc-log-new-record :quality quality)))
Caching Layer
Scanning large Org files for priorities can be slow. org-inc-cache-mode
keeps a buffer-local hash of (PRIORITY . MARKER)
pairs.
- Enable per buffer:
(add-hook 'org-mode-hook #'org-inc-cache-mode)
- Cache updates automatically on edits; clear manually with
M-: (org-inc-priority-cache-clear)
(org-inc-priorities)
reads from cache when enabled
Overlay Visualization
org-inc-overlay-mode
uses overlays to show due dates and priorities inline:
- Toggle mode:
(org-inc-overlay-mode 1)
- Refresh all overlays after bulk changes:
(org-inc-overlay-refresh)
- Faces to customize:
org-inc-overlay-priority-face
,org-inc-overlay-due-face
Topic Extraction & Review
Topics let you lift arbitrary Org text into dedicated review items:
M-x org-inc-extract
on a selected region creates a child heading with SRS fields and replaces the region with@@inc:[[ID][…]]@@
M-x org-inc-extract
on an existing link jumps to the topic; with prefix (C-u
) it deletes the topic and restores text- Internals:
•org-inc-extract-1
– core implementation
•org-inc-transform
– reparent or rebalance after extracting in mid-review
Example: bind a key for quick extraction
(define-key org-mode-map (kbd "C-c x") #'org-inc-extract)
By thinking in terms of items (headings+metadata), priority scales, review algorithms, caches, overlays, and topic extracts, you’ll understand how each Org-Inc command reads, updates, or displays your spaced-repetition data in Org files.
Daily Workflow & Commands
A task-oriented guide to common Org-inc operations: starting reviews, managing items, adjusting priorities, visualizing overlays, and extracting topics. Use these commands and keybindings in your daily Org mode workflows.
Starting or Continuing a Review
Resume an in-progress review or start a new one covering both topics and items.
Interactive Usage
• M-x org-inc-continue
• No prefix: resumes last review or begins new session.
• C-u M-x org-inc-continue: always prompts for a fresh session.
Lisp Usage
;; Behave like no-prefix interactive call
(org-inc-continue)
;; Resume a specific item
(org-inc-continue '("notes.org" 42 :topic))
Keybinding Example
(define-key org-mode-map (kbd "C-c r") #'org-inc-continue)
Practical Tips
• Quit with q
to pause; next org-inc-continue
picks up where you left off.
• Use prefix (C-u) to clear context and select a different directory or strategy.
Dismissing and Postponing Items
Mark items as done or defer their review.
Dismiss an item after satisfactory review:
• M-x org-inc-dismiss
• Lisp: (org-inc-dismiss ITEM &optional SCORE)
where SCORE ∈ 0..1
Postpone an item to a later date:
• M-x org-inc-postpone
• Prefix numeric argument (e.g. C-u 3) to postpone by N days.
• Lisp: (org-inc-postpone ITEM DAYS)
Examples
;; Dismiss current review item with default score
(org-inc-dismiss (org-srs-review-item))
;; Postpone by 5 days
(org-inc-postpone (org-srs-review-item) 5)
Navigating and Listing Entry Items
Retrieve all Org-inc items under the current heading.
Interactive Listing
• M-x org-inc-entry-items
• Displays (ITEM . PROPS)
alist in the echo area.
Programmatic Access
;; Get all items in subtree
(let ((items (org-inc-entry-items)))
(dolist (itm items)
(message "ID: %s, Due: %s"
(plist-get (cdr itm) :id)
(plist-get (cdr itm) :scheduled))))
Adjusting Priorities
Set, query, and rebalance relative priorities within a subtree.
Set a new priority for the current item:
• M-x org-inc-priority-set
• Lisp: (org-inc-priority-set VALUE)
where VALUE ∈ [0.0 – 1.0]
Quick commands
• M-x org-inc-priority-increase / org-inc-priority-decrease
• M-x org-inc-priority-next / org-inc-priority-prev
Rebalance all priorities in region or file:
• M-x org-inc-priority-balance
Examples
;; Bind keys for stepping through priorities
(define-key org-mode-map (kbd "C-c p >") #'org-inc-priority-increase)
(define-key org-mode-map (kbd "C-c p <") #'org-inc-priority-decrease)
;; Set a fixed middle priority
(org-inc-priority-set 0.5)
;; Rebalance priorities in current subtree
(save-excursion
(org-back-to-heading)
(let ((beg (point))
(end (progn (org-end-of-subtree) (point))))
(org-inc-priority-balance beg end)))
Managing Overlays
Visualize priorities and extracted content inline.
Toggle overlays on/off
• M-x org-inc-overlay-mode
Refresh overlays manually
• M-x org-inc-priority-update-overlays
• M-x org-inc-overlay-text-update-overlays
Example Keybindings
;; Toggle overlays with C-c o
(define-key org-mode-map (kbd "C-c o") #'org-inc-overlay-mode)
;; Refresh overlays after bulk edits
(advice-add #'org-inc-priority-balance :after
(lambda (&rest _) (org-inc-priority-update-overlays)))
Extracting and Transforming Topics
Turn regions into standalone “topic” entries or convert existing topics.
Extract a region as a topic (with cloze embed):
• Select region → M-x org-inc-extract → choose “topic”
Jump to or delete an extraction:
• Point on embed → M-x org-inc-extract (no prefix: jump; C-u: delete)
Transform item types
• M-x org-inc-transform
• Prompts for target type (e.g. cloze
, topic
, item
)
Example
;; Bind extraction to C-c e
(define-key org-mode-map (kbd "C-c e") #'org-inc-extract)
;; Programmatic transform of current item to cloze
(org-inc-transform 'cloze)
Example Daily Workflow Keymap
Bind core commands for quick access in Org mode:
(with-eval-after-load 'org
(define-key org-mode-map (kbd "C-c r") #'org-inc-continue)
(define-key org-mode-map (kbd "C-c d") #'org-inc-dismiss)
(define-key org-mode-map (kbd "C-c t") #'org-inc-postpone)
(define-key org-mode-map (kbd "C-c p") #'org-inc-priority-set)
(define-key org-mode-map (kbd "C-c o") #'org-inc-overlay-mode)
(define-key org-mode-map (kbd "C-c e") #'org-inc-extract))
## Customisation & Advanced Usage
This section shows power users how to tweak Org-Inc internals and integrate it into larger workflows.
### 1. Adjusting SuperMemo Parameters
Override or advise core functions to reshape your review curve.
#### Override a-factor adjustment
By default `org-inc-a-factor-review` applies a fixed formula after each review. To apply your own:
```elisp
(defun my-org-inc-a-factor-review (old-a)
"Custom a-factor update: add a small bonus for late reviews."
(let ((base (org-inc-a-factor-review old-a)))
(if (> (float-time (time-subtract (current-time)
(org-entry-get (point) "LAST_REVIEW" t)))
(* 2 24 60 60))
(+ base 0.1)
base)))
(advice-add 'org-inc-a-factor-review :override #'my-org-inc-a-factor-review)
Remap priority scaling
org-inc-priority-scale
controls how interval changes affect priority. Apply a logarithmic curve:
(defun my-org-inc-priority-scale (ratio)
"Dampen extreme ratio changes via a log scale."
(log (+ 1 ratio) 2))
(advice-add 'org-inc-priority-scale :override #'my-org-inc-priority-scale)
2. Custom Cache Hooks & Bulk Updates
Extend org-inc-cache-mode
to batch-invalidate on multi-file edits.
Bulk-clear cache after external sync
(defun my-org-inc-bulk-clear-caches ()
"Clear Org-Inc caches in all open Org buffers."
(dolist (buf (buffer-list))
(with-current-buffer buf
(when (bound-and-true-p org-inc-cache-mode)
(org-inc-priority-cache-clear)))))
;; Run after a git pull or external sync
(add-hook 'after-save-hook #'my-org-inc-bulk-clear-caches)
Conditional caching
Skip caching for very small buffers:
(defun my-org-inc-cache-mode-maybe ()
"Enable org-inc-cache-mode only in large Org buffers."
(when (> (count-lines (point-min) (point-max)) 500)
(org-inc-cache-mode 1)))
(add-hook 'org-mode-hook #'my-org-inc-cache-mode-maybe)
3. Advanced Overlay Customization
Tweak org-inc-overlay-mode
to integrate with other visual tools.
Custom overlay format
(defun my-org-inc-format-priority (pct)
"Display PCT in parentheses with a star."
(format "(★ %.1f%% ★)" (* pct 100)))
(advice-add
'org-inc-priority-put-overlays :around
(lambda (orig &rest args)
(cl-letf (((symbol-function 'format) #'my-org-inc-format-priority))
(apply orig args))))
Highlight overdue items
Overlay overdue repeat entries in red:
(defun my-org-inc-highlight-overdue ()
"Apply `face-remapping-alist` to overdue Org-Inc entries."
(save-excursion
(goto-char (point-min))
(while (re-search-forward org-regexp-repeat nil t)
(let ((ts (match-string 0)))
(when (org-time< (org-read-date nil t ts) (current-time))
(let ((ov (make-overlay (match-beginning 0) (match-end 0))))
(overlay-put ov 'face '(:foreground "red"))))))))
(add-hook 'org-inc-review-after-evaluate-hook #'my-org-inc-highlight-overdue)
4. Priority Management & Navigation
Use org-inc-priority.el
functions in scripts or keymaps.
Batch-set and rebalance
(defun my-org-inc-balance-priorities ()
"Normalize all priorities in current buffer to sum to 1."
(interactive)
(let* ((all (org-inc-priorities))
(total (apply #'+ (mapcar #'cdr all))))
(dolist (pair all)
(let ((marker (car pair))
(val (/ (cdr pair) total)))
(with-current-buffer (marker-buffer marker)
(save-excursion
(goto-char marker)
(org-inc-priority-set val)))))
(org-inc-priority-update-overlays)))
Bind it for quick use:
(define-key org-mode-map (kbd "C-c i b") #'my-org-inc-balance-priorities)
Jump to next high-priority
(defun my-org-inc-goto-next-top (threshold)
"Jump to next Org-Inc entry with priority ≥ THRESHOLD."
(interactive "nMin priority (0–1): ")
(let ((pts (seq-filter (lambda (pair) (>= (cdr pair) threshold))
(org-inc-priorities))))
(when pts
(goto-char (car (car pts))))))
5. Batch Rescheduling & Integration
Automate rescheduling across your entire Org directory.
(defun my-org-inc-reschedule-all ()
"Run a full review pass and update `REPEAT` timestamps."
(interactive)
(org-map-entries
(lambda ()
(let ((res (org-srs-algorithm-repeat
(org-element-property :TYPE (org-element-at-point))
(org-inc--collect-args))))
(when (alist-get 'timestamp res)
(org-schedule nil (alist-get 'timestamp res)))))
nil ;; all entries
'file))
;; Run nightly at 2am
(run-at-time "02:00" (* 24 60 60) #'my-org-inc-reschedule-all)
With these patterns, you can adapt Org-Inc’s core behavior to your workflows, embed it in automated scripts, and maintain performance at scale.
Contributor Guide
This guide covers setting up a development environment, navigating the codebase, following coding conventions, running tests, and submitting patches for org-inc.
Repository Layout
• org-inc.el
– Entry point: loads modules, sets up autoloads and hooks.
• modules/
– algorithms.el Core scheduling and a-factor logic
– caching.el Internal cache for due items
– items.el Data structures and CRUD for review items
– overlays.el Inline prompts and overlays in Org buffers
– priorities.el Priority management API
– reviews.el Review scheduling and interval updates
– topics.el Topic creation, metadata and Org integrations
• tests/
– *.el ERT tests for core functions (if present)
• README.org User-facing documentation
• CONTRIBUTING.md (this file)
1. Setup
1.1 Clone and Install
git clone https://github.com/bohonghuang/org-inc.git
cd org-inc
;; Add to your Emacs load-path:
(add-to-list 'load-path "/path/to/org-inc")
1.2 Dev Dependencies
• Emacs 27+ with lexical-binding
• Org-mode (built-in)
• Optional: use-package for local testing
2. Loading for Development
Place in your init.el:
;; Load core package
(add-to-list 'load-path "/path/to/org-inc")
(require 'org-inc)
;; Enable overlay & cache modes in Org buffers
(add-hook 'org-mode-hook #'org-inc-overlay-mode)
(add-hook 'org-mode-hook #'org-inc-cache-mode)
Restart Emacs or evaluate buffer to pick up changes.
3. Interactive Testing
• M-x org-inc-continue
– Walk through due items in current Org buffers.
• M-x org-inc-create / org-inc-extract / org-inc-dismiss
– Test creation, extraction and dismissal flows.
• Toggle breakpoints or insert (message …) calls in modules to inspect behavior.
4. Automated Tests
If tests/ contains ERT suites:
;; In Emacs:
M-x load-directory RET /path/to/org-inc/tests RET
M-x ert RET t RET
Add new tests in tests/*.el following ERT conventions:
(ert-deftest org-inc-algo-test-a-factor-review ()
(should (= (org-inc-a-factor-review 2.0) 2.16)))
5. Coding Conventions
• Prefix all symbols with org-inc-
.
• Use lexical-binding; include -*- lexical-binding: t -*-
at top of new files.
• Add autoload cookies ;;;###autoload
on interactive commands.
• Document public functions with a one-line docstring followed by :tangle:
if needed.
• Byte-compile without warnings:
M-x byte-compile-file RET org-inc.el RET
6. Documentation
• Update examples in README.org when APIs change.
• Regenerate README.md
(if applicable) by exporting Org to Markdown:
M-x org-md-export-to-markdown RET
7. Pull Request Workflow
- Fork the repo and create a feature branch (
feature/…
orfix/…
). - Commit small, focused changes with clear messages.
- Add or update ERT tests for new behavior.
- Ensure byte-compilation passes and interactive flows work.
- Push to GitHub and open a PR referencing relevant issue(s).
8. Example: Adding a New Scaling Function
In modules/algorithms.el, define:
;;;###autoload (defun org-inc-a-factor-custom (x) "Custom a-factor adjustment: sqrt model." (max 1.2 (min 6.9 (sqrt x))))
Register it in README.org’s “Customizing a-factor Scaling Functions” section.
Add an ERT test in tests/algorithms-test.el:
(ert-deftest org-inc-a-factor-custom-boundaries () (should (= (org-inc-a-factor-custom 0.5) 1.2)) (should (= (org-inc-a-factor-custom 49) 6.9)))
Byte-compile and verify:
M-x byte-compile-file RET modules/algorithms.el M-x ert RET org-inc-a-factor-custom-boundaries RET
Commit, push branch, open PR.
With this workflow and conventions, you’ll streamline contributions and maintain code quality across org-inc.