Anki Generator
A Ruby tool to generate Anki .apkg files from YAML definitions, Markdown notes, or CSV files — with AI-powered content generation (Gemini, OpenAI, Anthropic, OpenRouter, or local Ollama via ruby_llm), cloze deletions, tags, and a built-in web editor.
Features
- AI-Powered Generation: Create flashcards using any LLM provider supported by ruby_llm — Gemini, OpenAI, Anthropic, OpenRouter, or a local Ollama server — with multiple AI models
-
Markdown & CSV Import: Turn
Q:/A:study notes or spreadsheets into decks; Markdown headings become tags -
Cloze Deletion Cards:
{{cN::...}}deletions export as real Anki cloze notes (one card per deletion) -
Tags & Reverse Cards: Per-card tags in Anki, plus
--reversefor recognition + recall pairs -
Web UI:
anki_generator serveopens a localhost editor — paste notes, generate with AI, export.apkg - AnkiConnect Push: Send decks straight into a running Anki with the AnkiConnect addon
-
Parallel Generation:
--jobs Nfans one API call per topic out across threads - Reliable AI Output: Structured generation via ruby_llm Schematist schemas — cards come back as validated JSON, not prompt-honoured text
- File Attachment Support: Attach code files, documentation, or entire directories for context-aware generation
- Prompt File Support: Use text files as prompts for better organization and reusability
- Multiple Input Methods: Generate from YAML files, direct prompts, file attachments, Markdown, or CSV
- Intelligent Content Processing: Automatic text file detection, size limits, and binary file filtering
- Direct Prompt-to-Deck Generation: Create decks in one command without intermediate files
- Sync Functionality: Merge new AI-generated cards with existing decks
- Flexible Configuration: Multiple difficulty levels, context settings, model and provider selection
- Comprehensive CLI: Full command-line interface with extensive options
Installation
Requirements: Ruby 3.1 or higher
-
Clone the repository
-
Install dependencies:
bundle install
-
Set up your LLM API key (e.g. Google Gemini):
cp .env.example .env # Edit .env and add your GOOGLE_API_KEY (https://aistudio.google.com/apikey)
Usage
Quick Start - Generate from Prompt
The fastest way to create flashcards is directly from a prompt:
# Generate flashcards and create deck in one step (API key from .env)
./bin/anki_generator prompt_to_deck "Ruby programming basics" "Ruby Deck" ruby_deck.apkg
# Or pass the key explicitly (requires --provider)
./bin/anki_generator prompt_to_deck "Ruby programming basics" "Ruby Deck" ruby_deck.apkg --provider gemini --api_key YOUR_API_KEY
# Generate from a prompt file with code attachments
./bin/anki_generator prompt_to_deck study_prompt.txt "Code Study" code_deck.apkg --prompt_file --attach ./src
# Generate just the YAML file first
./bin/anki_generator generate_yaml "JavaScript fundamentals" js_cards.yaml --count 15
# Then create the deck
./bin/anki_generator generate "JS Deck" js_cards.yaml js_deck.apkgTraditional Usage
Generate a deck from a YAML file:
./bin/anki_generator generate "My Deck" input/input.yaml my_deck.apkgImport Markdown or CSV Notes
Turn existing study notes into a deck:
# Markdown: Q:/A: pairs or "- **question** — answer" bullets; headings become tags
./bin/anki_generator import "Biology" notes.md biology.apkg
# Add reversed (recall) cards for every basic card
./bin/anki_generator import "Biology" notes.md biology.apkg --reverse
# CSV: front,back[,tags] with pipe-separated tags
./bin/anki_generator import "Capitals" capitals.csv capitals.apkgWeb Editor
./bin/anki_generator serve # http://localhost:8787
./bin/anki_generator serve --port 9000
./bin/anki_generator serve --provider ollama # default AI generation in the UI to OllamaThe web editor is a local Sinatra app. Paste Markdown/YAML on the left, generate cards with AI, edit the table, export .apkg. --provider sets the default provider for AI generation in the UI; any provider-specific key still comes from the environment.
Push to a Running Anki
With the AnkiConnect addon installed in Anki:
./bin/anki_generator push "My Deck" cards.yaml
./bin/anki_generator push "My Deck" cards.yaml --url http://localhost:8765AI-Powered Generation
Create an AI generation template:
./bin/anki_generator create_ai_template my_ai_deck.yamlGenerate a deck with AI content:
./bin/anki_generator generate "AI Deck" my_ai_deck.yaml ai_deck.apkgAdvanced Options
# Use a specific AI model
./bin/anki_generator prompt_to_deck "Python basics" "Python Deck" python.apkg --model anthropic/claude-sonnet-4
# Set difficulty and count
./bin/anki_generator generate_yaml "Advanced algorithms" algo.yaml --difficulty hard --count 20
# Add context for better generation
./bin/anki_generator prompt_to_deck "Machine Learning" "ML Deck" ml.apkg --context "For computer science students" --difficulty medium
# Use prompt from file
./bin/anki_generator generate_yaml prompt.txt output.yaml --prompt_file
# Attach files for context
./bin/anki_generator prompt_to_deck "Explain this code" "Code Deck" code.apkg --attach src/main.rb --attach config.yml
# Attach entire directory
./bin/anki_generator generate_yaml "Create cards about this project" project.yaml --attach ./src --attach ./docs
# Combine file prompt with attachments
./bin/anki_generator prompt_to_deck prompt.txt "My Deck" deck.apkg --prompt_file --attach ./examples
# Save intermediate YAML file
./bin/anki_generator prompt_to_deck "React hooks" "React Deck" react.apkg --save_yaml
# Sync with existing deck
./bin/anki_generator generate "My Deck" input.yaml output.apkg --sync_with existing_deck.yaml
# Test API connection (uses the key from .env)
./bin/anki_generator test_api
# Test a specific provider with an explicit key
./bin/anki_generator test_api --provider openai --api_key YOUR_API_KEY
# Use a local Ollama model instead of a cloud provider (no API key needed)
./bin/anki_generator prompt_to_deck "Ruby basics" "Ruby" ruby.apkg --provider ollama --model llama3.2
# Generate one API call per topic, 4 at a time
./bin/anki_generator generate "AI Deck" ai.yaml out.apkg --jobs 4
# Basic + reversed cards from a YAML deck
./bin/anki_generator generate "My Deck" input.yaml out.apkg --reverseCLI Commands
prompt_to_deck - One-Step Generation
Generate flashcards from a prompt and create the deck immediately:
anki_generator prompt_to_deck PROMPT DECK_NAME OUTPUT_FILE [options]Options:
-
--attach FILE_OR_DIR [FILE_OR_DIR...]- Attach files or directories for context -
--prompt_file- Treat PROMPT as a file path to read from -
--save_yaml- Save intermediate YAML file -
--provider PROVIDER- LLM provider (gemini/openai/anthropic/openrouter/ollama/...); auto-resolved from the model when omitted -
--api_key API_KEY- Provider API key (requires--provider; otherwise the provider env var is used) -
--model MODEL- AI model to use -
--difficulty LEVEL- Difficulty level (easy, medium, hard) -
--count N- Number of flashcards to generate -
--context TEXT- Additional context for better generation
generate_yaml - Generate YAML from Prompt
Create a YAML file from a prompt for later use:
anki_generator generate_yaml PROMPT OUTPUT_YAML [options]Options:
-
--attach FILE_OR_DIR [FILE_OR_DIR...]- Attach files or directories for context -
--prompt_file- Treat PROMPT as a file path to read from -
--provider PROVIDER- LLM provider (gemini/openai/anthropic/openrouter/ollama/...); auto-resolved from the model when omitted -
--api_key API_KEY- Provider API key (requires--provider; otherwise the provider env var is used) -
--model MODEL- AI model to use -
--difficulty LEVEL- Difficulty level (easy, medium, hard) -
--count N- Number of flashcards to generate -
--context TEXT- Additional context for better generation
generate - Create Deck from YAML
Generate an Anki deck from an existing YAML file:
anki_generator generate DECK_NAME YAML_FILE OUTPUT_FILE [options]Options:
-
--reverse- Append a front↔back copy of every basic card -
--jobs N- Generate AI topics in parallel across N threads -
--sync_with YAML_FILE- Existing YAML file to merge with (skips duplicate fronts) -
--provider PROVIDER,--api_key API_KEY(requires--provider),--model MODEL
import - Import Markdown or CSV
Turn study notes into a deck:
anki_generator import DECK_NAME INPUT_FILE OUTPUT_FILE [options]Options:
-
--reverse- Append reversed copies of basic cards
Supports .md/.markdown (Q:/A: pairs, - **front** — back bullets, headings → tags) and .csv (front,back[,tags], tags pipe-separated).
push - Push to Anki
Send a YAML deck straight into a running Anki via AnkiConnect:
anki_generator push DECK_NAME YAML_FILE [options]Options:
-
--url URL- AnkiConnect endpoint (defaulthttp://localhost:8765)
serve - Web Editor
Start the localhost editor UI (Sinatra, default port 8787):
anki_generator serve [--port PORT] [--provider PROVIDER]--provider sets the default provider for AI generation in the UI.
create_ai_template - Create Template
Create a template YAML file for AI generation:
anki_generator create_ai_template TEMPLATE_FILE
test_api - Test Connection
Test your LLM connection:
anki_generator test_api [--provider PROVIDER] [--api_key API_KEY] [--model MODEL]File Attachments
The Anki Generator supports attaching files and directories to provide context for AI generation. This is particularly useful for:
- Creating flashcards about specific code files
- Generating questions based on documentation
- Learning from configuration files or data structures
- Creating study materials from existing project files
Supported File Types
The tool automatically processes text-based files including:
- Code files:
.rb,.py,.js,.ts,.java,.cpp,.c,.go,.rs, etc. - Documentation:
.md,.txt,.rst,.adoc,.org - Configuration:
.yaml,.yml,.json,.xml,.toml - Web files:
.html,.css,.scss - Scripts:
.sh,.bat,.ps1
File Size Limits
- Maximum individual file size: 1MB
- Maximum total attachment size: 5MB
- Files exceeding limits are automatically skipped with warnings
Usage Examples
# Attach a single file
./bin/anki_generator prompt_to_deck "Explain this Ruby class" "Ruby Deck" ruby.apkg --attach person.rb
# Attach multiple files
./bin/anki_generator generate_yaml "Create cards about these configs" config.yaml --attach database.yml --attach routes.rb --attach Gemfile
# Attach entire directories (processes all text files)
./bin/anki_generator prompt_to_deck "Study this codebase" "Project Deck" project.apkg --attach ./src --attach ./lib
# Combine with prompt files
./bin/anki_generator generate_yaml study_prompt.txt output.yaml --prompt_file --attach ./examples --attach README.md
# Use context and attachments together
./bin/anki_generator prompt_to_deck "Advanced Ruby patterns" "Advanced Ruby" advanced.apkg \
--attach ./lib --context "Focus on metaprogramming and DSL patterns" --difficulty hardHow Attachments Work
- File Processing: The tool scans attached files and directories for text-based content
- Content Inclusion: File contents are included in the AI prompt with clear file boundaries
- Smart Generation: The AI uses the file content to create more accurate and specific flashcards
- Automatic Filtering: Binary files and oversized files are automatically skipped
Best Practices
- Be Specific: Attach only relevant files to avoid overwhelming the AI with too much context
- Use Descriptive Prompts: Combine attachments with clear prompts about what you want to learn
- Organize Files: Group related files in directories for easier attachment
- Check File Sizes: Large files will be skipped, so break them down if needed
YAML Formats
Traditional Format
- front: "What is Big O notation?"
back: "Big O notation describes the limiting behavior of a function..."
tags: [complexity, cs]
- front: "Define a graph"
back: "A graph is a collection of vertices connected by edges"
# Cloze deletion — one card per {{cN::...}} ordinal
- cloze: "{{c1::Paris}} is the capital of {{c2::France}}"
tags: [geography]AI Generation Format
ai_generation:
topics:
- "Ruby programming fundamentals"
- "Object-oriented programming"
context: "Beginner-friendly programming concepts"
difficulty: "medium" # easy, medium, hard
count: 10
save_generated: true
# Optional manual cards
cards:
- front: "Manual question"
back: "Manual answer"Configuration
Environment Variables
-
GOOGLE_API_KEY/GEMINI_API_KEY: Your Google Gemini API key (default provider) -
OPENAI_API_KEY,ANTHROPIC_API_KEY,OPENROUTER_API_KEY: keys for the other cloud providers -
OLLAMA_URL: Ollama server URL (defaulthttp://localhost:11434) -
ANKI_GENERATOR_MODEL: Default model to use (optional, or pass--model)
Providers
AI generation is backed by the ruby_llm gem, so any provider it supports works. Omit --provider to auto-resolve from the model name, or pin one explicitly:
-
Gemini (default model
gemini-3.8-flash, no--providerneeded): Google's models, key fromGOOGLE_API_KEY/GEMINI_API_KEY -
OpenAI (
--provider openai):OPENAI_API_KEY -
Anthropic (
--provider anthropic):ANTHROPIC_API_KEY -
OpenRouter (
--provider openrouter): cloud aggregator,OPENROUTER_API_KEY -
Ollama (
--provider ollama): free, local, private — run any GGUF model on your machine with no API key
Supported Models
The tool supports all models available through the configured provider:
- Google:
gemini-3.8-flash(default),gemini-3.8-pro - OpenAI:
gpt-5,gpt-4o - Anthropic:
claude-sonnet-4,claude-haiku-4 - And many more (any model id the provider supports)
Examples
Quick Examples
# Generate 10 Python flashcards
./bin/anki_generator prompt_to_deck "Python data structures" "Python Deck" python.apkg
# Generate 20 hard-level algorithm cards
./bin/anki_generator generate_yaml "Sorting algorithms" algo.yaml --difficulty hard --count 20
# Create deck with context
./bin/anki_generator prompt_to_deck "React components" "React Deck" react.apkg --context "For beginners learning React"
# Study a specific code file
./bin/anki_generator prompt_to_deck "Create flashcards about this Ruby class" "Ruby Class Deck" ruby_class.apkg --attach person.rb
# Learn from project documentation
./bin/anki_generator generate_yaml "Study this API documentation" api_study.yaml --attach README.md --attach docs/api.md
# Comprehensive project study
./bin/anki_generator prompt_to_deck "Help me understand this codebase structure and patterns" "Codebase Study" study.apkg \
--attach ./src --attach ./lib --attach README.md --context "Focus on architecture and design patterns"File Attachment Examples
# Study a single Ruby file
./bin/anki_generator prompt_to_deck "What does this code do?" "Code Analysis" analysis.apkg --attach calculator.rb
# Learn from configuration files
./bin/anki_generator generate_yaml "Explain these configurations" config_study.yaml --attach config/database.yml --attach config/routes.rb
# Study an entire project
./bin/anki_generator prompt_to_deck "Create comprehensive study cards for this project" "Project Study" project.apkg \
--attach ./app --attach ./lib --attach Gemfile --attach README.md
# Use prompt file with attachments
echo "Create flashcards focusing on the class structure and methods in the attached files" > study_prompt.txt
./bin/anki_generator generate_yaml study_prompt.txt class_study.yaml --prompt_file --attach ./models
# Advanced usage with multiple options
./bin/anki_generator prompt_to_deck prompt_file.txt "Advanced Study" advanced.apkg \
--prompt_file --attach ./src --attach ./docs --difficulty hard --count 25 \
--context "Focus on advanced patterns and best practices" --save_yamlExample YAML Files
See the input/ directory for example YAML files, or create examples with rake examples:
-
examples/study_prompt.txt- Example prompt file -
examples/example_class.rb- Example Ruby code for attachments -
examples/manual_cards.yaml- Traditional format example -
input/ai_generation_example.yaml- AI generation example -
input/algorithms_ai.yaml- Computer science topics -
input/input.yaml.example- Traditional format
Development
Quick Start for Developers
The repo pins Ruby via .ruby-version (3.3). With rbenv/asdf installed:
# Clone and setup
git clone <repository-url>
cd anki_generator
rake setup # Install dependencies and create examples
# Run tests (coverage report in coverage/, 75% line floor enforced)
rake test # Run all tests
rake test_file[cli] # Run specific test
# Lint (zero offenses enforced — CI fails otherwise)
rake lint
rake lint_fix # Auto-correct safe offenses
# Try the examples
rake demo_api # Test API connection
rake examples # Create example files
rake demo_attachments # Demo with file attachmentsGitHub Actions CI/CD
The project includes GitHub Actions workflows:
-
ruby.yml- Main CI pipeline: tests on Ruby 3.1–3.4 plus a RuboCop lint gate -
release.yml- Automated releases when tags are pushed -
manual-test.yml- Manual workflow for testing specific scenarios
To trigger a release:
git tag v1.4.0
git push origin v1.4.0Running Tests
# Run all tests (SimpleCov runs by default; the suite fails below 75% line coverage)
rake test
# Run specific test file
rake test_file[cli] # runs tests/test_cli.rb
rake test_file[file_processor] # runs tests/test_file_processor.rbDevelopment Commands
# Setup development environment
rake setup # Install deps and create examples
# Build and install
rake build # Build gem
rake install_local # Build and install gem locally
rake clean # Clean build artifacts
# Code quality
rake lint # Run RuboCop linter
rake lint_fix # Auto-fix linting issues
# Demos and examples
rake examples # Create example files
rake demo_prompt # Demo prompt generation
rake demo_attachments # Demo file attachment features
rake demo_api # Test API connection
# Utilities
rake help # Show CLI help
rake version # Show version info
rake changelog # Show changelog for current version
rake release_prep # Prepare for releaseProject Structure
├── lib/anki_generator/
│ ├── deck_builder.rb # Deck assembly: YAML loading, AI generation, sync
│ ├── card.rb # Card value object (basic + cloze, tags, reverse)
│ ├── apkg_writer.rb # Native .apkg (zip + SQLite) writer
│ ├── apkg_schema.rb # Anki collection schema and model JSON
│ ├── apkg_exporter.rb # .apkg export for the web UI download
│ ├── cli.rb # Thor CLI (thin shell over Commands::*)
│ ├── commands/ # One service object per CLI command
│ ├── importers/ # Markdown and CSV note importers
│ ├── llm_client.rb # Provider-agnostic LLM client (ruby_llm gem)
│ ├── client_factory.rb # Builds the LLM client (any ruby_llm provider)
│ ├── card_schema.rb # Schematist schemas for structured LLM output
│ ├── anki_connect_client.rb # Push decks into a running Anki
│ ├── server.rb # Sinatra app for the web editor
│ ├── prompt_builder.rb # Prompt construction
│ └── file_processor.rb # File attachment processing
├── bin/
│ └── anki_generator # CLI executable
├── tests/ # Test files
├── input/ # Example YAML files
└── README.md
API Integration
The tool integrates with the ruby_llm gem to provide access to multiple AI providers and models. You can:
- Generate flashcards on any topic
- Specify difficulty levels
- Provide context for better generation
- Choose from various AI models
- Control the number of cards generated
Sync Functionality
The sync feature allows you to:
- Merge new AI-generated cards with existing manual cards
- Prevent duplicate cards (based on front text)
- Maintain version control of your flashcard sets
- Incrementally build large decks
Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Update CHANGELOG.md with your changes
- Submit a pull request
Changelog
See CHANGELOG.md for detailed version history and changes.
License
MIT License - see LICENSE file for details.