Skip to content

Live Anki sync (AnkiConnect / AnkiWeb) #264

Closed

Description

@HugoFara

Split out of #228, which conflated two features under one title. #228 now covers the one-time deck importer; this issue tracks live, bidirectional sync, which is a much larger and later piece of work.

Why this is deferred, not just unscheduled

A server cannot reach AnkiConnect. AnkiConnect binds to 127.0.0.1 by default and gates browser callers through webCorsOriginList. An LWT server — self-hosted on a VPS, or lwt-online.org — has no route to a user's localhost. Telling users to rebind it to 0.0.0.0 and expose it to the network is not something we should ship.

The only viable architecture is client-side: browser JS running on the user's own machine talks to localhost:8765, with the LWT origin added to AnkiConnect's webCorsOriginList by the user. That means it is a frontend feature gated on a manual config step, not a server feature.

AnkiWeb has no public API, so syncing through Anki's own cloud is not an option.

Bidirectional sync is the conflict-resolution problem. The roadmap deliberately quarantines this to Phase 4: "Spike conflict resolution FIRST (the Anki problem) — it looks easy and isn't. Decide last-writer-wins+tombstones vs CRDT before committing." Two systems both mutating term state, both offline-capable, is exactly that problem.

Prerequisites

  • The scheduling half is now partly in place: Term status model: single source of truth + Anki/FSRS-aligned scheduling #238 phase 2a added FSRS-6 memory state (term_schedule) and an append-only review_log, with states matching Anki's cards.type. Phase 2b would populate cards.data + revlog in the .apkg exporter, which gets scheduling round-tripping by file — likely enough for most users who think they want sync.
  • Do the Phase 4 conflict-resolution spike before writing any sync code.

Recommendation

Ship the file-based path first (#228 importer + #238 phase 2b scheduling round-trip) and see whether real demand for live sync survives it. File round-trip covers the common case without owning a sync protocol.

Activity

  1. changed the title [-]Live Anki sync (AnkiConnect / AnkiWeb) — deferred[/-] [+]Live Anki sync (AnkiConnect / AnkiWeb)[/+] on Sep 4, 2026
  2. added a commit that references this issue on Nov 3, 2026
  3. HugoFara commented on Nov 3, 2026

    @HugoFara
    OwnerAuthor

    The conflict-resolution spike this issue asked for is in develop (#326): docs-src/developer/anki-sync-conflicts.md. Decision: neither plain last-writer-wins nor a CRDT. Reviews merge as the union of both logs folded through LWT's scheduler; fields, tags, flags and existence merge three-way against a stored sync base, with newest-wins only as the tie-break for a true conflict. It ends with a three-step build order, of which step 1 (pull Anki reviews over AnkiConnect) is useful on its own. Phase 2b of #238 is complete (#325), so the file round-trip prerequisite is met.

  4. added a commit that references this issue on Nov 3, 2026
  5. HugoFara commented on Nov 3, 2026

    @HugoFara
    OwnerAuthor

    Step 1 of the build order is in develop (#327): /vocabulary/anki/sync pulls reviews from Anki over AnkiConnect and merges them into each term's history; the .apkg importer now merges the same way, so an Anki review older than LWT's latest is fitted in rather than skipped. Not yet run against a real AnkiConnect (worth one manual check before release). Remaining: step 2 (push LWT reviews to Anki, after checking whether Anki recomputes cards.data from inserted revlog) and step 3 (fields, tags, flags, existence via the sync base).

  6. added 3 commits that reference this issue on Nov 3, 2026
  7. HugoFara commented on Nov 3, 2026

    @HugoFara
    OwnerAuthor

    Done in develop. /vocabulary/anki/sync keeps LWT and Anki in step over AnkiConnect, following the spike in docs-src/developer/anki-sync-conflicts.md:

    Tested against a real headless Anki (scripts/anki/container, npm run anki:up, cypress/e2e/24-anki-live.cy.ts), FSRS on and off.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementDevelop an existing feature

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions