Nblm
magicseek/nblmThis skill enables users to efficiently manage Google NotebookLM notebooks and sources, generate citations-backed answers, and add various media content. It offers key capabilities such as creating, renaming, summarizing, and deleting notebooks, as well as uploading and managing sources like URLs, files, and media. Ideal for researchers, students, and knowledge workers, it streamlines organizing and querying large collections of knowledge sources.
NotebookLM Quick Commands
Query Google NotebookLM for source-grounded, citation-backed answers.
Environment
All dependencies and authentication are handled automatically by run.py:
- First run creates
.venvand installs Python/Node.js dependencies - If Google auth is missing or expired, a browser window opens automatically
- No manual pre-flight steps required
Usage
/nblm <command> [args]
Commands
Notebook Management
Command
Description
login
Authenticate with Google
status
Show auth and library status
accounts
List all Google accounts
accounts add
Add a new Google account
accounts switch <id>
Switch active account (by index or email)
accounts remove <id>
Remove a Google account
accounts use <id>
Set agent-specific active account (OpenClaw isolation)
accounts clear
Clear agent-specific account override
local
List notebooks in local library
remote
List all notebooks from NotebookLM API
create <name>
Create a new notebook
delete [--id ID]
Delete a notebook
rename <name> [--id ID]
Rename a notebook
summary [--id ID]
Get AI-generated summary
describe [--id ID]
Get description and suggested topics
add <url-or-id>
Add notebook to local library (auto-detects URL vs notebook ID)
activate <id>
Set active notebook
Source Management
Command
Description
sources [--id ID]
List sources in notebook
upload <file>
Upload a single file
upload <folder>
Sync a folder of files to NotebookLM
upload-zlib <url>
Download from Z-Library and upload
upload-url <url>
Add URL as source
upload-youtube <url>
Add YouTube video as source
upload-text <title> [--content TEXT]
Add text as source
source-text <source-id>
Get full indexed text
source-guide <source-id>
Get AI summary and keywords
source-rename <source-id> <name>
Rename a source
source-refresh <source-id>
Re-fetch URL content
source-delete <source-id>
Delete a source
Upload options:
--use-active- Upload to the currently active notebook--create-new- Create a new notebook named after the file/folder--notebook-id <id>- Upload to a specific notebook--dry-run- Show sync plan without executing (folder sync)--rebuild- Force rebuild tracking file (folder sync) Important: When user runs upload without specifying a target, ASK them first:
"Would you like to upload to the active notebook, or create a new notebook?" Then pass the appropriate flag (
--use-activeor--create-new).
Chat & Audio/Media
Command
Description
ask <question>
Query NotebookLM
podcast [--instructions TEXT]
Generate audio podcast
podcast-status <task-id>
Check podcast generation status
podcast-download [output-path]
Download latest podcast
briefing [--instructions TEXT]
Generate brief audio summary
debate [--instructions TEXT]
Generate debate-style audio
slides [--instructions TEXT]
Generate slide deck
slides-download [output-path]
Download slide deck as PDF
infographic [--instructions TEXT]
Generate infographic
infographic-download [output-path]
Download infographic
media-list [--type TYPE]
List generated media (audio/video/slides/infographic)
media-delete <id>
Delete a generated media item
Command Routing
Based on $ARGUMENTS, execute the appropriate command:
$IF($ARGUMENTS, Parse the command from: "$ARGUMENTS"
login → python scripts/run.py auth_manager.py setup --service google
accounts → python scripts/run.py auth_manager.py accounts list
accounts add → python scripts/run.py auth_manager.py accounts add
accounts switch → python scripts/run.py auth_manager.py accounts switch "<id>"
accounts remove → python scripts/run.py auth_manager.py accounts remove "<id>"
accounts use → python scripts/run.py auth_manager.py accounts use "<id>"
accounts clear → python scripts/run.py auth_manager.py accounts clear
status → Run both:
python scripts/run.py auth_manager.py statuspython scripts/run.py notebook_manager.py listlocal →python scripts/run.py notebook_manager.py listremote →python scripts/run.py nblm_cli.py notebookscreate →python scripts/run.py nblm_cli.py create "<name>"delete [--id ID] →python scripts/run.py nblm_cli.py delete <args>rename [--id ID] →python scripts/run.py nblm_cli.py rename "<name>" <args>summary [--id ID] →python scripts/run.py nblm_cli.py summary <args>describe [--id ID] →python scripts/run.py nblm_cli.py describe <args>add → Smart add workflow (auto-detects URL vs notebook ID) activate →python scripts/run.py notebook_manager.py activate --id "<id>"sources [--id ID] →python scripts/run.py nblm_cli.py sources <args>upload → First ASK user: "Upload to active notebook or create new?" Then: - Active:python scripts/run.py source_manager.py add --file "<file>" --use-active- New:python scripts/run.py source_manager.py add --file "<file>" --create-newupload → Sync a folder: - First ASK user: "Sync to active notebook, create new, or specify notebook?" - Active:python scripts/run.py source_manager.py sync "<folder>" --use-active- New:python scripts/run.py source_manager.py sync "<folder>" --create-new- Specific:python scripts/run.py source_manager.py sync "<folder>" --notebook-id ID- Dry-run:python scripts/run.py source_manager.py sync "<folder>" --dry-run- Rebuild:python scripts/run.py source_manager.py sync "<folder>" --rebuildupload-zlib → First ASK user: "Upload to active notebook or create new?" Then: - Active:python scripts/run.py source_manager.py add --url "<url>" --use-active- New:python scripts/run.py source_manager.py add --url "<url>" --create-newupload-url →python scripts/run.py nblm_cli.py upload-url "<url>"upload-youtube →python scripts/run.py nblm_cli.py upload-youtube "<url>"upload-text →python scripts/run.py nblm_cli.py upload-text "<title>" <args>source-text →python scripts/run.py nblm_cli.py source-text "<id>"source-guide →python scripts/run.py nblm_cli.py source-guide "<id>"source-rename →python scripts/run.py nblm_cli.py source-rename "<id>" "<name>"source-refresh →python scripts/run.py nblm_cli.py source-refresh "<id>"source-delete →python scripts/run.py nblm_cli.py source-delete "<id>"ask →python scripts/run.py nblm_cli.py ask "<question>"podcast →python scripts/run.py artifact_manager.py generate --format DEEP_DIVE <args>podcast-status →python scripts/run.py artifact_manager.py status --task-id "<task-id>"podcast-download [output-path] →python scripts/run.py artifact_manager.py download "<output-path>"briefing →python scripts/run.py artifact_manager.py generate --format BRIEF <args>debate →python scripts/run.py artifact_manager.py generate --format DEBATE <args>slides →python scripts/run.py artifact_manager.py generate-slides <args>slides-download [output-path] →python scripts/run.py artifact_manager.py download "<output-path>" --type slide-deckinfographic →python scripts/run.py artifact_manager.py generate-infographic <args>infographic-download [output-path] →python scripts/run.py artifact_manager.py download "<output-path>" --type infographicmedia-list [--type TYPE] →python scripts/run.py artifact_manager.py list <args>media-delete →python scripts/run.py artifact_manager.py delete "<id>"If command not recognized, show usage help., Show available commands with/nblm(no arguments) )
Podcast Options
/nblm podcast --length DEFAULT --wait --output ./podcast.mp3
/nblm podcast --instructions "Focus on the key findings"
/nblm briefing --wait --output ./summary.mp3
/nblm debate --instructions "Compare the two approaches"
Option
Values
--length
SHORT, DEFAULT, LONG
--instructions
Custom instructions for the content
--wait
Wait for generation to complete
--output
Download path (requires --wait)
Slide Deck Options
/nblm slides --format DETAILED_DECK --wait --output ./presentation.pdf
/nblm slides --instructions "Focus on key diagrams" --format PRESENTER_SLIDES
Option
Values
--format
DETAILED_DECK, PRESENTER_SLIDES
--length
SHORT, DEFAULT
--instructions
Custom instructions for the content
--wait
Wait for generation to complete
--output
Download path (requires --wait)
Infographic Options
/nblm infographic --orientation LANDSCAPE --wait --output ./visual.png
/nblm infographic --instructions "Highlight comparison" --detail-level DETAILED
Option
Values
--orientation
LANDSCAPE, PORTRAIT, SQUARE
--detail-level
CONCISE, STANDARD, DETAILED
--instructions
Custom instructions for the content
--wait
Wait for generation to complete
--output
Download path (requires --wait)
Media Generation
Command
Description
Output
/nblm podcast
Deep-dive audio discussion
MP3
/nblm briefing
Brief audio summary
MP3
/nblm debate
Debate-style audio
MP3
/nblm slides
Slide deck presentation
PDF
/nblm infographic
Visual infographic
PNG
Examples
/nblm podcast --wait --output ./deep-dive.mp3
/nblm briefing --instructions "Focus on chapter 3" --wait
/nblm debate --length LONG --wait --output ./debate.mp3
/nblm slides --instructions "Include key diagrams" --format DETAILED_DECK --wait --output ./presentation.pdf
/nblm infographic --orientation LANDSCAPE --detail-level DETAILED --wait --output ./summary.png
Download & Manage
/nblm podcast-download ./my-podcast.mp3
/nblm slides-download ./presentation.pdf
/nblm infographic-download ./visual.png
/nblm media-list # List all generated media
/nblm media-list --type audio # List only audio
/nblm media-delete <id> # Delete a media item
Extended Documentation
When to Use This Skill
Trigger when user:
- Mentions NotebookLM explicitly
- Shares NotebookLM URL (
https://notebooklm.google.com/notebook/...) - Asks to query their notebooks/documentation
- Wants to add documentation to NotebookLM library
- Uses phrases like "ask my NotebookLM", "check my docs", "query my notebook"
⚠️ CRITICAL: Add Command - Smart Discovery
The add command now automatically discovers metadata from the notebook:
# Smart Add (auto-discovers name, description, topics)
python scripts/run.py notebook_manager.py add <notebook-id-or-url>
# With optional overrides
python scripts/run.py notebook_manager.py add <id> --name "Custom Name" --topics "custom,topics"
What Smart Add does:
- Fetches notebook title from NotebookLM API
- Queries the notebook content to generate description and topics
- Adds to local library with discovered metadata Supported input formats:
- Notebook ID:
5fd9f36b-8000-401d-a7a0-7aa3f7832644 - Full URL:
https://notebooklm.google.com/notebook/5fd9f36b-8000-401d-a7a0-7aa3f7832644NEVER manually specify--name,--description, or--topicsunless the user explicitly provides them.
Critical: Always Use run.py Wrapper
NEVER call scripts directly. ALWAYS use python scripts/run.py [script]:
# ✅ CORRECT - Always use run.py:
python scripts/run.py auth_manager.py status
python scripts/run.py notebook_manager.py list
python scripts/run.py ask_question.py --question "..."
# ❌ WRONG - Never call directly:
python scripts/auth_manager.py status # Fails without venv!
The run.py wrapper automatically:
- Creates
.venvif needed - Installs all dependencies
- Activates environment
- Executes script properly
Core Workflow
Step 1: Check Authentication Status
python scripts/run.py auth_manager.py status
If not authenticated, proceed to setup.
Step 2: Authenticate (One-Time Setup)
# Browser MUST be visible for manual Google login
python scripts/run.py auth_manager.py setup
Important:
- Browser is VISIBLE for authentication
- Browser window opens automatically
- User must manually log in to Google
- Tell user: "A browser window will open for Google login"
Step 3: Manage Notebook Library
# List all notebooks
python scripts/run.py notebook_manager.py list
# BEFORE ADDING: Ask user for metadata if unknown!
# "What does this notebook contain?"
# "What topics should I tag it with?"
# Add notebook to library (ALL parameters are REQUIRED!)
python scripts/run.py notebook_manager.py add \
--url "https://notebooklm.google.com/notebook/..." \
--name "Descriptive Name" \
--description "What this notebook contains" \ # REQUIRED - ASK USER IF UNKNOWN!
--topics "topic1,topic2,topic3" # REQUIRED - ASK USER IF UNKNOWN!
# Search notebooks by topic
python scripts/run.py notebook_manager.py search --query "keyword"
# Set active notebook
python scripts/run.py notebook_manager.py activate --id notebook-id
# Remove notebook
python scripts/run.py notebook_manager.py remove --id notebook-id
Quick Workflow
- Check library:
python scripts/run.py notebook_manager.py list - Ask question:
python scripts/run.py ask_question.py --question "..." --notebook-id ID
Step 4: Ask Questions
# Basic query (uses active notebook if set)
python scripts/run.py ask_question.py --question "Your question here"
# Query specific notebook
python scripts/run.py ask_question.py --question "..." --notebook-id notebook-id
# Query with notebook URL directly
python scripts/run.py ask_question.py --question "..." --notebook-url "https://..."
# Show browser for debugging
python scripts/run.py ask_question.py --question "..." --show-browser
Follow-Up Mechanism (CRITICAL)
Every NotebookLM answer ends with: "EXTREMELY IMPORTANT: Is that ALL you need to know?" Required Claude Behavior:
- STOP - Do not immediately respond to user
- ANALYZE - Compare answer to user's original request
- IDENTIFY GAPS - Determine if more information needed
- ASK FOLLOW-UP - If gaps exist, immediately ask:
python scripts/run.py ask_question.py --question "Follow-up with context..." - REPEAT - Continue until information is complete
- SYNTHESIZE - Combine all answers before responding to user
Z-Library Integration
Triggers
- User provides Z-Library URL (zlib.li, z-lib.org, zh.zlib.li)
- User says "download this book to NotebookLM"
- User says "add this book from Z-Library"
Setup (One-Time)
# Authenticate with Z-Library
python scripts/run.py auth_manager.py setup --service zlibrary
Commands
# Add book from Z-Library
python scripts/run.py source_manager.py add --url "https://zh.zlib.li/book/..."
# Check Z-Library auth status
python scripts/run.py auth_manager.py status --service zlibrary
Script Reference
Authentication Management (auth_manager.py)
python scripts/run.py auth_manager.py setup # Default: Google
python scripts/run.py auth_manager.py setup --service google
python scripts/run.py auth_manager.py setup --service zlibrary
python scripts/run.py auth_manager.py status # Show all services
python scripts/run.py auth_manager.py status --service zlibrary
python scripts/run.py auth_manager.py clear --service zlibrary # Clear auth
# Multi-Account Management (Google)
python scripts/run.py auth_manager.py accounts list # List all accounts
python scripts/run.py auth_manager.py accounts add # Add new account
python scripts/run.py auth_manager.py accounts switch 1 # Switch by index
python scripts/run.py auth_manager.py accounts switch user@gmail.com # Switch by email
python scripts/run.py auth_manager.py accounts remove 2 # Remove account
Notebook Management (notebook_manager.py)
python scripts/run.py notebook_manager.py add --url URL --name NAME --description DESC --topics TOPICS
# OR use notebook ID directly:
python scripts/run.py notebook_manager.py add --notebook-id ID --name NAME --description DESC --topics TOPICS
python scripts/run.py notebook_manager.py list
python scripts/run.py notebook_manager.py search --query QUERY
python scripts/run.py notebook_manager.py activate --id ID
python scripts/run.py notebook_manager.py remove --id ID
python scripts/run.py notebook_manager.py stats
Question Interface (ask_question.py)
python scripts/run.py ask_question.py --question "..." [--notebook-id ID] [--notebook-url URL] [--show-browser]
Source Manager (source_manager.py)
# Upload to active notebook
python scripts/run.py source_manager.py add --file "/path/to/book.pdf" --use-active
# Create new notebook for upload
python scripts/run.py source_manager.py add --file "/path/to/book.pdf" --create-new
# Upload to specific notebook
python scripts/run.py source_manager.py add --file "/path/to/book.pdf" --notebook-id NOTEBOOK_ID
# Z-Library download and upload
python scripts/run.py source_manager.py add --url "https://zh.zlib.li/book/..." --use-active
python scripts/run.py source_manager.py add --url "https://zh.zlib.li/book/..." --create-new
# Sync a folder (new!)
python scripts/run.py source_manager.py sync "/path/to/docs" --use-active
python scripts/run.py source_manager.py sync "/path/to/docs" --create-new
python scripts/run.py source_manager.py sync "/path/to/docs" --notebook-id NOTEBOOK_ID
# Sync options (new!)
python scripts/run.py source_manager.py sync "/path/to/docs" --dry-run # Preview only
python scripts/run.py source_manager.py sync "/path/to/docs" --rebuild # Force re-hash all files
Folder Sync:
- Scans folder for supported types: PDF, TXT, MD, DOCX, HTML, EPUB
- Tracks sync state internally (no per-folder tracking file to manage)
- Sync strategy: add new, update modified (delete + re-upload), skip unchanged
- Multi-account aware (tracks which Google account was used) Note: One of
--use-active,--create-new, or--notebook-idis REQUIRED. Uploads wait for NotebookLM processing and print progress asReady: N/T. Press Ctrl+C to stop waiting. Local file uploads use browser automation and require Google authentication. If browser automation is unavailable, setNOTEBOOKLM_UPLOAD_MODE=textto upload extracted text instead (PDFs requirepypdf).
Data Cleanup (cleanup_manager.py)
python scripts/run.py cleanup_manager.py # Preview cleanup
python scripts/run.py cleanup_manager.py --confirm # Execute cleanup
python scripts/run.py cleanup_manager.py --preserve-library # Keep notebooks
Watchdog Status (auth_manager.py)
python scripts/run.py auth_manager.py watchdog-status
Environment Management
The virtual environment is automatically managed:
- First run creates
.venvautomatically - Dependencies install automatically
- Node.js dependencies install automatically
- agent-browser daemon starts on demand and keeps browser state in memory
- daemon stops after 10 minutes of inactivity (any agent-browser command resets the timer)
- set
AGENT_BROWSER_OWNER_PIDto auto-stop when the agent process exits scripts/run.pysetsAGENT_BROWSER_OWNER_PIDto its parent PID by default- Everything isolated in skill directory Manual setup (only if automatic fails):
python -m venv .venv
source .venv/bin/activate # Linux/Mac
pip install -r requirements.txt
npm install
npm run install-browsers
Data Storage
All data stored in ~/.claude/skills/notebooklm/data/:
library.json- Notebook metadata (with account associations)auth/google/- Multi-account Google authindex.json- Account index (active account, list)<n>-<email>.json- Per-account credentials
auth/zlibrary.json- Z-Library auth stateagent_browser/session_id- Current daemon session IDagent_browser/last_activity.json- Last activity timestamp for idle shutdownagent_browser/watchdog.pid- Idle watchdog process ID Security: Protected by.gitignore, never commit to git.
Configuration
Optional .env file in skill directory:
HEADLESS=false # Browser visibility
SHOW_BROWSER=false # Default browser display
STEALTH_ENABLED=true # Human-like behavior
TYPING_WPM_MIN=160 # Typing speed
TYPING_WPM_MAX=240
DEFAULT_NOTEBOOK_ID= # Default notebook
Decision Flow
User mentions NotebookLM
↓
Check auth → python scripts/run.py auth_manager.py status
↓
If not authenticated → python scripts/run.py auth_manager.py setup
↓
Check/Add notebook → python scripts/run.py notebook_manager.py list/add (with --description)
↓
Activate notebook → python scripts/run.py notebook_manager.py activate --id ID
↓
Ask question → python scripts/run.py ask_question.py --question "..."
↓
See "Is that ALL you need?" → Ask follow-ups until complete
↓
Synthesize and respond to user
Troubleshooting
Problem
Solution
ModuleNotFoundError
Use run.py wrapper
Authentication fails
Browser must be visible for setup! --show-browser
DAEMON_UNAVAILABLE
Ensure Node.js/npm installed, run npm install, retry
AUTH_REQUIRED
Run python scripts/run.py auth_manager.py setup
ELEMENT_NOT_FOUND
Verify notebook URL and re-run with fresh page load
Rate limit (50/day)
Wait or add another Google account with accounts add
Browser crashes
python scripts/run.py cleanup_manager.py --preserve-library
Notebook not found
Check with notebook_manager.py list
Best Practices
- Always use run.py - Handles environment automatically
- Check auth first - Before any operations
- Follow-up questions - Don't stop at first answer
- Browser visible for auth - Required for manual login
- Include context - Each question is independent
- Synthesize answers - Combine multiple responses
Limitations
- No session persistence (each question = new browser)
- Rate limits on free Google accounts (50 queries/day per account; use multiple accounts to increase)
- Manual upload required (user must add docs to NotebookLM)
- Browser overhead (few seconds per question)
Resources (Skill Structure)
Important directories and files:
scripts/- All automation scripts (ask_question.py, notebook_manager.py, etc.)data/- Local storage for authentication and notebook libraryreferences/- Extended documentation:api_reference.md- Detailed API documentation for all scriptstroubleshooting.md- Common issues and solutionsusage_patterns.md- Best practices and workflow examples
.venv/- Isolated Python environment (auto-created on first run).gitignore- Protects sensitive data from being committed
GitHub Owner
Owner: magicseek
SKILL.md
name: nblm description: Use this skill to query your Google NotebookLM notebooks directly from Claude Code for source-grounded, citation-backed answers from Gemini. Browser automation, library management, persistent auth. Drastically reduced hallucinations through document-only responses.
NotebookLM Quick Commands
Query Google NotebookLM for source-grounded, citation-backed answers.
Environment
All dependencies and authentication are handled automatically by run.py:
- First run creates
.venvand installs Python/Node.js dependencies - If Google auth is missing or expired, a browser window opens automatically
- No manual pre-flight steps required
Usage
/nblm <command> [args]
Commands
Notebook Management
| Command | Description |
|---|---|
login | Authenticate with Google |
status | Show auth and library status |
accounts | List all Google accounts |
accounts add | Add a new Google account |
accounts switch <id> | Switch active account (by index or email) |
accounts remove <id> | Remove a Google account |
accounts use <id> | Set agent-specific active account (OpenClaw isolation) |
accounts clear | Clear agent-specific account override |
local | List notebooks in local library |
remote | List all notebooks from NotebookLM API |
create <name> | Create a new notebook |
delete [--id ID] | Delete a notebook |
rename <name> [--id ID] | Rename a notebook |
summary [--id ID] | Get AI-generated summary |
describe [--id ID] | Get description and suggested topics |
add <url-or-id> | Add notebook to local library (auto-detects URL vs notebook ID) |
activate <id> | Set active notebook |
Source Management
| Command | Description |
|---|---|
sources [--id ID] | List sources in notebook |
upload <file> | Upload a single file |
upload <folder> | Sync a folder of files to NotebookLM |
upload-zlib <url> | Download from Z-Library and upload |
upload-url <url> | Add URL as source |
upload-youtube <url> | Add YouTube video as source |
upload-text <title> [--content TEXT] | Add text as source |
source-text <source-id> | Get full indexed text |
source-guide <source-id> | Get AI summary and keywords |
source-rename <source-id> <name> | Rename a source |
source-refresh <source-id> | Re-fetch URL content |
source-delete <source-id> | Delete a source |
| Upload options: |
--use-active- Upload to the currently active notebook--create-new- Create a new notebook named after the file/folder--notebook-id <id>- Upload to a specific notebook--dry-run- Show sync plan without executing (folder sync)--rebuild- Force rebuild tracking file (folder sync) Important: When user runs upload without specifying a target, ASK them first:
"Would you like to upload to the active notebook, or create a new notebook?" Then pass the appropriate flag (
--use-activeor--create-new).
Chat & Audio/Media
| Command | Description |
|---|---|
ask <question> | Query NotebookLM |
podcast [--instructions TEXT] | Generate audio podcast |
podcast-status <task-id> | Check podcast generation status |
podcast-download [output-path] | Download latest podcast |
briefing [--instructions TEXT] | Generate brief audio summary |
debate [--instructions TEXT] | Generate debate-style audio |
slides [--instructions TEXT] | Generate slide deck |
slides-download [output-path] | Download slide deck as PDF |
infographic [--instructions TEXT] | Generate infographic |
infographic-download [output-path] | Download infographic |
media-list [--type TYPE] | List generated media (audio/video/slides/infographic) |
media-delete <id> | Delete a generated media item |
Command Routing
Based on $ARGUMENTS, execute the appropriate command:
$IF($ARGUMENTS,
Parse the command from: "$ARGUMENTS"
login → python scripts/run.py auth_manager.py setup --service google
accounts → python scripts/run.py auth_manager.py accounts list
accounts add → python scripts/run.py auth_manager.py accounts add
accounts switch → python scripts/run.py auth_manager.py accounts switch "<id>"
accounts remove → python scripts/run.py auth_manager.py accounts remove "<id>"
accounts use → python scripts/run.py auth_manager.py accounts use "<id>"
accounts clear → python scripts/run.py auth_manager.py accounts clear
status → Run both:
python scripts/run.py auth_manager.py statuspython scripts/run.py notebook_manager.py listlocal →python scripts/run.py notebook_manager.py listremote →python scripts/run.py nblm_cli.py notebookscreate →python scripts/run.py nblm_cli.py create "<name>"delete [--id ID] →python scripts/run.py nblm_cli.py delete <args>rename [--id ID] →python scripts/run.py nblm_cli.py rename "<name>" <args>summary [--id ID] →python scripts/run.py nblm_cli.py summary <args>describe [--id ID] →python scripts/run.py nblm_cli.py describe <args>add → Smart add workflow (auto-detects URL vs notebook ID) activate →python scripts/run.py notebook_manager.py activate --id "<id>"sources [--id ID] →python scripts/run.py nblm_cli.py sources <args>upload → First ASK user: "Upload to active notebook or create new?" Then:- Active:
python scripts/run.py source_manager.py add --file "<file>" --use-active - New:
python scripts/run.py source_manager.py add --file "<file>" --create-newupload → Sync a folder: - First ASK user: "Sync to active notebook, create new, or specify notebook?"
- Active:
python scripts/run.py source_manager.py sync "<folder>" --use-active - New:
python scripts/run.py source_manager.py sync "<folder>" --create-new - Specific:
python scripts/run.py source_manager.py sync "<folder>" --notebook-id ID - Dry-run:
python scripts/run.py source_manager.py sync "<folder>" --dry-run - Rebuild:
python scripts/run.py source_manager.py sync "<folder>" --rebuildupload-zlib → First ASK user: "Upload to active notebook or create new?" Then: - Active:
python scripts/run.py source_manager.py add --url "<url>" --use-active - New:
python scripts/run.py source_manager.py add --url "<url>" --create-newupload-url →python scripts/run.py nblm_cli.py upload-url "<url>"upload-youtube →python scripts/run.py nblm_cli.py upload-youtube "<url>"upload-text →python scripts/run.py nblm_cli.py upload-text "<title>" <args>source-text →python scripts/run.py nblm_cli.py source-text "<id>"source-guide →python scripts/run.py nblm_cli.py source-guide "<id>"source-rename →python scripts/run.py nblm_cli.py source-rename "<id>" "<name>"source-refresh →python scripts/run.py nblm_cli.py source-refresh "<id>"source-delete →python scripts/run.py nblm_cli.py source-delete "<id>"ask →python scripts/run.py nblm_cli.py ask "<question>"podcast →python scripts/run.py artifact_manager.py generate --format DEEP_DIVE <args>podcast-status →python scripts/run.py artifact_manager.py status --task-id "<task-id>"podcast-download [output-path] →python scripts/run.py artifact_manager.py download "<output-path>"briefing →python scripts/run.py artifact_manager.py generate --format BRIEF <args>debate →python scripts/run.py artifact_manager.py generate --format DEBATE <args>slides →python scripts/run.py artifact_manager.py generate-slides <args>slides-download [output-path] →python scripts/run.py artifact_manager.py download "<output-path>" --type slide-deckinfographic →python scripts/run.py artifact_manager.py generate-infographic <args>infographic-download [output-path] →python scripts/run.py artifact_manager.py download "<output-path>" --type infographicmedia-list [--type TYPE] →python scripts/run.py artifact_manager.py list <args>media-delete →python scripts/run.py artifact_manager.py delete "<id>"If command not recognized, show usage help., Show available commands with/nblm(no arguments) )
- Active:
Podcast Options
/nblm podcast --length DEFAULT --wait --output ./podcast.mp3
/nblm podcast --instructions "Focus on the key findings"
/nblm briefing --wait --output ./summary.mp3
/nblm debate --instructions "Compare the two approaches"
| Option | Values |
|---|---|
--length | SHORT, DEFAULT, LONG |
--instructions | Custom instructions for the content |
--wait | Wait for generation to complete |
--output | Download path (requires --wait) |
Slide Deck Options
/nblm slides --format DETAILED_DECK --wait --output ./presentation.pdf
/nblm slides --instructions "Focus on key diagrams" --format PRESENTER_SLIDES
| Option | Values |
|---|---|
--format | DETAILED_DECK, PRESENTER_SLIDES |
--length | SHORT, DEFAULT |
--instructions | Custom instructions for the content |
--wait | Wait for generation to complete |
--output | Download path (requires --wait) |
Infographic Options
/nblm infographic --orientation LANDSCAPE --wait --output ./visual.png
/nblm infographic --instructions "Highlight comparison" --detail-level DETAILED
| Option | Values |
|---|---|
--orientation | LANDSCAPE, PORTRAIT, SQUARE |
--detail-level | CONCISE, STANDARD, DETAILED |
--instructions | Custom instructions for the content |
--wait | Wait for generation to complete |
--output | Download path (requires --wait) |
Media Generation
| Command | Description | Output |
|---|---|---|
/nblm podcast | Deep-dive audio discussion | MP3 |
/nblm briefing | Brief audio summary | MP3 |
/nblm debate | Debate-style audio | MP3 |
/nblm slides | Slide deck presentation | |
/nblm infographic | Visual infographic | PNG |
Examples
/nblm podcast --wait --output ./deep-dive.mp3
/nblm briefing --instructions "Focus on chapter 3" --wait
/nblm debate --length LONG --wait --output ./debate.mp3
/nblm slides --instructions "Include key diagrams" --format DETAILED_DECK --wait --output ./presentation.pdf
/nblm infographic --orientation LANDSCAPE --detail-level DETAILED --wait --output ./summary.png
Download & Manage
/nblm podcast-download ./my-podcast.mp3
/nblm slides-download ./presentation.pdf
/nblm infographic-download ./visual.png
/nblm media-list # List all generated media
/nblm media-list --type audio # List only audio
/nblm media-delete <id> # Delete a media item
Extended Documentation
When to Use This Skill
Trigger when user:
- Mentions NotebookLM explicitly
- Shares NotebookLM URL (
https://notebooklm.google.com/notebook/...) - Asks to query their notebooks/documentation
- Wants to add documentation to NotebookLM library
- Uses phrases like "ask my NotebookLM", "check my docs", "query my notebook"
⚠️ CRITICAL: Add Command - Smart Discovery
The add command now automatically discovers metadata from the notebook:
# Smart Add (auto-discovers name, description, topics)
python scripts/run.py notebook_manager.py add <notebook-id-or-url>
# With optional overrides
python scripts/run.py notebook_manager.py add <id> --name "Custom Name" --topics "custom,topics"
What Smart Add does:
- Fetches notebook title from NotebookLM API
- Queries the notebook content to generate description and topics
- Adds to local library with discovered metadata Supported input formats:
- Notebook ID:
5fd9f36b-8000-401d-a7a0-7aa3f7832644 - Full URL:
https://notebooklm.google.com/notebook/5fd9f36b-8000-401d-a7a0-7aa3f7832644NEVER manually specify--name,--description, or--topicsunless the user explicitly provides them.
Critical: Always Use run.py Wrapper
NEVER call scripts directly. ALWAYS use python scripts/run.py [script]:
# ✅ CORRECT - Always use run.py:
python scripts/run.py auth_manager.py status
python scripts/run.py notebook_manager.py list
python scripts/run.py ask_question.py --question "..."
# ❌ WRONG - Never call directly:
python scripts/auth_manager.py status # Fails without venv!
The run.py wrapper automatically:
- Creates
.venvif needed - Installs all dependencies
- Activates environment
- Executes script properly
Core Workflow
Step 1: Check Authentication Status
python scripts/run.py auth_manager.py status
If not authenticated, proceed to setup.
Step 2: Authenticate (One-Time Setup)
# Browser MUST be visible for manual Google login
python scripts/run.py auth_manager.py setup
Important:
- Browser is VISIBLE for authentication
- Browser window opens automatically
- User must manually log in to Google
- Tell user: "A browser window will open for Google login"
Step 3: Manage Notebook Library
# List all notebooks
python scripts/run.py notebook_manager.py list
# BEFORE ADDING: Ask user for metadata if unknown!
# "What does this notebook contain?"
# "What topics should I tag it with?"
# Add notebook to library (ALL parameters are REQUIRED!)
python scripts/run.py notebook_manager.py add \
--url "https://notebooklm.google.com/notebook/..." \
--name "Descriptive Name" \
--description "What this notebook contains" \ # REQUIRED - ASK USER IF UNKNOWN!
--topics "topic1,topic2,topic3" # REQUIRED - ASK USER IF UNKNOWN!
# Search notebooks by topic
python scripts/run.py notebook_manager.py search --query "keyword"
# Set active notebook
python scripts/run.py notebook_manager.py activate --id notebook-id
# Remove notebook
python scripts/run.py notebook_manager.py remove --id notebook-id
Quick Workflow
- Check library:
python scripts/run.py notebook_manager.py list - Ask question:
python scripts/run.py ask_question.py --question "..." --notebook-id ID
Step 4: Ask Questions
# Basic query (uses active notebook if set)
python scripts/run.py ask_question.py --question "Your question here"
# Query specific notebook
python scripts/run.py ask_question.py --question "..." --notebook-id notebook-id
# Query with notebook URL directly
python scripts/run.py ask_question.py --question "..." --notebook-url "https://..."
# Show browser for debugging
python scripts/run.py ask_question.py --question "..." --show-browser
Follow-Up Mechanism (CRITICAL)
Every NotebookLM answer ends with: "EXTREMELY IMPORTANT: Is that ALL you need to know?" Required Claude Behavior:
- STOP - Do not immediately respond to user
- ANALYZE - Compare answer to user's original request
- IDENTIFY GAPS - Determine if more information needed
- ASK FOLLOW-UP - If gaps exist, immediately ask:
python scripts/run.py ask_question.py --question "Follow-up with context..." - REPEAT - Continue until information is complete
- SYNTHESIZE - Combine all answers before responding to user
Z-Library Integration
Triggers
- User provides Z-Library URL (zlib.li, z-lib.org, zh.zlib.li)
- User says "download this book to NotebookLM"
- User says "add this book from Z-Library"
Setup (One-Time)
# Authenticate with Z-Library
python scripts/run.py auth_manager.py setup --service zlibrary
Commands
# Add book from Z-Library
python scripts/run.py source_manager.py add --url "https://zh.zlib.li/book/..."
# Check Z-Library auth status
python scripts/run.py auth_manager.py status --service zlibrary
Script Reference
Authentication Management (auth_manager.py)
python scripts/run.py auth_manager.py setup # Default: Google
python scripts/run.py auth_manager.py setup --service google
python scripts/run.py auth_manager.py setup --service zlibrary
python scripts/run.py auth_manager.py status # Show all services
python scripts/run.py auth_manager.py status --service zlibrary
python scripts/run.py auth_manager.py clear --service zlibrary # Clear auth
# Multi-Account Management (Google)
python scripts/run.py auth_manager.py accounts list # List all accounts
python scripts/run.py auth_manager.py accounts add # Add new account
python scripts/run.py auth_manager.py accounts switch 1 # Switch by index
python scripts/run.py auth_manager.py accounts switch user@gmail.com # Switch by email
python scripts/run.py auth_manager.py accounts remove 2 # Remove account
Notebook Management (notebook_manager.py)
python scripts/run.py notebook_manager.py add --url URL --name NAME --description DESC --topics TOPICS
# OR use notebook ID directly:
python scripts/run.py notebook_manager.py add --notebook-id ID --name NAME --description DESC --topics TOPICS
python scripts/run.py notebook_manager.py list
python scripts/run.py notebook_manager.py search --query QUERY
python scripts/run.py notebook_manager.py activate --id ID
python scripts/run.py notebook_manager.py remove --id ID
python scripts/run.py notebook_manager.py stats
Question Interface (ask_question.py)
python scripts/run.py ask_question.py --question "..." [--notebook-id ID] [--notebook-url URL] [--show-browser]
Source Manager (source_manager.py)
# Upload to active notebook
python scripts/run.py source_manager.py add --file "/path/to/book.pdf" --use-active
# Create new notebook for upload
python scripts/run.py source_manager.py add --file "/path/to/book.pdf" --create-new
# Upload to specific notebook
python scripts/run.py source_manager.py add --file "/path/to/book.pdf" --notebook-id NOTEBOOK_ID
# Z-Library download and upload
python scripts/run.py source_manager.py add --url "https://zh.zlib.li/book/..." --use-active
python scripts/run.py source_manager.py add --url "https://zh.zlib.li/book/..." --create-new
# Sync a folder (new!)
python scripts/run.py source_manager.py sync "/path/to/docs" --use-active
python scripts/run.py source_manager.py sync "/path/to/docs" --create-new
python scripts/run.py source_manager.py sync "/path/to/docs" --notebook-id NOTEBOOK_ID
# Sync options (new!)
python scripts/run.py source_manager.py sync "/path/to/docs" --dry-run # Preview only
python scripts/run.py source_manager.py sync "/path/to/docs" --rebuild # Force re-hash all files
Folder Sync:
- Scans folder for supported types: PDF, TXT, MD, DOCX, HTML, EPUB
- Tracks sync state internally (no per-folder tracking file to manage)
- Sync strategy: add new, update modified (delete + re-upload), skip unchanged
- Multi-account aware (tracks which Google account was used)
Note: One of
--use-active,--create-new, or--notebook-idis REQUIRED. Uploads wait for NotebookLM processing and print progress asReady: N/T. Press Ctrl+C to stop waiting. Local file uploads use browser automation and require Google authentication. If browser automation is unavailable, setNOTEBOOKLM_UPLOAD_MODE=textto upload extracted text instead (PDFs requirepypdf).
Data Cleanup (cleanup_manager.py)
python scripts/run.py cleanup_manager.py # Preview cleanup
python scripts/run.py cleanup_manager.py --confirm # Execute cleanup
python scripts/run.py cleanup_manager.py --preserve-library # Keep notebooks
Watchdog Status (auth_manager.py)
python scripts/run.py auth_manager.py watchdog-status
Environment Management
The virtual environment is automatically managed:
- First run creates
.venvautomatically - Dependencies install automatically
- Node.js dependencies install automatically
- agent-browser daemon starts on demand and keeps browser state in memory
- daemon stops after 10 minutes of inactivity (any agent-browser command resets the timer)
- set
AGENT_BROWSER_OWNER_PIDto auto-stop when the agent process exits scripts/run.pysetsAGENT_BROWSER_OWNER_PIDto its parent PID by default- Everything isolated in skill directory Manual setup (only if automatic fails):
python -m venv .venv
source .venv/bin/activate # Linux/Mac
pip install -r requirements.txt
npm install
npm run install-browsers
Data Storage
All data stored in ~/.claude/skills/notebooklm/data/:
library.json- Notebook metadata (with account associations)auth/google/- Multi-account Google authindex.json- Account index (active account, list)<n>-<email>.json- Per-account credentials
auth/zlibrary.json- Z-Library auth stateagent_browser/session_id- Current daemon session IDagent_browser/last_activity.json- Last activity timestamp for idle shutdownagent_browser/watchdog.pid- Idle watchdog process ID Security: Protected by.gitignore, never commit to git.
Configuration
Optional .env file in skill directory:
HEADLESS=false # Browser visibility
SHOW_BROWSER=false # Default browser display
STEALTH_ENABLED=true # Human-like behavior
TYPING_WPM_MIN=160 # Typing speed
TYPING_WPM_MAX=240
DEFAULT_NOTEBOOK_ID= # Default notebook
Decision Flow
User mentions NotebookLM
↓
Check auth → python scripts/run.py auth_manager.py status
↓
If not authenticated → python scripts/run.py auth_manager.py setup
↓
Check/Add notebook → python scripts/run.py notebook_manager.py list/add (with --description)
↓
Activate notebook → python scripts/run.py notebook_manager.py activate --id ID
↓
Ask question → python scripts/run.py ask_question.py --question "..."
↓
See "Is that ALL you need?" → Ask follow-ups until complete
↓
Synthesize and respond to user
Troubleshooting
| Problem | Solution |
|---|---|
| ModuleNotFoundError | Use run.py wrapper |
| Authentication fails | Browser must be visible for setup! --show-browser |
| DAEMON_UNAVAILABLE | Ensure Node.js/npm installed, run npm install, retry |
| AUTH_REQUIRED | Run python scripts/run.py auth_manager.py setup |
| ELEMENT_NOT_FOUND | Verify notebook URL and re-run with fresh page load |
| Rate limit (50/day) | Wait or add another Google account with accounts add |
| Browser crashes | python scripts/run.py cleanup_manager.py --preserve-library |
| Notebook not found | Check with notebook_manager.py list |
Best Practices
- Always use run.py - Handles environment automatically
- Check auth first - Before any operations
- Follow-up questions - Don't stop at first answer
- Browser visible for auth - Required for manual login
- Include context - Each question is independent
- Synthesize answers - Combine multiple responses
Limitations
- No session persistence (each question = new browser)
- Rate limits on free Google accounts (50 queries/day per account; use multiple accounts to increase)
- Manual upload required (user must add docs to NotebookLM)
- Browser overhead (few seconds per question)
Resources (Skill Structure)
Important directories and files:
scripts/- All automation scripts (ask_question.py, notebook_manager.py, etc.)data/- Local storage for authentication and notebook libraryreferences/- Extended documentation:api_reference.md- Detailed API documentation for all scriptstroubleshooting.md- Common issues and solutionsusage_patterns.md- Best practices and workflow examples
.venv/- Isolated Python environment (auto-created on first run).gitignore- Protects sensitive data from being committed