Agent-assisted Anki flashcard generation. Agents propose cards from web content, YouTube transcripts, and documents — you review before anything touches your decks.
Built on the EAT Framework (Encoded, Atomic, Timeless): cognitive science-grounded principles that prioritize understanding over rote memorization. See docs/EAT_FRAMEWORK.md for the full framework.
- Anki Desktop with AnkiConnect plugin — must be running for all operations
- Python 3.11+ via
uv - Node.js 20+ & pnpm — for the web frontend
- crawl4ai (optional) — web scraping. Set
CRAWL4AI_DIRor place alongside repo
uv sync
uv run anki-api ping # verify Anki connection
uv run anki-api decks # verify the live target deck
uv run anki-api models # verify the live note typeThe current Anki profile was verified on 2026-07-11 with all existing cards in its sole Default deck. Card-generation sessions should still run the diagnostics above and use the existing live deck rather than assume or create one. The standard note type is Basic.
All commands: uv run anki-api <command>
anki-api up # start full stack (backend + frontend via tmux)
anki-api down # stop the stack
anki-api status # show stack status
anki-api logs # attach to tmux session for logs
anki-api serve # start backend API server onlyanki-api review <file.json> # interactive review (approve/edit/skip)
anki-api review <file.json> --deck X # target specific deck
anki-api add <file.json> # batch add without review
anki-api quick "Q?" "A" --tags t1,t2 # create single card
anki-api find "deck:Default tag:python" # search notes (Anki query syntax)
anki-api delete <note-id> [--yes] # delete notes by IDanki-api flow <source> # generate cards + launch review UI
anki-api extract doc.docx -o out.md # DOCX → markdown
./scrape.sh <url> # URL → scraped/<name>.md (needs crawl4ai)anki-api ping # check AnkiConnect
anki-api decks # list decks
anki-api models # list note typesReact + TypeScript frontend with a FastAPI backend. Used by the flow command for card review.
# Full stack (recommended)
uv run anki-api up
# Manual
uv run anki-api serve --reload # backend on :8000
cd web/frontend && pnpm dev # frontend on :5173Cards are stored as JSON in cards/. Example:
[
{
"front": "Why should you understand material before creating flashcards?",
"back": "Anki schedules retrieval practice; it does not create initial understanding.",
"context": "EAT's Encoded principle connects new material to an existing schema before memorization.",
"tags": ["anki", "eat-framework", "type::concept"],
"deck": "Default",
"model": "Basic"
}
]Review JSON keeps front, back, context, tags, deck, and model, with an optional images list containing filenames stored under cards/media/. Cards use plain text only—no Markdown or HTML. Put the concise answer in back; the application adds a separator before context when exporting to Anki. The review UI serves attached images locally, and approval uploads them to Anki before adding the note.
For mathematical cards, use Anki MathJax delimiters (\( ... \) inline and \[ ... \] display), not dollar-sign delimiters. JSON strings must escape backslashes, and every non-obvious symbol must be defined on the same card. The canonical generation workflow is the project card-creation skill; its MathJax notation rule is mandatory whenever cards contain mathematical notation.
src/
├── anki_client.py # AnkiConnect HTTP wrapper
├── schema.py # Flashcard model + validation
├── youtube.py # YouTube transcript extraction
├── documents.py # DOCX text extraction
└── cli/commands/
├── cards.py # review, add, quick, find, delete
├── orchestration.py # up, down, status, logs, flow, serve, extract
└── diagnostics.py # ping, decks, models
web/
├── backend/ # FastAPI (routes/, models.py, main.py)
└── frontend/ # React + Vite + TypeScript
uv run pytest # run tests
prek run --all-files # all linters + formattersMIT