Skip to content

AlexW00/anki-patcher

Repository files navigation

🩹 Anki Patcher

= modular python script launcher to patch anki cards en masse

Basic Idea

Anki patcher is a script launcher to manipulate anki cards via patch operations defined as python functions.

An operation is a python file with an execute (card_id, fields, config) function. This function gets called for each card of a specified deck and can execute arbitrary code on the card. The card_id and fields are provided by anki pacher and the config is a parsed .yml file provided by the user.

Setup

  • Option A (local dev):
    • run poetry install
    • run poetry shell and python -m unidic download to download the unidic dictionary
    • add an .env file to the root of the project (based on .env.example)
  • Option B (Docker, no local Python required):
    • ensure the AnkiConnect add-on is installed and your Anki Desktop app is running (defaults to http://localhost:8765)
    • Docker will reach your host's AnkiConnect via http://host.docker.internal:8765 (pre-configured)

Available commands

To execute an operation locally, run poetry run anki-patcher <--flags> <command>

  • poetry run anki-patcher list: lists all available patch operations
  • poetry run anki-patcher patch -o <operation> -d <deck-name> -c <path-to-config.yml> : executes the specified operation on all cards of the deck

Running with Docker

No need to install Python or Poetry. The container image includes all dependencies and downloads unidic at build time.

Quickstart with docker compose (recommended):

# List available operations
docker compose run --rm anki-patcher list

# Run an operation (example: gpt)
docker compose run --rm \
  -e OPENROUTER_API_KEY=your_key \
  anki-patcher patch -o gpt -d "Your::Deck" -c /work/example_configs/gpt_example.yml

Notes:

  • Anki must be running on your Mac with the AnkiConnect add-on enabled.
  • The container uses ANKI_CONNECT_URL=http://host.docker.internal:8765 by default so it can call your host's AnkiConnect.
  • Mount your configs via the provided docker-compose.yml. By default, ./configs and ./example_configs are available at /work/configs and /work/example_configs.
  • Stock media operations (add_image, add_tts) store files via AnkiConnect (storeMediaFile), so they work from Docker without mounting your collection.media.
  • If a custom operation writes media files directly, set ANKI_MEDIA_FOLDER to a valid path reachable from the container and mount it. Two options:
    1. Pass your host path directly (read/write): -e ANKI_MEDIA_FOLDER="/absolute/host/path/to/collection.media" and mount that path into the container at the same location using volumes:.
    2. Or mount into the container at /anki_media and set -e ANKI_MEDIA_FOLDER=/anki_media.

Example with media mount (only needed for custom operations that write directly to the media folder):

docker compose run --rm \
  -e ANKI_MEDIA_FOLDER=/anki_media \
  -v "$HOME/Library/Application Support/Anki2/User 1/collection.media":/anki_media:rw \
  anki-patcher patch -o add_image -d "German::A1" -c /work/example_configs/add_image_example.yml

Optional environment variables:

  • OPENROUTER_API_KEY or OPENAI_API_KEY (for gpt op)
  • OPENAI_API_BASE (defaults to https://openrouter.ai/api/v1)
  • GOOGLE_API_KEY and CX (for add_image op)

Stock operations:

  • add_image: for each card of a deck, adds an image retrieved from google, based on another card field value (example config)
    • use-case: add images to cards for language learning
    • example-use: poetry run anki-patcher patch -o add_image -d "German::A1" -c example_configs/add_image_example.yml
  • add_tts: for each card of a deck, adds a text-to-speech audio file retrieved from google tts, based on another card field value (example config)
    • use-case: add tts to cards for language learning
    • example-use: poetry run anki-patcher patch -o add_tts -d "German::A1" -c example_configs/add_tts_example.yml
  • gpt: for each card of a deck, adds a text generated by an OpenAI-compatible API (defaults to OpenRouter; e.g., openai/gpt-5), based on another card field value (example config)
    • use-case: add example sentences to cards
    • example-use: poetry run anki-patcher patch -o gpt -d "German::A1" -c example_configs/gpt_example.yml
    • env: set OPENROUTER_API_KEY (preferred) or OPENAI_API_KEY; optionally override OPENAI_API_BASE (defaults to https://openrouter.ai/api/v1)
  • replace: for each card of a deck, replaces a substring of a field value with another string (example config)
    • use-case: replace a substring of a field value with another string
    • example-use: poetry run anki-patcher patch -o replace -d "German::A1" -c example_configs/replace_example.yml
  • ... building more, contributions welcome!

Building your own operations

It's easy! Just create a new file in operations with a execute(card_id, fields, config) function (see add_image for an example). Afterwards, the operation will be available to be executed via poetry run anki-patcher patch -o <operation> -d <deck-name> -c <path-to-config.yml> . To check if your operation is available, run poetry run anki-patcher list.

About

🩹 A modular python script launcher to patch anki cards en masse

Topics

Resources

Stars

Watchers

Forks

Contributors