Chat about this codebase

AI-powered code exploration

Online

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 via org-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 with org-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

  1. Open (or create) an Org file, e.g. ~/org/biology.org:

    * Photosynthesis
      Process by which plants convert light energy into chemical energy.
    
  2. 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:
    
  3. (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:

  1. Narrow to the passage: C-x n n

  2. Select the region.

  3. 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 to org-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

  1. Fork the repo and create a feature branch (feature/… or fix/…).
  2. Commit small, focused changes with clear messages.
  3. Add or update ERT tests for new behavior.
  4. Ensure byte-compilation passes and interactive flows work.
  5. Push to GitHub and open a PR referencing relevant issue(s).

8. Example: Adding a New Scaling Function

  1. 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))))
    
  2. Register it in README.org’s “Customizing a-factor Scaling Functions” section.

  3. 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)))
    
  4. Byte-compile and verify:

    M-x byte-compile-file RET modules/algorithms.el  
    M-x ert RET org-inc-a-factor-custom-boundaries RET
    
  5. Commit, push branch, open PR.

With this workflow and conventions, you’ll streamline contributions and maintain code quality across org-inc.