moonlight-lupin/agent-skills/library-rag
Claude Code and agent skill by moonlight-lupin/agent-skills
- community
Checking that the SKILL.md file is still in the repository.
Semantic search over a personal library using Nemotron-3-Embed-1B embeddings + sqlite-vec. Index books, documents, any text corpus; query by meaning. Includes EPUB→Markdown conversion and MCP server for auto-available search tools.
Install
npx vskill@latest install moonlight-lupin/agent-skills/library-ragSKILL.md
Library RAG
Semantic search over ~/.hermes/library/ using Nemotron-3-Embed-1B embeddings (via NVIDIA NIM) stored in sqlite-vec. Enables meaning-based retrieval across any text corpus — books, documents, reference works — in any language.
Architecture
Onboarding workflow (run this the first time a user sets up the skill)
When a user wants to start using Library RAG, walk them through this sequence. Use AskUserQuestion for the decisions marked ASK — don't assume paths or silently create directories outside the home folder.
Step 1 — Check prerequisites
- If
sqlite-vecimport fails → runpip install -r requirements.txt(add
--break-system-packages on externally-managed Python). See README "Installation".
- If
NO API KEY→ help the user create a free NVIDIA NIM key at
<https://build.nvidia.com/nvidia/nemotron-3-embed-1b>, then store it: echo 'NVIDIA_API_KEY=nvapi-...' >> ~/.hermes/.env. (Legacy OpenRouter keys still work: if only OPENROUTER_API_KEY is set, load_api_key() auto-switches to the bge-m3 OpenRouter endpoint.)
Step 2 — Define directories (ASK)
Three locations drive everything. Confirm them with the user and export the env vars (persist in their shell profile). Defaults in parentheses:
| Purpose | Env var | Default | Notes | |
|---|---|---|---|---|
| Indexed content + vector DB | LIBRARY_ROOT | ~/.hermes/library | Holds the structured .md/.txt that get embedded, plus rag_index.db. | |
| Vector DB file | (derived) | $LIBRARY_ROOT/rag_index.db | Override per-run with rag_index.py --db <path> if you want it elsewhere. | |
| Raw books + conversion staging | BOOKS_DIR | ~/.hermes/book | Where original EPUBs/PDFs land and where text is extracted. |
Recommended layout (keep raw/text out of LIBRARY_ROOT — see pitfall below):
Pitfall — avoid double-indexing:discover_files()indexes every.mdand.txtunderLIBRARY_ROOT. If both the extracted.txtand the converted.mdof thesame book live underLIBRARY_ROOT, the content is embedded twice. Keep only onerepresentation (prefer the structured.md) underLIBRARY_ROOT; keep raw + text staginginBOOKS_DIRoutside it.
Create the chosen dirs:
Step 3 — Add the first content & build the index
- EPUB/PDF via MCP (if the server is configured): call
add_book(...)— it converts and
indexes in one step.
- Manual: drop source files in
$BOOKS_DIR/raw, convert to structured markdown under
$LIBRARY_ROOT/<source_type>/ (see convert_epub_library.py and references/epub-conversion.md), then:
Step 4 — Automated scanning/conversion/indexing (ASK)
Ask the user whether they want new files indexed automatically or manually:
- Manual (default, recommended to start): they run
python3 scripts/rag_index.py
after adding files. Incremental + SHA-256 tracking means re-runs are cheap and only touch new/changed files. No setup needed.
- Automated (cron): schedule a periodic incremental index. Only offer this once Step 3
works end-to-end. Example — index nightly at 02:00 and log output:
``bash # crontab -e (adjust the repo path and env vars) 0 2 * * * NVIDIA_API_KEY=nvapi-... LIBRARY_ROOT=$HOME/.hermes/library \ /usr/bin/python3 $HOME/library-rag/scripts/rag_index.py >> $HOME/.hermes/rag_index.log 2>&1 ``
If they also want EPUBs auto-converted before indexing, chain a conversion step ahead of rag_index.py in the same cron line (or a small wrapper script). On macOS, launchd / a launchd plist is the more reliable equivalent of cron.
Cron cautions to mention:
- Cron has a minimal environment — set
NVIDIA_API_KEY,LIBRARY_ROOT, and use an
absolute python3 path (or activate the venv inside a wrapper script).
- Never overlap two
--rebuildruns on the same DB (see Pitfalls). A nightly incremental
run is safe; a full --rebuild should stay manual.
- NIM embeddings are free on the NVIDIA free trial tier; the log still shows token usage.
After onboarding, summarize for the user: the three paths chosen, where the DB lives, and whether indexing is manual or scheduled.
MCP Tools (auto-available in every conversation)
Once configured in config.yaml, these tools are available as mcp_library_rag_search, mcp_library_rag_stats, mcp_library_rag_add_book.
Config
Restart the gateway after adding.
search
Returns JSON array of results with similarity, source_type, book, chapter, section_title, text.
stats
add_book
Converts EPUB → chapters or PDF → pages, then indexes them. One-call workflow for adding new books to the library.
Scripts (for batch operations)
rag_index.py — Indexer
When to use:
- After adding new files to the library → run incremental (default)
- After changing chunking strategy → run
--rebuild - To estimate cost/time → run
--dry-runfirst - After deleting/moving files out of the library → run
--prune-missing
(removes orphaned chunks + vectors so the DB doesn't keep dead rows; safe alongside incremental indexing — only files absent from disk are retired)
- After a
--rebuildor a large--prune-missing→ run--vacuumto shrink
the DB file (SQLite reuses freed pages but doesn't shrink the file otherwise)
rag_query.py — CLI Query
Can also be imported:
Conversion Tools
EPUB → Markdown (scripts/convert_epub_library.py)
Extracts text from EPUB files and splits into per-chapter Markdown with YAML frontmatter. Runnable as a CLI or importable as convert_epub() — the same implementation backs the MCP add_book tool, so there is one conversion code path.
Raw EPUB + extracted text stage under $BOOKS_DIR (outside LIBRARY_ROOT); only the structured markdown is written to --md-root, so the raw text is never double-indexed.
Chapter detection tries several styles (CHAPTER 12 / CHAPTER One / PART IV / 12. Title / bare 12\nTitle), picking the first that confidently applies, and guards against date/page-number false positives. Before trusting a conversion, eyeball convert_epub_library.audit_chapter_markers(text) — every entry should be a real chapter, not a date or page number.
Key pitfalls (see references/epub-conversion.md for full details):
- Multiple TOC ghosts: Large EPUBs produce multiple table-of-contents blocks. Skip all when finding chapter headings in body text.
- CHAPTER N vs N. Title: EPUBs use different heading patterns in TOC vs body. Match the BODY pattern.
- Title + subtitle leak into YAML: Use only the main title for the
title:field. - Slug truncation: Truncate slugs to 60 chars (preserving the
chNN-prefix). - Page-number blocks: Some EPUBs extract huge blocks of standalone page numbers. Detect and exclude.
- Post-processing pass: Always verify every
.mdfile has valid YAML frontmatter.
PDF → Markdown (scripts/convert_pdf_library.py)
Extracts text and tables with pdfplumber. Each page → a ## Page N section (so the markdown chunker yields per-page citations); tables → **[Table N]** blocks. CLI or convert_pdf(); it also backs add_book for .pdf inputs.
The table block is display-only: clean_for_embedding strips **[Table N]** and rows ending in <br> from the embedding input (the page's narrative text already carries the table content linearly), so tables stay searchable without being embedded twice.
Built-in chunkers (rag_index.py)
| Chunker | Input | Strategy | |
|---|---|---|---|
chunk_markdown() | .md with headings | Split by ##/### (a ### chunk carries its parent ## as a Section — Subsection breadcrumb), paragraph merge fallback, single-newline normalization | |
chunk_plain_text() | .txt files | Paragraph merge with 15% overlap |
For domain-specific formats (PDFs, XML, JSON), write a custom chunker and register it in discover_files(). See references/chunking-strategies.md for patterns.
Adding new books to the library
Quick path (EPUB/PDF via MCP)
Use mcp_library_rag_add_book — it dispatches on extension and handles EPUB/PDF → md → index in one call.
Manual path
- Convert to structured Markdown with the converter CLI for the format. Both stage
the raw file + extracted text under $BOOKS_DIR (outside LIBRARY_ROOT, so they're not indexed) and write markdown to --md-root:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingresearch/library-rag/SKILL.md
Popularity
- Repository stars
- 76
- Repository forks
- 12
- 7-day trend score
- 22
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/moonlight-lupin/agent-skills/library-rag)