
- Use --locked to assert that the lockfile won't change, so we need to explicitly 'uv lock' when making changes. Still trying to get to the bottom of why the lockfile sometimes has editable entries, which break things when switching between platforms. - Exclude __pycache__ from wheels - Move the typing stubs to our dev deps (https://github.com/ankitects/anki/pull/4074#pullrequestreview-2948088436)
3 KiB
Claude Code Configuration
Project Overview
Anki is a spaced repetition flashcard program with a multi-layered architecture. Main components:
- Web frontend: Svelte/TypeScript in ts/
- PyQt GUI, which embeds the web components in aqt/
- Python library which wraps our rust Layer (pylib/, with Rust module in pylib/rsbridge)
- Core Rust layer in rslib/
- Protobuf definitions in proto/ that are used by the different layers to talk to each other.
Building/checking
./check (check.bat) will format the code and run the main build & checks. Please do this as a final step before marking a task as completed.
Quick iteration
During development, you can build/check subsections of our code:
- Rust: 'cargo check'
- Python: './tools/dmypy', and if wheel-related, './ninja wheels'
- TypeScript/Svelte: './ninja check:svelte'
Be mindful that some changes (such as modifications to .proto files) may need a full build with './check' first.
Build tooling
'./check' and './ninja' invoke our build system, which is implemented in build/. It takes care of downloading required deps and invoking our build steps.
Translations
ftl/ contains our Fluent translation files. We have scripts in rslib/i18n to auto-generate an API for Rust, TypeScript and Python so that our code can access the translations in a type-safe manner. Changes should be made to ftl/core or ftl/qt. Except for features specific to our Qt interface, prefer the core module. When adding new strings, confirm the appropriate ftl file first, and try to match the existing style.
Protobuf and IPC
Our build scripts use the .proto files to define our Rust library's non-Rust API. pylib/rsbridge exposes that API, and _backend.py exposes snake_case methods for each protobuf RPC that call into the API. Similar tooling creates a @generated/backend TypeScript module for communicating with the Rust backend (which happens over POST requests).
Fixing errors
When dealing with build errors or failing tests, invoke 'check' or one of the quick iteration commands regularly. This helps verify your changes are correct. To locate other instances of a problem, run the check again - don't attempt to grep the codebase.
Ignores
The files in out/ are auto-generated. Mostly you should ignore that folder, though you may sometimes find it useful to view out/{pylib/anki,qt/_aqt,ts/lib/generated} when dealing with cross-language communication or our other generated sourcecode.
Launcher/installer
The code for our launcher is in qt/launcher, with separate code for each platform.
Rust dependencies
Prefer adding to the root workspace, and using dep.workspace = true in the individual Rust project.
Rust utilities
rslib/{process,io} contain some helpers for file and process operations, which provide better error messages/context and some ergonomics. Use them when possible.
Rust error handling
in rslib, use error/mod.rs's AnkiError/Result and snafu. In our other Rust modules, prefer anyhow + additional context where appropriate. Unwrapping in build scripts/tests is fine.