@shbernal/pdfanki-cli
v0.3.0
Published
Create Anki decks from PDF and EPUB files using NLP with LLMs.
Maintainers
Readme
pdfanki
Create Anki decks from PDF/EPUB files using NLP with LLMs.
Installation
pnpm i -g @shbernal/pdfanki-cli
Requirements
- Node >=24
- Provider API keys via environment variables for API-backed providers:
GEMINI_API_KEY,ANTHROPIC_API_KEY,OPENAI_API_KEY,DEEPSEEK_API_KEY, orOPENROUTER_API_KEY - Optional experimental Codex provider: locally installed official
codexCLI with an existing login; pdfanki callscodex execand does not read Codex auth files directly
Config (XDG)
- Config dir:
$XDG_CONFIG_HOME/pdfanki/or~/.pdfanki/if unset - Auto-created on first run:
settings.jsonwith nestedoutput,generation, andepubsections.prompts/default.md: default prompt- you can select any
.mdin this dir as prompt.
- you can select any
Default settings.json shape:
{
"output": {
"path": ".",
"paths": {}
},
"generation": {
"defaultProvider": "gemini",
"defaultPrompt": "default",
"providers": {
"gemini": {
"defaultModel": "gemini-3-pro-preview"
},
"codex": {
"defaultModel": "gpt-5.4",
"reasoningEffort": "medium"
}
}
},
"epub": {
"preview": false,
"previewChars": 120,
"filters": {
"titles": [{ "type": "regex", "pattern": "^contents?$", "flags": "i" }]
}
}
}Usage
The CLI is organized by source type, then by target type:
pdfanki pdf <json|md|anki> <input>pdfanki epub <json|md|anki> <input>pdfanki json <md|anki> <input>pdfanki md anki <input>
Create an Anki deck from a PDF:
pdfanki pdf anki file.pdf --deck-title "Title"Use DeepSeek explicitly (with
DEEPSEEK_API_KEYset):pdfanki pdf md file.pdf --provider deepseek --model deepseek-chatUse OpenRouter explicitly (with
OPENROUTER_API_KEYset):pdfanki pdf md file.pdf --provider openrouter --model z-ai/glm-5Use the experimental local Codex CLI provider:
pdfanki pdf md file.pdf --provider codex --model gpt-5.4 --codex-reasoning-effort highExtract JSON from an EPUB section slice:
pdfanki epub json file.epub --start-section 3 --end-section 5 --min-char 300Extract JSON from an EPUB while skipping specific sections:
pdfanki epub json file.epub --exclude-sections "3,7,19,25-27"Extract JSON from an EPUB with section previews:
pdfanki epub json file.epub --previewExtract JSON from an EPUB with 200-char previews:
pdfanki epub json file.epub --preview 200Build an Anki deck from extracted JSON:
pdfanki json anki file.json --provider deepseek --model deepseek-reasonerBuild an Anki deck from existing markdown:
pdfanki md anki deck.mdList available prompts from the configured prompts directory:
pdfanki prompts listPrint the current
settings.jsonconfig to stdout:pdfanki configReset the local config directory to defaults:
pdfanki config resetSimulate extraction or markdown generation without writing files:
pdfanki pdf json file.pdf --dry-runInspect the file contents before passing it to an AI model :
pdfanki pdf json file.pdf- Use cases :
- Check if the file has been correctly separated in sections (for PDF, you'll often need an index file)
- Remove sections that have not been filtered using regex or minimum of characters
- Use cases :
Inspect the markdown flashcards before creating the deck :
pdfanki pdf md file.pdf- Use cases :
- Make editions to the AI model output
- Add images (option currently not supported by pdfanki)
- Compress flashcards with similar content (option currently not supported by pdfanki)
- Use cases :
Usage notes
Default outputs go to the current working directory with filenames derived from the input (
kebab-case).The
codexprovider is experimental. It pipes each section prompt intocodex exec --ephemeral --skip-git-repo-check, captures the final Markdown from stdout, and relies on your existing Codex CLI authentication rather thanOPENAI_API_KEY.Codex
defaultModelmaps tocodex exec --model, andreasoningEffortmaps to a per-runmodel_reasoning_effortconfig override. CLI flags--model,--codex-reasoning-effort, and--codex-profileoverridesettings.jsonwithout editing~/.codex/config.toml.Set
output.pathto change the default output directory for conversion commands.Set
output.paths.json,output.paths.md, oroutput.paths.apkgto route specific artifact types to dedicated directories.Use
-o, --outto override the final output path for any conversion command.Output path precedence is
--out, thenoutput.paths.<artifact>, thenoutput.path.--dry-runskips writing the requested output and failure artifact files, while keeping the normal terminal feedback.Successful
... ankicommands only write the requested.apkg. Partial markdown/debug files are written only when markdown generation fails.Log and UX controls:
--verbose: detailed per-section logs and provider/model diagnostics.--quiet/-q: warnings and errors only.--no-color: disable ANSI colors.--no-spinner: disable loading animations and progress rendering.
pdfanki index template 8 --from-file book.pdfgenerates./book.index.jsonby default.--index <path>expects a JSON array of chapter ranges for PDFs.titleis optional:[ { "start": 1, "end": 3, "title": "Introduction" }, { "start": 4, "end": 18 }, { "start": 19, "end": 35, "title": "Chapter 2" } ]--index-ranges "<start>-<end>,<start>-<end>"provides the same PDF section boundaries inline:--index-ranges "1-3,4-18,19-35"Pages are 1-based and inclusive;
start≤end. Each entry maps to one output section.Ranges must be in ascending order and must not overlap. Gaps are allowed.
--full-fidelityonpdfanki pdf jsonorpdfanki epub jsonwrites the unpruned extraction payload.--start-section <num>/--end-section <num>restrict EPUB extraction to a 1-based inclusive section range.--exclude-sections "<section>,<section>,<start>-<end>"skips specific EPUB sections by original 1-based section number.--min-char <num>filters out extracted sections with fewer than<num>characters.--previewprints a text preview under each EPUB section during parsing.--preview <num>or--preview-chars <num>sets the EPUB preview length. If no explicit value is provided and no config value is set, the default is120.PDFs only support filtering through
--indexor--index-ranges. EPUB section filtering uses--start-section/--end-section.
JSON shape for pdfanki json ...
The CLI accepts the same minimal JSON it writes with pdfanki pdf json / pdfanki epub json:
metadatais optional and ignored for model calls; omit it for the minimal shape.
{
"content": [
{ "index": 1, "title": "Chapter 1", "text": "..." },
{ "index": 2, "title": "Chapter 2", "text": "..." }
]
}