| Crates.io | ankiconnect-rs |
| lib.rs | ankiconnect-rs |
| version | 1.0.0 |
| created_at | 2025-01-25 11:56:40.545521+00 |
| updated_at | 2025-04-04 13:03:00.185625+00 |
| description | A package for convenient interaction with AnkiConnect. |
| homepage | |
| repository | https://github.com/btrkeks/ankiconnect-rs.git |
| max_upload_size | |
| id | 1530533 |
| size | 231,823 |
A work-in-progress Rust crate for interacting with AnkiConnect, enabling convenient programmatic control of Anki from within Rust applications. Provides type-safe abstractions for common Anki operations with a clean domain-driven API.
Add this to your Cargo.toml:
[dependencies]
ankiconnect-rs = "1.0.0"
localhost:8765)The crate is organized around a central AnkiClient that provides access to domain-specific clients:
client.cards() - Operations for notes and cards (add notes, find cards, etc.)client.decks() - Operations for decks (create, list, get stats, etc.)client.models() - Operations for note types (get fields, templates, etc.)client.media() - Operations for media files (store, retrieve, etc.)use ankiconnect_rs::{AnkiClient, DuplicateScope, NoteBuilder};
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
// Create a client with default connection (localhost:8765)
let client = AnkiClient::new();
// Get available decks and models
let decks = client.decks().get_all()?;
let models = client.models().get_all()?;
// Build a note with the selected model
let selected_model = &models[0];
let front_field = selected_model.field_ref("Front").unwrap();
let back_field = selected_model.field_ref("Back").unwrap();
let note = NoteBuilder::new(selected_model.clone())
.with_field(front_field, "¿Dónde está la biblioteca?")
.with_field(back_field, "Where is the library?")
.with_tag("spanish-vocab")
.build()?;
// Add the note to the first deck
let note_id = client.cards().add_note(&decks[0], note, false, None)?;
println!("Added note with ID: {}", note_id.value());
Ok(())
}
use ankiconnect_rs::{AnkiClient, MediaSource, NoteBuilder};
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let client = AnkiClient::new();
let decks = client.decks().get_all()?;
let models = client.models().get_all()?;
let selected_model = &models[0];
let front_field = selected_model.field_ref("Front").unwrap();
let back_field = selected_model.field_ref("Back").unwrap();
let note = NoteBuilder::new(selected_model.clone())
.with_field(front_field, "Dog")
.with_field(back_field, "A friendly animal")
.with_tag("animals")
// Add an image to the front field
.with_image(
front_field,
MediaSource::Url("https://example.com/dog.jpg".to_string()),
"dog.jpg"
)
.build()?;
client.cards().add_note(&decks[0], note, false, None)?;
Ok(())
}
use ankiconnect_rs::{AnkiClient, QueryBuilder, CardState};
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let client = AnkiClient::new();
// Build a complex search query
let query = QueryBuilder::new()
.in_deck("Japanese::Vocabulary")
.and()
.field("Front").contains("犬")
.and()
.not()
.in_state(CardState::Suspended)
.build();
// Find cards matching the query
let cards = client.cards().find(&query)?;
println!("Found {} matching cards", cards.len());
Ok(())
}
See the examples directory for more complete examples:
list_decks.rs - Listing decks and their informationlist_models.rs - Listing models (note types) and their fieldsadd_note.rs - Interactive example of adding a note with mediaLicensed under either of:
at your option.
Contributions welcome! Please feel free to submit a Pull Request.