$npx -y skills add tuan3w/obsidian-vault-agent --skill recallSpaced repetition and retrieval practice engine for the vault. Use when the user wants a review session, recall practice, to test what they remember, or to resurface notes. Triggers on "review session", "what should I review", "recall practice", "resurface notes", "spaced repetit
| 1 | <Purpose> |
| 2 | Run an interactive spaced repetition session: build a mixed queue of retrieval |
| 3 | practice cards, inbox triage items, and a surprise cross-domain connection. |
| 4 | For each card, show only the title first — forcing recall before revealing |
| 5 | content (retrieval practice). Interleave domains to exploit the spacing and |
| 6 | interleaving effects. Surface a non-obvious connection the user hasn't made yet. |
| 7 | </Purpose> |
| 8 | |
| 9 | <Use_When> |
| 10 | - User wants a review session ("what should I review?", "quiz me", "recall practice") |
| 11 | - User wants to resurface notes they haven't seen in a while |
| 12 | - User wants to triage their inbox |
| 13 | - User wants to discover connections across domains |
| 14 | - User asks "what do I remember about X?" |
| 15 | - Periodic knowledge maintenance (daily, weekly reviews) |
| 16 | </Use_When> |
| 17 | |
| 18 | <Do_Not_Use_When> |
| 19 | - User wants to deeply process a specific note (use /process) |
| 20 | - User wants vault structure analysis (use /vault-graph) |
| 21 | - User wants to synthesize across a cluster (use /synthesize) |
| 22 | - User is actively reading or adding a new source note |
| 23 | </Do_Not_Use_When> |
| 24 | |
| 25 | <Execution_Policy> |
| 26 | - INTERACTIVE — never skip ahead. Each card requires the user to respond before |
| 27 | the answer is shown. The friction IS the learning. |
| 28 | - Never show note content before the user attempts recall |
| 29 | - Prefer notes with updated_date older than 14 days (spacing effect) |
| 30 | - MUST interleave domains — draw from at least 3 different topic folders |
| 31 | - Use MCP tools (search_notes, get_frontmatter) when available; fall back to Grep/Glob |
| 32 | - Session size: default 5 retrieval cards, 2 inbox items, 1 surprise connection |
| 33 | (adjust to user's argument if provided) |
| 34 | - After each reveal, offer to update the note if it's stale |
| 35 | </Execution_Policy> |
| 36 | |
| 37 | <Steps> |
| 38 | |
| 39 | ## Stage 1: BUILD THE QUEUE |
| 40 | |
| 41 | ### 1a. Retrieval Practice Cards (default 3–5) |
| 42 | |
| 43 | Candidate selection using MCP: |
| 44 | ``` |
| 45 | search_notes(query="processing_status: processed OR processing_status: evergreen", limit=50) |
| 46 | search_notes(query="type: term OR type: note", limit=50) |
| 47 | ``` |
| 48 | |
| 49 | Or fall back to Grep: |
| 50 | ``` |
| 51 | Grep(pattern="processing_status: (processed|evergreen)", path="notes/", glob="*.md") |
| 52 | Grep(pattern="^type: (term|note)$", path="notes/", glob="*.md") |
| 53 | ``` |
| 54 | |
| 55 | Filter and rank candidates: |
| 56 | 1. Prefer notes with `updated_date` older than 14 days — compute from today (2026-03-20) |
| 57 | 2. Prefer notes with the `[ ](#anki-card)` anchor (marked for spaced repetition) |
| 58 | 3. Prefer notes with `processing_status: processed` over `evergreen` |
| 59 | (evergreen notes are maintained; processed ones need re-testing) |
| 60 | 4. **Enforce domain interleaving**: collect the topic folder for each candidate |
| 61 | (`notes/ml/`, `notes/psychology/`, `notes/startup/`, etc.) and ensure the |
| 62 | final selection spans at least 3 different folders |
| 63 | 5. If fewer than 3 domains are available, accept 2 minimum |
| 64 | |
| 65 | Read the frontmatter to confirm `updated_date` and `type`: |
| 66 | ``` |
| 67 | get_frontmatter(path="notes/PATH/filename.md") |
| 68 | ``` |
| 69 | |
| 70 | ### 1b. Inbox Triage Items (1–2) |
| 71 | |
| 72 | Find the oldest unprocessed source notes: |
| 73 | ``` |
| 74 | search_notes(query="processing_status: inbox", limit=20) |
| 75 | ``` |
| 76 | Or: |
| 77 | ``` |
| 78 | Grep(pattern="processing_status: inbox", path="notes/", glob="*.md") |
| 79 | ``` |
| 80 | |
| 81 | Filter to types: `paper`, `post`, `book`, `lecture`, `course`. |
| 82 | Sort by `created_date` ascending — oldest first. |
| 83 | Pick 1–2. |
| 84 | |
| 85 | ### 1c. Surprise Connection (1) |
| 86 | |
| 87 | Goal: find two notes from DIFFERENT domain folders that share a concept keyword |
| 88 | but have NO wikilink between them. |
| 89 | |
| 90 | Algorithm: |
| 91 | 1. Pick a retrieval card already in the queue (it has topic keywords in its body) |
| 92 | 2. Extract 2–3 key concept words from that note's title or content |
| 93 | 3. Search a DIFFERENT domain folder for notes containing those keywords: |
| 94 | ``` |
| 95 | Grep(pattern="KEYWORD", path="notes/OTHER_DOMAIN/", glob="*.md") |
| 96 | ``` |
| 97 | 4. Check that the two notes do NOT link to each other: |
| 98 | ``` |
| 99 | Grep(pattern="\\[\\[.*TITLE.*\\]\\]", path="notes/SOURCE_NOTE.md") |
| 100 | ``` |
| 101 | 5. If no match, try a second keyword or a second candidate note |
| 102 | 6. Present both notes with the shared concept as the "bridge" |
| 103 | |
| 104 | Non-obvious pairings to prioritize (cross-domain > within-domain): |
| 105 | - ml/ ↔ psychology/ (learning algorithms ↔ cognitive science) |
| 106 | - startup/ ↔ design/ (product strategy ↔ UX) |
| 107 | - finance/ ↔ ml/ (optimization ↔ market dynamics) |
| 108 | - psychology/ ↔ startup/ (behavioral economics ↔ business) |
| 109 | - computer science/ ↔ logic/ (formal systems ↔ reasoning) |
| 110 | |
| 111 | ## Stage 2: PRESENT QUEUE OVERVIEW |
| 112 | |
| 113 | Before |