bohonghuang/org-srs

A feature-rich and flexible spaced repetition system inside Org-mode

125

stars

226

commits

Emacs Lisp

primary language

Jun 28, 2026

updated

README

#+TITLE: Org-srs

[[https://melpa.org/#/org-srs][file:https://melpa.org/packages/org-srs-badge.svg]]

Org Spaced Repetition System
* Introduction
Org-srs is a feature-rich and extensible spaced repetition system
integrated within Org-mode, allowing you to learn and review knowledge
without leaving your Org workflow.
* Features
- *Everything in Org* \\
  All data in Org-srs, including review histories and customizable
  options, are stored as plain text in your Org files. This makes
  version control easy, and by simply syncing your Org files, you can
  review seamlessly across different devices (especially the native
  Emacs on Android).
- *Powerful* \\
  Org-srs integrates the modern FSRS algorithm out of the box to help
  you review more efficiently and effectively. You can also optimize
  the parameters based on the content and your review habits. Org-srs
  also includes various advanced scheduling features such as fuzzing,
  stepped learning, and auto-burying, all with customizable
  parameters.
- *Performant* \\
  Org-srs supports enabling caching for a review session to
  significantly improve its performance in a large review collection
  with 10K+ items, at the cost of some flexibility (such as creating
  items on the fly).
- *Flexible* \\
  In Org-srs, the smallest review unit is an "item" (similar to a card
  in Anki). A content piece reviewed through one or more items is
  called an "entry" (similar to a note in Anki). An item can be a
  flashcard with a front (question) and back (answer), a cloze
  deletion, etc. This means an entry can hold different types of items
  to meet various review needs. For example, you can review the same
  content using both flashcards and cloze deletions simultaneously if
  needed. Moreover, various customizable options provided by Org-srs
  can be finely controlled, allowing you to set different values for
  the same customizable option at the global, directory, file, entry,
  or item level to suit your review preferences.
- *Embeddable* \\
  If you're reviewing your own notes, maintaining additional entries
  for review can be tedious. If you modify your notes or add, delete,
  or modify cloze deletions, manually updating the created review
  entries can be a nightmare. Org-srs supports non-invasive embedding
  of review entries into your notes. This means that whenever you
  change the content of your notes, you can update the exported entry
  with one command, without polluting the export of your Org files.
- *Extensible* \\
  Org-srs is designed with high modularity. By virtue of generic
  functions and hooks, algorithms, scheduling features, item types,
  and review strategies can be extended externally as you need.
- *Statistics Visualization* \\
  Org-srs allows you to view review history (e.g., number of reviews
  per day, retention rate) and the number of items scheduled for
  review on future dates through charts.
- *Touchscreen/Mouse Support* \\
  Org-srs supports displaying GUI buttons via child frames to enable
  complete review via mouse or touchscreen, perfectly adapting to
  native Emacs on Android, allowing you to review out of your phone on
  the go.
* Installation
Org-srs is now available on [[https://melpa.org/#/org-srs][MELPA]]. Below is an example configuration
with ~use-package~:

#+BEGIN_SRC emacs-lisp
  (use-package org-srs
    :ensure t
    :defer t
    :hook (org-mode . org-srs-embed-overlay-mode)
    :bind (:map org-mode-map
           ("<f5>" . org-srs-review-rate-easy)
           ("<f6>" . org-srs-review-rate-good)
           ("<f7>" . org-srs-review-rate-hard)
           ("<f8>" . org-srs-review-rate-again)))

  (use-package org-srs
    :when (eq system-type 'android)
    :ensure t
    :defer t
    :custom
    (org-srs-item-confirm #'org-srs-item-confirm-command)
    :config
    (org-srs-ui-mode +1))
#+END_SRC
* Usage
Here are some demonstrations and descriptions for the main features of
Org-srs. You can also open file [[https://github.com/bohonghuang/org-srs/blob/doc/org-srs-example.org][org-srs-example.org]] in Emacs and
execute command ~org-srs-review-start~ to start an example review
session right out of the box.
** Flashcards
[[https://github.com/user-attachments/assets/eaafff3c-6463-438d-8780-9cd4c17826cd][Demo]]

A basic form of review that you can see in most spaced repetition
software. It consists of a card's front (question) and back (answer).
You can easily create a flashcard by using ~org-srs-item-create~ in an
entry and selecting ~card~. There are multiple supported formats for the
front and back of a flashcard:

- *File-level flashcards* \\
  #+BEGIN_SRC org
    # Card 1
    ,#+TITLE: The card front
    The card back
  #+END_SRC

  #+BEGIN_SRC org
    ,#+TITLE: Card 2
    The card front
    ,* Back
    The card back
  #+END_SRC

  #+BEGIN_SRC org
    ,#+TITLE: Card 3
    ,* Front
    The card front
    ,* Back
    The card back
  #+END_SRC
- *Heading-level flashcards* \\
  #+BEGIN_SRC org
    # Card 1
    ,* The card front
    The card back
  #+END_SRC

  #+BEGIN_SRC org
    ,* Card 2
    The card front
    ,** Back
    The card back
  #+END_SRC

  #+BEGIN_SRC org
    ,* Card 3
    ,** Front
    The card front
    ,** Back
    The card back
  #+END_SRC
** Cloze Deletion
[[https://github.com/user-attachments/assets/176fb6ef-87a2-42b9-ad4e-7639b6371254][Demo]]

This feature allows you to cloze any content you want to review (such
as a word, a list item, or a table field) and hide it during the
review process. There are two ways to create a cloze item:
1) Select the content you want to cloze, execute the
   ~org-srs-item-create~ command, and then select ~cloze~.
2) Use ~org-srs-item-cloze-dwim~ for context-sensitive cloze creation
   (note that you can use ~org-srs-item-uncloze-dwim~ to undo the
   cloze). Afterward, you need to manually execute
   ~org-srs-item-cloze-update~ to create the corresponding items for all
   cloze deletions at once.

By default, each cloze deletion’s ID is the first 7 characters of the
SHA-1 hash of its content. This means you can freely insert, delete,
swap, or modify them. However, it is recommended to execute
~org-srs-item-cloze-update~ after each modification to ensure that the
changes of clozes are always tracked by Org-srs.

The syntax for a cloze deletion is as follows:

#+BEGIN_SRC org
  {{<cloze-id>}{<content>}{<hint>}}
#+END_SRC
** Embedding
[[https://github.com/user-attachments/assets/5e55a3ff-c1eb-48b6-9f56-5c15c012fc63][Demo]]

A good part of Org-srs is the ability to export content from within
your notes that you want to review. After modifying your notes, you
can directly update the corresponding entry in your notes. The main
command for this feature is the context-sensitive ~org-srs-embed-dwim~,
whose logic is as follows:
1. If point is on an element without a corresponding exported entry,
   that element will be exported as the content of the entry. If the
   exported element contains clozes, corresponding items will
   automatically be created; otherwise, the content will be exported
   as the back of a flashcard. You will need to fill in the entry’s
   title in the pop-up buffer. The default export path is the current
   Org file's relative path to ~org-directory~ under the =org-srs=
   directory in ~org-directory~. For example, if your ~org-directory~ is
   =~/org= and the current file is =~/org/foo/bar.org=, the file where the
   entry is exported will be =~/org/org-srs/foo/bar.org=.
2. If point is on an element that already has a corresponding exported
   entry, the exported entry will be updated with the current
   element's content.
3. If point is on a marker (shown as =#+SRS= when
   ~org-srs-embed-overlay-mode~ is on) representing an embedded Org-srs
   entry, it will jump to the corresponding exported entry.

Additionally, if you need to cloze or uncloze the content to be
exported, you can use ~org-srs-embed-cloze-dwim~ and
~org-srs-embed-uncloze-dwim~.
* Configuration
See the ~org-srs~ customization group, where all the customizable
variables are documented.
** Per-directory Configuration
#+BEGIN_SRC emacs-lisp
  ;; .dir-locals.el
  ((org-mode . ((org-srs-algorithm . fsrs)
                (org-srs-item-confirm . org-srs-item-confirm-command))))
#+END_SRC
** Per-file Configuration
#+BEGIN_SRC org
  :PROPERTIES:
  :SRS_ALGORITHM: fsrs
  :SRS_ITEM_CONFIRM: org-srs-item-confirm-command
  :END:
  ,#+TITLE: Title

  # or:

  # Local Variables:
  # org-srs-algorithm: fsrs
  # org-srs-item-confirm: org-srs-item-confirm-command
  # End:
#+END_SRC
** Per-entry Configuration
#+BEGIN_SRC org
  ,* Entry
  :PROPERTIES:
  :SRS_ALGORITHM: fsrs
  :SRS_ITEM_CONFIRM: org-srs-item-confirm-command
  :END:
#+END_SRC
** Per-item Configuration
#+BEGIN_SRC org
  :SRSITEMS:
  ,#+NAME: srsitem:569a2e48-633d-4b8c-82b5-f3df9b29bb69::cloze::d0ee345
  ,#+ATTR_SRS: :algorithm fsrs :item-confirm org-srs-item-confirm-command
  | ! | timestamp            | rating | stability | difficulty | state |
  |---+----------------------+--------+-----------+------------+-------|
  |   | 2024-12-07T13:54:06Z |        |       0.0 |        0.0 | :new  |
  | * | 2024-12-07T13:54:34Z |        |           |            |       |
  :END:
#+END_SRC

#+BEGIN_COMMENT
Keep this block at the bottom of the file.
It instructs Emacs to ignore examples
of local variables sections above, see
<info:emacs#Specifying File Variables>
The following line contains the form feed 0x0c character.

#+END_COMMENT

Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.

Contributors

bohonghuang

220 commits

josephmturner

3 commits

juraph-dev

1 commits

kozity

1 commits

bohonghuang/org-srs

A feature-rich and flexible spaced repetition system inside Org-mode

125

stars

226

commits

Emacs Lisp

primary language

Jun 28, 2026

updated

README

#+TITLE: Org-srs

[[https://melpa.org/#/org-srs][file:https://melpa.org/packages/org-srs-badge.svg]]

Org Spaced Repetition System
* Introduction
Org-srs is a feature-rich and extensible spaced repetition system
integrated within Org-mode, allowing you to learn and review knowledge
without leaving your Org workflow.
* Features
- *Everything in Org* \\
  All data in Org-srs, including review histories and customizable
  options, are stored as plain text in your Org files. This makes
  version control easy, and by simply syncing your Org files, you can
  review seamlessly across different devices (especially the native
  Emacs on Android).
- *Powerful* \\
  Org-srs integrates the modern FSRS algorithm out of the box to help
  you review more efficiently and effectively. You can also optimize
  the parameters based on the content and your review habits. Org-srs
  also includes various advanced scheduling features such as fuzzing,
  stepped learning, and auto-burying, all with customizable
  parameters.
- *Performant* \\
  Org-srs supports enabling caching for a review session to
  significantly improve its performance in a large review collection
  with 10K+ items, at the cost of some flexibility (such as creating
  items on the fly).
- *Flexible* \\
  In Org-srs, the smallest review unit is an "item" (similar to a card
  in Anki). A content piece reviewed through one or more items is
  called an "entry" (similar to a note in Anki). An item can be a
  flashcard with a front (question) and back (answer), a cloze
  deletion, etc. This means an entry can hold different types of items
  to meet various review needs. For example, you can review the same
  content using both flashcards and cloze deletions simultaneously if
  needed. Moreover, various customizable options provided by Org-srs
  can be finely controlled, allowing you to set different values for
  the same customizable option at the global, directory, file, entry,
  or item level to suit your review preferences.
- *Embeddable* \\
  If you're reviewing your own notes, maintaining additional entries
  for review can be tedious. If you modify your notes or add, delete,
  or modify cloze deletions, manually updating the created review
  entries can be a nightmare. Org-srs supports non-invasive embedding
  of review entries into your notes. This means that whenever you
  change the content of your notes, you can update the exported entry
  with one command, without polluting the export of your Org files.
- *Extensible* \\
  Org-srs is designed with high modularity. By virtue of generic
  functions and hooks, algorithms, scheduling features, item types,
  and review strategies can be extended externally as you need.
- *Statistics Visualization* \\
  Org-srs allows you to view review history (e.g., number of reviews
  per day, retention rate) and the number of items scheduled for
  review on future dates through charts.
- *Touchscreen/Mouse Support* \\
  Org-srs supports displaying GUI buttons via child frames to enable
  complete review via mouse or touchscreen, perfectly adapting to
  native Emacs on Android, allowing you to review out of your phone on
  the go.
* Installation
Org-srs is now available on [[https://melpa.org/#/org-srs][MELPA]]. Below is an example configuration
with ~use-package~:

#+BEGIN_SRC emacs-lisp
  (use-package org-srs
    :ensure t
    :defer t
    :hook (org-mode . org-srs-embed-overlay-mode)
    :bind (:map org-mode-map
           ("<f5>" . org-srs-review-rate-easy)
           ("<f6>" . org-srs-review-rate-good)
           ("<f7>" . org-srs-review-rate-hard)
           ("<f8>" . org-srs-review-rate-again)))

  (use-package org-srs
    :when (eq system-type 'android)
    :ensure t
    :defer t
    :custom
    (org-srs-item-confirm #'org-srs-item-confirm-command)
    :config
    (org-srs-ui-mode +1))
#+END_SRC
* Usage
Here are some demonstrations and descriptions for the main features of
Org-srs. You can also open file [[https://github.com/bohonghuang/org-srs/blob/doc/org-srs-example.org][org-srs-example.org]] in Emacs and
execute command ~org-srs-review-start~ to start an example review
session right out of the box.
** Flashcards
[[https://github.com/user-attachments/assets/eaafff3c-6463-438d-8780-9cd4c17826cd][Demo]]

A basic form of review that you can see in most spaced repetition
software. It consists of a card's front (question) and back (answer).
You can easily create a flashcard by using ~org-srs-item-create~ in an
entry and selecting ~card~. There are multiple supported formats for the
front and back of a flashcard:

- *File-level flashcards* \\
  #+BEGIN_SRC org
    # Card 1
    ,#+TITLE: The card front
    The card back
  #+END_SRC

  #+BEGIN_SRC org
    ,#+TITLE: Card 2
    The card front
    ,* Back
    The card back
  #+END_SRC

  #+BEGIN_SRC org
    ,#+TITLE: Card 3
    ,* Front
    The card front
    ,* Back
    The card back
  #+END_SRC
- *Heading-level flashcards* \\
  #+BEGIN_SRC org
    # Card 1
    ,* The card front
    The card back
  #+END_SRC

  #+BEGIN_SRC org
    ,* Card 2
    The card front
    ,** Back
    The card back
  #+END_SRC

  #+BEGIN_SRC org
    ,* Card 3
    ,** Front
    The card front
    ,** Back
    The card back
  #+END_SRC
** Cloze Deletion
[[https://github.com/user-attachments/assets/176fb6ef-87a2-42b9-ad4e-7639b6371254][Demo]]

This feature allows you to cloze any content you want to review (such
as a word, a list item, or a table field) and hide it during the
review process. There are two ways to create a cloze item:
1) Select the content you want to cloze, execute the
   ~org-srs-item-create~ command, and then select ~cloze~.
2) Use ~org-srs-item-cloze-dwim~ for context-sensitive cloze creation
   (note that you can use ~org-srs-item-uncloze-dwim~ to undo the
   cloze). Afterward, you need to manually execute
   ~org-srs-item-cloze-update~ to create the corresponding items for all
   cloze deletions at once.

By default, each cloze deletion’s ID is the first 7 characters of the
SHA-1 hash of its content. This means you can freely insert, delete,
swap, or modify them. However, it is recommended to execute
~org-srs-item-cloze-update~ after each modification to ensure that the
changes of clozes are always tracked by Org-srs.

The syntax for a cloze deletion is as follows:

#+BEGIN_SRC org
  {{<cloze-id>}{<content>}{<hint>}}
#+END_SRC
** Embedding
[[https://github.com/user-attachments/assets/5e55a3ff-c1eb-48b6-9f56-5c15c012fc63][Demo]]

A good part of Org-srs is the ability to export content from within
your notes that you want to review. After modifying your notes, you
can directly update the corresponding entry in your notes. The main
command for this feature is the context-sensitive ~org-srs-embed-dwim~,
whose logic is as follows:
1. If point is on an element without a corresponding exported entry,
   that element will be exported as the content of the entry. If the
   exported element contains clozes, corresponding items will
   automatically be created; otherwise, the content will be exported
   as the back of a flashcard. You will need to fill in the entry’s
   title in the pop-up buffer. The default export path is the current
   Org file's relative path to ~org-directory~ under the =org-srs=
   directory in ~org-directory~. For example, if your ~org-directory~ is
   =~/org= and the current file is =~/org/foo/bar.org=, the file where the
   entry is exported will be =~/org/org-srs/foo/bar.org=.
2. If point is on an element that already has a corresponding exported
   entry, the exported entry will be updated with the current
   element's content.
3. If point is on a marker (shown as =#+SRS= when
   ~org-srs-embed-overlay-mode~ is on) representing an embedded Org-srs
   entry, it will jump to the corresponding exported entry.

Additionally, if you need to cloze or uncloze the content to be
exported, you can use ~org-srs-embed-cloze-dwim~ and
~org-srs-embed-uncloze-dwim~.
* Configuration
See the ~org-srs~ customization group, where all the customizable
variables are documented.
** Per-directory Configuration
#+BEGIN_SRC emacs-lisp
  ;; .dir-locals.el
  ((org-mode . ((org-srs-algorithm . fsrs)
                (org-srs-item-confirm . org-srs-item-confirm-command))))
#+END_SRC
** Per-file Configuration
#+BEGIN_SRC org
  :PROPERTIES:
  :SRS_ALGORITHM: fsrs
  :SRS_ITEM_CONFIRM: org-srs-item-confirm-command
  :END:
  ,#+TITLE: Title

  # or:

  # Local Variables:
  # org-srs-algorithm: fsrs
  # org-srs-item-confirm: org-srs-item-confirm-command
  # End:
#+END_SRC
** Per-entry Configuration
#+BEGIN_SRC org
  ,* Entry
  :PROPERTIES:
  :SRS_ALGORITHM: fsrs
  :SRS_ITEM_CONFIRM: org-srs-item-confirm-command
  :END:
#+END_SRC
** Per-item Configuration
#+BEGIN_SRC org
  :SRSITEMS:
  ,#+NAME: srsitem:569a2e48-633d-4b8c-82b5-f3df9b29bb69::cloze::d0ee345
  ,#+ATTR_SRS: :algorithm fsrs :item-confirm org-srs-item-confirm-command
  | ! | timestamp            | rating | stability | difficulty | state |
  |---+----------------------+--------+-----------+------------+-------|
  |   | 2024-12-07T13:54:06Z |        |       0.0 |        0.0 | :new  |
  | * | 2024-12-07T13:54:34Z |        |           |            |       |
  :END:
#+END_SRC

#+BEGIN_COMMENT
Keep this block at the bottom of the file.
It instructs Emacs to ignore examples
of local variables sections above, see
<info:emacs#Specifying File Variables>
The following line contains the form feed 0x0c character.

#+END_COMMENT

Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.

Contributors

bohonghuang

220 commits

josephmturner

3 commits

juraph-dev

1 commits

kozity

1 commits

Languages

Emacs Lisp

100.0%