AnkiForgeAI
AI-powered vocabulary flashcard pipeline for any language with automatic delivery to Anki.
Language-agnostic via configurable YAML profiles (languages/{code}/language.yaml).
Built-in languages: ๐ณ๐ด Norwegian Bokmรฅl (nb), ๐ฉ๐ช German (de), ๐ฌ๐ง English (en), ๐ช๐ธ Spanish (es).
What it does
- Ingest โ generates word candidates:
- by topic via LLM ("20 food-related words, A2")
- from a URL (web page extraction + LLM parsing)
- Enrich โ adds grammar forms, translation, example sentences.
- Dedupe โ checks duplicates against existing Anki notes and staging DB.
- Media โ generates mp3 audio (edge-tts) and downloads images (pick a provider: Unsplash, Pexels, Pixabay, or key-free Openverse).
- Review โ interactive review of ambiguous candidates (CLI).
- Push โ sends approved cards to Anki via AnkiConnect.
Architecture
| Decision | Why |
|---|---|
| AnkiConnect, not CSV | Two-way sync, dedupe against live Anki deck |
| SQLite as staging + audit + cache | Anki = source of truth, SQLite = local index + history |
forms as JSON |
Different schemas for nouns/verbs/adjectives per language |
| edge-tts over gTTS | Microsoft neural voices, free, per-language quality |
| Pluggable image provider | images.provider: Unsplash, Pexels, Pixabay, or key-free Openverse โ legal, free tiers |
| Selectable transcription | transcription: practical (Cyrillic respelling) or ipa โ pronunciation hints aren't hardcoded to Russian speakers |
Prompts in prompts/*.md |
Improve card quality without touching code |
| Any LLM provider | OpenRouter or Anthropic Claude |
Card statuses
pending โ review โ approved โ pushed
โ
skipped / suspended
- pending โ just created, not yet enriched
- review โ potential duplicates found, needs decision
- approved โ ready for push to Anki
- pushed โ already in Anki (
anki_note_idset) - skipped โ discarded (reason in audit_log)
- suspended โ postponed
Supported Languages
Language profiles live in languages/{code}/. Currently supported:
| Language | Code | Status |
|---|---|---|
| ๐ณ๐ด Norwegian Bokmรฅl | nb |
โ Complete |
| ๐ฉ๐ช German | de |
โ Complete |
| ๐ฌ๐ง English | en |
โ Complete |
| ๐ช๐ธ Spanish | es |
โ Complete |
Select the active language with language: <code> in config.yaml, or pick it interactively via ankiforgeai setup.
Adding Your Language
code: xx # ISO 639-1
name: Language Name
article: true # whether nouns have articles
pos_labels: # POS โ target language name
noun: ...
verb: ...
forms: # grammar field schema per POS
noun:
- {key: gender, label: "Gender"}
- {key: ...}
tts: # edge-tts voices
voice_female: xx-XX-NameNeural
anki:
deck_name: MyDeck
back_labels: # labels in your native language
translation: "Translation"
- Copy prompts:
cp prompts/*.md languages/{code}/prompts/ - Adapt prompts for the target language
- Minimal setup for a working language:
language.yaml+topic_words.md
Installation
Requires Python 3.11+ and Anki desktop + the AnkiConnect addon.
As a tool (end users)
uv tool install ankiforgeai # or: pipx install ankiforgeai / pip install ankiforgeai
ankiforgeai setup # writes config.yaml in the current directory
ankiforgeai init # creates the local DB and the Anki Note Type
config.yaml, data/, and media/ are created in whatever directory you run ankiforgeai from โ cd into a project folder first (e.g. mkdir ~/ankiforgeai && cd ~/ankiforgeai).
init is safe to re-run: if the Note Type already exists in Anki, it pushes the current card templates and CSS to it instead of skipping, so re-run it after pulling an update that changes the card design. This also applies if an update renames the Note Type itself (anki.note_type in languages/{code}/language.yaml) โ ankiforgeai push will fail with Note Type '...' ะฝะต ะฝะฐะนะดะตะฝ ะฒ Anki until you re-run init to create it.
From source (contributors)
git clone https://github.com/k0bad/AnkiForgeAi.git
cd AnkiForgeAi
uv venv
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
uv pip install -e ".[dev]"
# Configuration
cp .env.example .env
# edit .env โ add your API keys
# Initialize (DB + Anki Note Type)
ankiforgeai init
Usage
# Generate 20 food-related words at A2 level
ankiforgeai ingest topic "mat" --count 20 --level A2
# Extract words from a web page
ankiforgeai ingest url "https://example.com/lesson"
# Run interactive review
ankiforgeai review
# Push approved cards to Anki
ankiforgeai push
# Sync Anki โ local cache (daily)
ankiforgeai sync
# View stats
ankiforgeai stats
# Consistency check: enrich/images config toggles vs actual card data
ankiforgeai doctor
# Delete cards permanently (frees their id for reuse; irreversible if already pushed)
ankiforgeai delete <id> [<id> ...]
Automated Daily Cycle
# Generate โ dedupe (AI-adjudicated)/enrich/media โ push (no Telegram notification)
python scripts/daily_topic.py
# Preview what today's topic would be
python scripts/daily_topic.py --dry-run
# Override topic and count
python scripts/daily_topic.py --topic dyr --count 5 --no-push
# Full cycle incl. notifications (config.yaml -> notifications:) โ use this for cron
./scripts/daily_topic.sh
daily_topic.py alone does not send notifications โ pass --notify (which is what
daily_topic.sh does) to fan the report out to every enabled channel in
config.yaml -> notifications:. Today that's a generic webhook backend (POST JSON to
any URL โ n8n, Zapier, a custom bot gateway); see src/ankicards/notify/. Set up
daily_topic.sh as a cron job for hands-free daily vocabulary generation with delivery
to your configured channel.
Project Structure
src/ankicards/
โโโ models.py # Card, POS, Status, Decision (Pydantic)
โโโ config.py # config.yaml + language profiles
โโโ db.py # SQLite layer
โโโ cli.py # Typer CLI
โโโ pipeline.py # Stage orchestration
โโโ llm.py # LLM client (OpenRouter/Anthropic)
โโโ dedupe.py # Exact + fuzzy matching (rapidfuzz)
โโโ doctor.py # Consistency check: enrich/images config vs card data
โโโ migrate_ids.py # One-time UUID โ sequential int id migration
โโโ ingest/
โ โโโ url.py # trafilatura + LLM
โ โโโ topic.py # Topic-based generation
โโโ enrich/
โ โโโ grammar.py # Grammar forms per POS
โ โโโ translation.py # Translations
โ โโโ examples.py # Example sentences
โ โโโ pronunciation.py # Pronunciation hints
โโโ media/
โ โโโ tts.py # edge-tts audio
โ โโโ images.py # Image search: unsplash/pexels/pixabay/openverse
โโโ anki/
โ โโโ connect.py # HTTP client for AnkiConnect
โ โโโ sync.py # Anki โ cache sync
โ โโโ notetype.py # Note type definition
โโโ notify/
โ โโโ base.py # Notifier protocol
โ โโโ webhook.py # Generic webhook backend (n8n, Zapier, ...)
โโโ review/
โโโ interactive.py # Rich + questionary UI
โโโ actions.py # Non-interactive accept/skip/suspend/resume/edit/delete
languages/ # Language profiles (YAML + prompts)
prompts/ # Default prompts
scripts/ # daily_topic, run_images
tests/
data/ # DB, logs (gitignored)
media/ # Audio, images (gitignored)
Roadmap
- Multi-language architecture
- Ingest by topic (LLM)
- Ingest from URL (trafilatura + LLM)
- Dedupe (rapidfuzz)
- Grammar enrichment
- edge-tts audio
- Pluggable image providers (Unsplash / Pexels / Pixabay / Openverse)
- Selectable pronunciation transcription (practical Cyrillic / IPA)
- AnkiConnect push & sync
- Interactive review CLI
- Full auto cycle (cron + dedupe + push + notify)
- Pluggable notification channels (generic webhook: n8n / Zapier / Hermes / any)
- AI-adjudicated dedupe โ ambiguous fuzzy matches are judged by the LLM (same word vs. coincidentally similar), not blindly auto-accepted or left for a human by default
- PyPI publication โ package and release workflow are ready (see
DEVELOPER_GUIDE.mdยง12), pending one-time trusted-publisher setup on pypi.org
For Developers
See DEVELOPER_GUIDE.md for the full architecture reference, and CONTRIBUTING.md for contribution guidelines.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ankiforgeai-0.4.0.tar.gz.
File metadata
- Download URL: ankiforgeai-0.4.0.tar.gz
- Upload date:
- Size: 83.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac44d55de6158823c57c4e0e24d7ecd0f8d226ef59b28d44254cc12c6dae7ecf
|
|
| MD5 |
a9b638762d5ff7d00381970cae4bbce6
|
|
| BLAKE2b-256 |
40f153d324ba0cf2097b3d6c9f8c4e0736e378b286d07e78daeb01a8310c53df
|
Provenance
The following attestation bundles were made for ankiforgeai-0.4.0.tar.gz:
Publisher:
publish.yml on k0bad/AnkiForgeAi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ankiforgeai-0.4.0.tar.gz -
Subject digest:
ac44d55de6158823c57c4e0e24d7ecd0f8d226ef59b28d44254cc12c6dae7ecf - Sigstore transparency entry: 2485297911
- Sigstore integration time:
-
Permalink:
k0bad/AnkiForgeAi@05a62f412df7c408a8486e6145de0d608f50cf3f -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/k0bad
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@05a62f412df7c408a8486e6145de0d608f50cf3f -
Trigger Event:
push
-
Statement type:
File details
Details for the file ankiforgeai-0.4.0-py3-none-any.whl.
File metadata
- Download URL: ankiforgeai-0.4.0-py3-none-any.whl
- Upload date:
- Size: 116.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f299e36959799586930e13078eb689228227f2bd519ddf938586b9d14ed03ea1
|
|
| MD5 |
91bc2f24f1dd4f8c29301cf701ad2f03
|
|
| BLAKE2b-256 |
677c0b01fbdd3391379c38b9ef3405e0a05f244f1248204aeee95895b00bd497
|
Provenance
The following attestation bundles were made for ankiforgeai-0.4.0-py3-none-any.whl:
Publisher:
publish.yml on k0bad/AnkiForgeAi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ankiforgeai-0.4.0-py3-none-any.whl -
Subject digest:
f299e36959799586930e13078eb689228227f2bd519ddf938586b9d14ed03ea1 - Sigstore transparency entry: 2485297977
- Sigstore integration time:
-
Permalink:
k0bad/AnkiForgeAi@05a62f412df7c408a8486e6145de0d608f50cf3f -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/k0bad
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@05a62f412df7c408a8486e6145de0d608f50cf3f -
Trigger Event:
push
-
Statement type: