Skip to main content

Anki decks ↔ Markdown files, in perfect sync

Project description

AnkiOps

License: MIT PyPI version

Anki decks ↔ Markdown files, in perfect sync

Editing flashcards in Anki's UI is tedious when you could be using your favorite text editor, AI tools, and Git. Currently available Markdown → Anki tools only go one way, where edits in Anki don't sync back.

AnkiOps is a bidirectional Anki ↔ Markdown bridge. Each deck is a Markdown file. Work in either Anki or your text editor, and let changes flow both ways. This brings AI assistance, batch editing, and version control to your flashcards.

Features

  • Fully round-trip, bidirectional sync that handles note creations, deletions, movements, and conflicts
  • High-performance processing: handles thousands of cards across hundreds of decks in seconds
  • Markdown rendering with nearly all features (including syntax-highlighted code blocks, supported on desktop and mobile)
  • Thoroughly tested, bidirectional conversion between Markdown and Anki-compatible HTML
  • Support for Basic (Q&A), Cloze, Single & Multiple Choice note types
  • Embed images via VS Code where they are directly copied into your Anki media folder (automatically set up)
  • Built-in Git integration with autocommit for tracking all changes
  • Package/unpackage entire collections to JSON format for backup, sharing, or automated AI processing
  • Simple CLI interface: after initialization, only two commands are needed for daily use

[!NOTE] AnkiOps only syncs the AnkiOpsQA, AnkiOpsCloze, and AnkiOpsChoice note types.

Getting Started

  1. Install AnkiOps via pipx: Pipx will make AnkiOps globally available in your terminal.
pipx install ankiops
  1. Initialize AnkiOps: Make sure that Anki is running, with the AnkiConnect add-on enabled. Initialize AnkiOps in any empty directory of your choosing. This is where your text-based decks will live. The additional tutorial flag creates a sample Markdown deck.
ankiops init --tutorial
  1. Execute AnkiOps: Import the tutorial deck into Anki using:
ankiops ma # markdown to anki (import)
  1. Keep everything in sync: When editing your Markdown files, sync Markdown → Anki (and vice versa), as each sync makes one side match the other. After reviewing and editing your cards in Anki, you can sync Anki → Markdown using the following command:
ankiops am # anki to markdown (export)

FAQ

How is this different from other Markdown or Obsidian tools?

Available tools are one-way importers: you write in Markdown or Obsidian and push to Anki, but edits in Anki don't sync back. AnkiOps is bidirectional: you can edit in either Anki or Markdown and sync in both directions. Additionally, AnkiOps uses a one-file-per-deck structure, making your collection easier to navigate and manage than approaches that use one file per card.

Is it safe to use?

Yes, AnkiOps will never modify notes with non-AnkiOps note types. Your existing collection won't be affected and you can safely mix managed and unmanaged notes in the same deck. Further, AnkiOps only syncs if the activated profiles matches the one it was initialized with. When orphaned AnkiOps notes are detected, you will be prompted to confirm their deletion. Concerning your Markdown files, AnkiOps automatically creates a Git commit of your collection folder before every sync, so you can always roll your files back if needed.

How do I create new notes?

