Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Query Google NotebookLM notebooks for source-grounded, citation-backed answers from user-uploaded documents. Manages notebook library, handles Google authentication, and supports smart discovery. Works standalone via /blog notebooklm or internally from blog-write and blog-researcher for source-grounded research context. Falls back gracefully when not configured. Use when user says "notebooklm", "notebook", "query notebook", "ask notebook", "notebook research", "source grounded research", "docume
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 321% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 74% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 72% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 103% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 288% | 0% |
Query Google NotebookLM notebooks directly from Claude Code for citation-backed answers from Gemini. Each question opens a headless browser session, retrieves the answer from your uploaded documents, and closes. Responses are source-grounded model answers, not proof of truth: uploaded documents may be primary or secondary, and the answer can still omit context.
Answers satisfy the FLOW evidence triple only when the returned citation includes a verifiable underlying source URL plus a publication or retrieval date. Use the underlying source title as the inline citation. Do not cite the private NotebookLM URL as the bibliography entry for public content.
| Command | What it does | |---------|-------------| | /blog notebooklm ask <question> | Query a notebook for source-grounded answers | | /blog notebooklm discover <url> | Smart-discover notebook content before cataloging | | /blog notebooklm library list | List all notebooks in library | | /blog notebooklm library add <url> | Add a notebook to library | | /blog notebooklm library search <query> | Search notebooks by keyword | | /blog notebooklm library remove <id> | Remove a notebook from library | | /blog notebooklm setup | One-time Google authentication (browser visible) | | /blog notebooklm status | Check authentication status | | /blog notebooklm cleanup | Clean browser state (preserves library) |
run.py)NEVER call scripts directly. ALWAYS use python3 scripts/run.py [script]:
bash# CORRECT: python3 scripts/run.py auth_manager.py status python3 scripts/run.py ask_question.py --question "..." # Do not call files under scripts/ directly. The wrapper owns venv setup.
The run.py wrapper automatically creates .venv, installs dependencies, sets up Chrome, and executes the target script.
Before any query operation, check authentication:
bashpython3 scripts/run.py auth_manager.py status
"NotebookLM requires Google login. Run /blog notebooklm setup to authenticate."
with no error if not authenticated. Never block the writing workflow.
For /blog notebooklm setup:
bash# Opens a visible browser for manual Google login (one-time) python3 scripts/run.py auth_manager.py setup
Tell the user: "A browser window will open. Please log in to your Google account." Authentication persists via browser profile + cookie injection (hybrid approach).
Other auth commands:
bashpython3 scripts/run.py auth_manager.py status # Check auth python3 scripts/run.py auth_manager.py reauth # Re-authenticate python3 scripts/run.py auth_manager.py clear # Clear all auth data
For /blog notebooklm ask <question>:
Run auth check (see gate pattern above). If not authenticated, guide to setup.
Determine which notebook to query:
--notebook-url provided: validate it is a NotebookLM notebook URL, then use it--notebook-id provided: look up in librarybash# Basic query (uses active notebook) python3 scripts/run.py ask_question.py --question "Your question here" # Query specific notebook by ID python3 scripts/run.py ask_question.py --question "..." --notebook-id notebook-id # Query by URL directly python3 scripts/run.py ask_question.py --question "..." --notebook-url "https://..." # JSON output (for internal/programmatic use) python3 scripts/run.py ask_question.py --question "..." --json # Show browser for debugging python3 scripts/run.py ask_question.py --question "..." --show-browser
Every response ends with a follow-up prompt. Required behavior:
For /blog notebooklm discover <url>:
When adding a notebook without knowing its content, query it first:
bash# Step 1: Discover content python3 scripts/run.py ask_question.py \ --question "What is the content of this notebook? What topics are covered? Provide a complete overview briefly and concisely" \ --notebook-url "<URL>" # Step 2: Add with discovered metadata python3 scripts/run.py notebook_manager.py add \ --url "<URL>" \ --name "<Based on content>" \ --description "<Based on content>" \ --topics "<Extracted topics>"
NEVER guess or use generic descriptions. Always discover or ask the user.
bash# List all notebooks python3 scripts/run.py notebook_manager.py list # Add notebook (all params required -- discover or ask user!) python3 scripts/run.py notebook_manager.py add \ --url "https://notebooklm.google.com/notebook/..." \ --name "Descriptive Name" \ --description "What this notebook contains" \ --topics "topic1,topic2,topic3" # Search by keyword python3 scripts/run.py notebook_manager.py search --query "keyword" # Set active notebook python3 scripts/run.py notebook_manager.py activate --id notebook-id # Remove notebook python3 scripts/run.py notebook_manager.py remove --id notebook-id # Library statistics python3 scripts/run.py notebook_manager.py stats
When invoked as a Task subagent from blog-write or blog-researcher:
Input (provided by calling skill):
question: Research question relevant to the blog topicnotebook_id or notebook_url: Which notebook to querycontext: "internal" (signals graceful fallback mode)Process:
Output (returned to calling skill):
markdown### NotebookLM Research - **Source:** [Notebook name] - **Question:** [What was asked] - **Answer:** [Source-grounded response from user's documents] - **Underlying Source:** [Public source URL or document identifier] - **Underlying Source Date:** [Publication date or retrieval date] - **Source Quality:** [Tier 1-3 after classifying the underlying document]
Graceful fallback: If auth is missing or query fails, return immediately with no error. The calling workflow continues with WebSearch-based research. Never block blog-write or blog-rewrite because NotebookLM is unavailable.
All data stored inside the skill directory:
data/library.json: Notebook metadata and librarydata/auth_info.json: Authentication statusdata/browser_state/: Chrome profile with cookiesSecurity: All data directories are gitignored. Never commit auth or browser state.
| Error | Resolution | |-------|-----------| | Not authenticated | Run /blog notebooklm setup | | ModuleNotFoundError | Always use run.py wrapper | | Browser crash | cleanup_manager.py --confirm --preserve-library, then re-auth | | Rate limit (50/day) | Wait until midnight PST or switch Google account | | Notebook not found | Check with notebook_manager.py list | | Query timeout (120s) | Retry with simpler question or --show-browser to debug | | MCP unavailable (internal) | Return silently: writing workflow uses WebSearch |
Load on-demand: do NOT load all at startup:
references/commands.md: Full CLI commands, parameters, and workflow patternsreferences/troubleshooting.md: Error solutions, recovery procedures, debuggingOther measured skills in the registry, with their headline benchmark lift.