vscode-spaced-repetition (Spaced Repetition)简体中文 | English
Fight the forgetting curve by reviewing obsidian-spaced-repetition flashcards & notes right in VS Code, scheduling with FSRS by default — the free spaced repetition scheduler used by Anki (via its official TypeScript port ts-fsrs) — or with the classic SM-2 (OSR variant) when you opt out.
Features⚡Scheduling algorithms 🧠
Reviewing flashcards 🗃️
Reviewing whole notes 📄
OSR compatibility 🔄
Localization 🌐
Usage TL;DR 🚀1. Install & open your vault
To use it for real, package a VSIX ( 2. Create decksAdd the tag 3. Create cards
A blank line is a card boundary (it ends the current card) — keep each card's content contiguous. 4. Review flashcardsOpen the command palette (Ctrl+Shift+P) and pick one of:
Select a deck, then rate your ability to recall the current card: press Space / "Show answer" to flip, then 5. Review whole notes
Flashcard syntax (same as OSR)A blank line is a card boundary (it ends the current card):
Notes (matching OSR): a blank line between Deck source (setting
|
| Value | Behavior |
|---|---|
tag (default, same as OSR) |
Only notes with #flashcards[…/subdeck] are parsed; deck = tag path |
folder |
All notes participate; deck = folder (≈ OSR convertFoldersToDecks) |
tagAndFolder |
Only tagged notes are parsed; tag sub-path wins, otherwise the folder |
Tags can be written in the body or in frontmatter tags.
Settings
Scheduling: srs.algorithm (default fsrs; SM-2-OSR = obsidian-spaced-repetition's variant of SM-2 — the same literal as its SRAlgorithmType.SM_2_OSR) · srs.fsrsDesiredRetention (default 0.9; FSRS retention target between 0.7 and 0.97)
Parsing & decks: srs.language (default auto) · srs.flashcardTags (default ["#flashcards"]) · srs.noteReviewTags (default ["#review"]) · srs.deckSource (default tag) · srs.ignoreGlobs (default excludes .git/.obsidian/.vscode/.agents/.trash/node_modules/.github) · srs.followSymlinks (default true: symlinked folders such as note/ -> ~/notes/nuttx are scanned too) · srs.clozePatterns (default ["==[123;;]answer[;;hint]=="], i.e. ==highlight== → cloze; empty array disables cloze)
SM-2 (OSR variant) only: srs.baseEase / easyBonus / lapsesIntervalChange / maximumInterval (used when srs.algorithm is SM-2-OSR; maximumInterval also caps FSRS intervals).
Scheduling algorithm (srs.algorithm)
fsrs(default): new cards are scheduled by ts-fsrs with short-term (re)learning steps enabled and the desired retention fromsrs.fsrsDesiredRetention; due-date/interval/stability/difficulty are written in OSR's<!--SR:!fsrs,...-->format. Legacy SM-2 comments are migrated to FSRS when their card is next reviewed.SM-2-OSR: the original SM-2 (OSR variant) scheduler used by classic obsidian-spaced-repetition. FSRS comments are converted back to SM-2 (ease derived from difficulty) when their card is next reviewed.- Because the algorithm is stored per card in the comment segment itself, the two formats coexist safely in one vault; the setting only decides what happens to a card the next time you rate it.
UI language (srs.language)
auto (default) follows the VS Code UI language (starts with zh → Simplified Chinese, otherwise English), or you can force en or zh-cn. Command titles, the activity-bar container and the view name are driven by the VS Code UI language (package.nls.*); in-panel runtime text is controlled by srs.language.
Known limitations
- Single-workspace mode; no statistics charts or reminders.
- If a note has unsaved edits while reviewing, the schedule write-back may fail due to text mismatch (save and retry).
- Write-back saves the whole document (unsaved edits are saved too; no content is lost).
- Whole-note (
#review) reviews stay on SM-2 (OSR variant) in frontmattersr-due/sr-interval/sr-ease— matching obsidian-spaced-repetition, which has no FSRS format for whole-note scheduling yet. - FSRS due dates are full timestamps (as in OSR), so the due queue becomes live once a card's due instant passes; FSRS (re)learning steps of under a day show up as due on the same day.
How it stays compatible with OSR
All differences live in the adaptation layer; the upstream body is untouched. Before parsing, non-<!--SR: HTML comments are blanked out (the upstream mishandles multi-line HTML comments by deciding on the first line, swallowing subsequent content), degenerate empty-answer cards are not queued, cloze patterns are configurable (default matches OSR's ==…==) but cloze cards are rendered with a plain-text formatter rather than OSR's inline-HTML spans (to keep the html:false render baseline), and SM-2 comment intervals are serialized to whole days with no load-balance fuzzing. The FSRS side mirrors OSR's FSRS integration (same <!--SR:!fsrs,...--> segment layout, same ts-fsrs parameter mapping — desired retention + enable_short_term — and the same SM-2 ↔ FSRS import helpers); the local implementation is plain-Date based (no moment) and does not write OSR's JSON sidecar data store.
Links & Resources 🔗
- Repository
- Issues
- obsidian-spaced-repetition (upstream)
- FSRS4Anki (algorithm)
- ts-fsrs (official TypeScript port used here)
Development
.vscode/launch.json / tasks.json / settings.json # F5 debug config
src/lib/ # vendored from OSR v1.15.4: parser.ts / question-type.ts / compat.ts / strings.ts (see THIRD-PARTY-NOTICES.md)
src/core/ # pure logic: dates, model, SM-2 (sm2.ts), FSRS (fsrs.ts on ts-fsrs), algorithm dispatcher (scheduler.ts)
src/parser/ # md utils, flashcard adapter layer (calls the vendored parser), #review frontmatter
src/store/ # comment write-back (text-level)
src/i18n.ts # en / zh-cn message dictionary with t(key, vars) formatter (display language srs.language)
src/ui/ # Webview review panel (markdown-it + highlight.js + KaTeX), due-note tree, status bar
src/workspace.ts / config.ts / extension.ts
package.nls.json / package.nls.zh-cn.json # contribution-point title/view localization
test/ # English fixture + smoke tests (upstream parse() parity, SM-2 & FSRS scheduling, write-back round-trips)
Scripts: npm run compile (tsc) · npm run smoke (parse parity / scheduling / write-back round-trip) · npm run package (VSIX via @vscode/vsce).
Upstream sync (when maintaining the vendored code)
src/lib/ comes from OSR v1.15.4. To upgrade: copy the corresponding files in and replace only the import lines (parser/question-type's CardType, SR_METADATA_CALLOUT and SRSettings come from ./compat, helpers from ./strings), then run npm run smoke and check the "upstream parser consistency" section for regressions. The FSRS layer (src/core/fsrs.ts, src/core/scheduler.ts) intentionally mirrors the FSRS integration on OSR's master (src/scheduling/algorithms/fsrs/*) so the on-disk formats stay interchangeable.
License
- The code developed for this extension is licensed under the MIT License, Copyright (c) 2026 rong baichuan.
- The vendored third-party code (
src/lib/parser.ts,src/lib/question-type.ts,src/lib/compat.ts,src/lib/strings.ts) is licensed separately under the upstream MIT License — see THIRD-PARTY-NOTICES.md. - The FSRS scheduling uses the npm dependency ts-fsrs (MIT, Copyright (c) 2026 Open Spaced Repetition), the official TypeScript port of the FSRS4Anki algorithm (MIT, Copyright (c) 2022 open-spaced-repetition) — see THIRD-PARTY-NOTICES.md.