README
Google NotebookLM research assistant. Queries NotebookLM notebooks for source-grounded, citation-backed answers. Uses Patchright (a Playwright fork with anti-detection) for reliable browser automation. A virtual environment is created automatically on first run.
Prerequisites
| Dependency | Install | Purpose |
|---|---|---|
| Python 3.9+ | required | runtime |
| Google account | required | NotebookLM authentication |
| Chrome / Chromium | installed by Patchright | browser automation |
No manual pip install is needed — run.py creates .venv and installs all packages automatically on first use.
Scripts
All scripts live in scripts/python/. Always use run.py as the entry point — never call scripts directly.
| File | Purpose |
|---|---|
scripts/python/run.py | Entry point: creates venv, installs deps, runs any script |
scripts/python/auth_manager.py | Google authentication setup and status check |
scripts/python/notebook_manager.py | List, add, and activate notebooks |
scripts/python/ask_question.py | Query the active notebook with a question |
Quick Start
# 1. Check or set up authentication (one-time)
python scripts/python/run.py auth_manager.py status
python scripts/python/run.py auth_manager.py setup # if not authenticated
# 2. List your notebooks
python scripts/python/run.py notebook_manager.py list
# 3. Activate a notebook
python scripts/python/run.py notebook_manager.py activate --id <notebook-id>
# 4. Ask a question
python scripts/python/run.py ask_question.py --question "What does the architecture document say about caching?"
Authentication
Authentication stores a session in .notebooklm_session/. Run auth_manager.py setup once and follow the interactive browser login. Sessions persist across queries until they expire.
Dependencies (auto-installed by run.py)
patchright— Playwright fork with stealth capabilitiesplaywright— browser automation base
SKILL.md
Query Google NotebookLM notebooks for source-grounded, citation-backed answers. Each question opens a fresh browser session, retrieves the answer from uploaded documents only, and closes. Uses Patchright (Playwright fork with anti-detection) for reliable browser automation.
When to Activate
- User mentions NotebookLM or shares a NotebookLM URL (
https://notebooklm.google.com/notebook/...) - User asks to query notebooks or documentation
- User wants to add documentation to the NotebookLM library
- User wants to generate Audio Overviews, study guides, FAQs, or other outputs
- User uses phrases like “ask my NotebookLM”, “check my docs”, “query my notebook”
Skip When
- User wants general web search — use WebSearch directly
- User wants to query this project’s own codebase — use codi-codebase-explore
- User wants to upload new documents to NotebookLM — that is a manual step in the web UI; this skill only queries
- User wants to convert audio to text — use codi-audio-transcriber (Whisper) instead of NotebookLM Audio Overviews
Critical: Always Use run.py Wrapper
NEVER call scripts directly. ALWAYS use python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]]:
# CORRECT — always use run.py:
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] auth_manager.py status
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] notebook_manager.py list
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] ask_question.py --question "..."
# WRONG — never call directly:
python ${CLAUDE_SKILL_DIR}[[/scripts/python/auth_manager.py]] status # Fails without venv!
The run.py wrapper creates .venv if needed, installs dependencies, and runs scripts in the correct environment.
Decision Flow
User mentions NotebookLM
|
v
Check auth --> python run.py auth_manager.py status
|
v
If not authenticated --> python run.py auth_manager.py setup
|
v
Check/Add notebook --> python run.py notebook_manager.py list/add
|
v
Activate notebook --> python run.py notebook_manager.py activate --id ID
|
v
Ask question --> python run.py ask_question.py --question "..."
|
v
See follow-up reminder --> Ask follow-ups until information is complete
|
v
Synthesize all answers and respond to user
Core Workflow
Step 1: Check Authentication Status
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] auth_manager.py status
If not authenticated, proceed to setup.
Step 2: Authenticate (One-Time Setup)
# Browser opens VISIBLE for manual Google login
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] auth_manager.py setup
Tell the user: “A browser window will open for Google login. Sign in to your Google account.”
- Browser is VISIBLE for authentication (not headless)
- User must manually log in to Google
- Auth state persists via browser profile + cookie injection (handles Playwright session cookie bug)
- Re-authenticate if needed:
auth_manager.py reauth
Step 3: Manage Notebook Library
# List all notebooks
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] notebook_manager.py list
# Add notebook — ALL parameters are REQUIRED
python ${CLAUDE_SKILL_DIR}[[/scripts/python/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 notebooks by topic
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] notebook_manager.py search --query "keyword"
# Set active notebook
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] notebook_manager.py activate --id notebook-id
# Remove notebook
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] notebook_manager.py remove --id notebook-id
# Library statistics
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] notebook_manager.py stats
Smart Add (Recommended)
When the user wants to add a notebook without providing details, query it first to discover content:
# Step 1: Query the notebook about its content
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] ask_question.py \
--question "What is the content of this notebook? What topics are covered? Provide a brief overview." \
--notebook-url "[URL]"
# Step 2: Use the discovered information to add it
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] notebook_manager.py add \
--url "[URL]" --name "[Based on content]" \
--description "[Based on content]" --topics "[Based on content]"
NEVER guess or use generic descriptions. If details are missing, use Smart Add to discover them.
Step 4: Ask Questions
# Basic query (uses active notebook if set)
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] ask_question.py --question "Your question here"
# Query specific notebook by ID
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] ask_question.py --question "..." --notebook-id notebook-id
# Query with notebook URL directly
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] ask_question.py --question "..." --notebook-url "https://..."
# Show browser for debugging
python ${CLAUDE_SKILL_DIR}[[/scripts/python/run.py]] ask_question.py --question "..." --show-browser
Follow-Up Mechanism (Critical)
Every NotebookLM answer ends with a follow-up reminder. When you receive it:
- STOP — do not immediately respond to the user
- ANALYZE — compare the answer to the user’s original request
- IDENTIFY GAPS — check if more information is needed
- ASK FOLLOW-UP — if gaps exist, ask another question with full context (each question opens a new browser session, so include all necessary context)
- REPEAT — continue until information is complete
- SYNTHESIZE — combine all answers into a comprehensive response before presenting to the user
Script Reference
Authentication (auth_manager.py)
python run.py auth_manager.py setup # Initial setup (browser visible)
python run.py auth_manager.py status # Check authentication
python run.py auth_manager.py reauth # Re-authenticate (browser visible)
python run.py auth_manager.py validate # Validate auth works
python run.py auth_manager.py clear # Clear authentication
Notebook Library (notebook_manager.py)
python run.py notebook_manager.py add --url URL --name NAME --description DESC --topics TOPICS
python run.py notebook_manager.py list
python run.py notebook_manager.py search --query QUERY
python run.py notebook_manager.py activate --id ID
python run.py notebook_manager.py remove --id ID
python run.py notebook_manager.py stats
Questions (ask_question.py)
python run.py ask_question.py --question "..." [--notebook-id ID] [--notebook-url URL] [--show-browser]
Cleanup (cleanup_manager.py)
python run.py cleanup_manager.py # Preview cleanup
python run.py cleanup_manager.py --confirm # Execute cleanup
python run.py cleanup_manager.py --preserve-library # Keep notebooks
Environment Management
The virtual environment is automatically managed by run.py:
- First run creates
.venvin the skill directory - Dependencies install automatically (patchright, python-dotenv)
- Chromium browser installs automatically via patchright
- Everything is isolated in the skill directory
Data Storage
All data stored in ${CLAUDE_SKILL_DIR}/data/:
library.json— notebook metadata and libraryauth_info.json— authentication statusbrowser_state/— browser cookies, session, and profile
Protected by .gitignore — never commit to git.
Configuration
Copy ${CLAUDE_SKILL_DIR}[[/scripts/.env.example]] to the skill root as .env and adjust:
cp ${CLAUDE_SKILL_DIR}[[/scripts/.env.example]] ${CLAUDE_SKILL_DIR}/.env
Available settings (all optional):
HEADLESS=true # Run browser in headless mode
SHOW_BROWSER=false # Always show browser window (overrides HEADLESS)
STEALTH_ENABLED=true # Human-like typing behavior
TYPING_WPM_MIN=160 # Typing speed range (words per minute)
TYPING_WPM_MAX=240
DEFAULT_NOTEBOOK_ID= # Default notebook when none is specified
Troubleshooting
| Problem | Solution |
|---|---|
| ModuleNotFoundError | Use run.py wrapper — never call scripts directly |
| Authentication fails | Browser must be visible for setup: auth_manager.py setup |
| Rate limit (50/day) | Wait or switch Google account |
| Browser crashes | cleanup_manager.py --preserve-library then retry |
| Notebook not found | Check with notebook_manager.py list |
| Timeout waiting for answer | Use --show-browser to debug, check notebook has sources |
| State expired (7+ days) | Run auth_manager.py reauth |
For detailed troubleshooting, read ${CLAUDE_SKILL_DIR}[[/references/troubleshooting.md]].
Limitations
- No session persistence (each question = new browser session)
- Rate limits on free Google accounts (~50 queries/day)
- User must add documents to NotebookLM manually (the skill queries, not uploads)
- Browser overhead (few seconds per question)
- Audio Overview generation requires browser-based interaction (not scriptable)
Resources
${CLAUDE_SKILL_DIR}[[/references/api_reference.md]]— detailed API docs for all scripts${CLAUDE_SKILL_DIR}[[/references/troubleshooting.md]]— common issues and solutions${CLAUDE_SKILL_DIR}[[/references/usage_patterns.md]]— workflow examples and best practices${CLAUDE_SKILL_DIR}[[/references/authentication.md]]— hybrid auth architecture explanation