Create a new Markdown file in your initialized AnkiOps folder. For the first import, the file name will act as the deck name. Subdecks are supported via two underscores __ (Anki's :: is not supported in the file system). Start by writing your notes in Markdown. For each note, you can decide whether to use the QA or cloze format. Notes must be separated by a new line, three dashes ---, and another new line. You can add new notes anywhere in an existing file.

Q: Question text here
A: Answer text here
E: Extra information (optional)
M: Content behind a "more" button (optional)

---

T: Text with {{c1::multiple}} {{c2::cloze deletions}}.
E: ![image with set width](im.png){width=700}

---

Q: What is this?
C1: A multiple choice note
C2: with
C3: automatically randomized answers.
A: 1,3

---

And so on…

Which characters or symbols cannot be used?

Since notes are separated by horizontal lines (---), they cannot be used within the content fields of your notes. This includes all special Markdown characters that render these lines (***, ___), and <hr>.

How does it work?

On first import, AnkiOps assigns IDs from Anki to each deck and note for tracking. They are represented by a single-line HTML tag (e.g., <!-- note_id: 1770487991522 -->) above a note in the Markdown. With the IDs in place, we can track what is new, changed, moved between decks, or deleted, and AnkiOps will sync accordingly. Content is automatically converted between Anki's HTML format and Markdown during sync operations. Note that one AnkiOps folder represents an entire Anki profile.

What is the recommended workflow?

We recommend using VS Code. It has excellent AI integration, a great add-on for Markdown previews, and supports image pasting (which will be saved in your Anki media folder by default).

How can I share my AnkiOps collection?

Use ankiops package --no-ids to export your local AnkiOps collection to a clean JSON package file without profile-specific IDs. Add --include-media to bundle media files from the Anki media folder into a ZIP archive. Recipients can import either format with ankiops unpackage <package-file>, which creates a new local AnkiOps directory on their machine and imports media to their Anki folder with smart conflict resolution. Alternatively, you could share your collection using the native Anki export (.apkg), or by sharing your plain Markdown files along with the media/AnkiOpsMedia folder. Make sure to remove all ID tags from your Markdown files first, as they are profile-specific.

How can I migrate my existing notes into AnkiOps?

While migration is doable, it can be tricky. The process requires:

  1. Converting note types: Your existing notes must be converted to AnkiOps note types (AnkiOpsQA or AnkiOpsCloze). This must be done manually in Anki or by adapting the AnkiOps code.
  2. Exporting to Markdown: Once converted, use ankiops am to export your notes from Anki to Markdown.
  3. Formatting adjustments: In the first re-import, some formatting may change because the original HTML from Anki may not follow the CommonMark standard.

If your existing note format doesn't map cleanly to the AnkiOps format (e.g., notes with additional or custom fields), you'll need to adapt the code to your specific needs.

How can I develop AnkiOps locally?

Fork this repository and initialize the tutorial in your root folder (make sure Anki is running). This will create a folder called collection with the sample Markdown in it. Paths will adapt automatically to the development environment. You can run AnkiOps locally using the main script.

git clone https://github.com/visserle/ankiops.git
cd ankiops
uv sync
uv run python -m main init --tutorial
uv run python -m main ma

What commands and flags are available in the CLI?

Global:

  • --debug - Enable debug logging
  • --help - Show help message

init:

  • --no-auto-commit - Disable automatic git commits
  • --tutorial - Create tutorial markdown file

anki-to-markdown / am:

  • --deck, -d - Export single deck by name
  • --keep-orphans - Keep deck files/notes that no longer exist in Anki
  • --no-auto-commit, -n - Skip automatic git commit

markdown-to-anki / ma:

  • --file, -f - Import single file
  • --only-add-new - Only add new notes, skip existing
  • --no-auto-commit, -n - Skip automatic git commit

package:

  • --output, -o - Output package file path (default: <collection-name>.json)
  • --no-ids - Exclude note_id and deck_id from package (useful for templates/sharing)
  • --include-media - Bundle media files into a ZIP archive (creates .zip instead of .json)

unpackage:

  • PACKAGE - Package file to import: .json or .zip (required)
  • --directory, -d - Local collection directory to create/update (default: use package filename)
  • --overwrite - Overwrite existing markdown files (media uses smart conflict resolution)

ko-fi

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ankiops-0.3.0.tar.gz (62.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ankiops-0.3.0-py3-none-any.whl (51.3 kB view details)

Uploaded Python 3

File details

Details for the file ankiops-0.3.0.tar.gz.

File metadata

  • Download URL: ankiops-0.3.0.tar.gz
  • Upload date:
  • Size: 62.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ankiops-0.3.0.tar.gz
Algorithm Hash digest
SHA256 9f301afa0eb22a5d8cf6a99c8080d599121d7dbf60fafcc40bcea5892aab1dcb
MD5 e10cb37585baae44e1393d1a8569d436
BLAKE2b-256 0616c8a3623f0fc50bb12fcd747ee9aa11c90b8e93c2643cfeebeb56f2232fdf

See more details on using hashes here.

Provenance

The following attestation bundles were made for ankiops-0.3.0.tar.gz:

Publisher: publish.yml on visserle/AnkiOps

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ankiops-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: ankiops-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 51.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ankiops-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d0e5f3b74932a4bfb18c5267430089bbd3f33ddae123e3bbc9784222beebe90a
MD5 d9a76cb4c90010839f4d2c3d703cc43c
BLAKE2b-256 37598b9cfe007481e59d74ce03eedbf10af6a088cf4fd5bb03c63721cd1b19ae

See more details on using hashes here.

Provenance

The following attestation bundles were made for ankiops-0.3.0-py3-none-any.whl:

Publisher: publish.yml on visserle/AnkiOps

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page