NotebookLM Automation
Automate Google NotebookLM: create notebooks, add sources, chat with content, generate artifacts (podcasts, videos, quizzes), and download results.
Prerequisites
IMPORTANT: Before using any command, you MUST authenticate:
notebooklm login # Opens browser for Google OAuth
notebooklm list # Verify authentication works
If commands fail with authentication errors, re-run notebooklm login.
CI/CD, Multiple Accounts, and Parallel Agents
For automated environments, multiple accounts, or parallel agent workflows:
| Variable | Purpose | |----------|---------| | NOTEBOOKLM_HOME | Custom config directory (default: ~/.notebooklm) | | NOTEBOOKLM_AUTH_JSON | Inline auth JSON - no file writes needed |
CI/CD setup: Set NOTEBOOKLM_AUTH_JSON from a secret containing your storage_state.json contents.
Multiple accounts: Use different NOTEBOOKLM_HOME directories per account.
Parallel agents: The CLI stores notebook context in a shared file (~/.notebooklm/context.json). Multiple concurrent agents using notebooklm use can overwrite each other's context.
Solutions for parallel workflows:
- Always use explicit notebook ID (recommended): Pass
-n <notebook_id>(forwait/downloadcommands) or--notebook <notebook_id>(for others) instead of relying onuse - Per-agent isolation: Set unique
NOTEBOOKLM_HOMEper agent:export NOTEBOOKLM_HOME=/tmp/agent-$ID - Use full UUIDs: Avoid partial IDs in automation (they can become ambiguous)
Agent Setup Verification
Before starting workflows, verify the CLI is ready:
notebooklm status→ Should show "Authenticated as: email@..."notebooklm list --json→ Should return valid JSON (even if empty notebooks list)- If either fails → Run
notebooklm login
When This Skill Activates
Explicit: User says "/notebooklm", "use notebooklm", or mentions the tool by name
Intent detection: Recognize requests like:
- "Create a podcast about [topic]"
- "Summarize these URLs/documents"
- "Generate a quiz from my research"
- "Turn this into an audio overview"
- "Add these sources to NotebookLM"
Autonomy Rules
Run automatically (no confirmation):
notebooklm status- check contextnotebooklm list- list notebooksnotebooklm source list- list sourcesnotebooklm artifact list- list artifactsnotebooklm artifact wait- wait for artifact completion (in subagent context)notebooklm source wait- wait for source processing (in subagent context)notebooklm research status- check research statusnotebooklm research wait- wait for research (in subagent context)notebooklm use <id>- set context (⚠️ SINGLE-AGENT ONLY - use-nflag in parallel workflows)notebooklm create- create notebooknotebooklm ask "..."- chat queriesnotebooklm source add- add sources
Ask before running:
notebooklm delete- destructivenotebooklm generate *- long-running, may failnotebooklm download *- writes to filesystemnotebooklm artifact wait- long-running (when in main conversation)notebooklm source wait- long-running (when in main conversation)notebooklm research wait- long-running (when in main conversation)
Quick Reference
| Task | Command | |------|---------| | Authenticate | notebooklm login | | List notebooks | notebooklm list | | Create notebook | notebooklm create "Title" | | Set context | notebooklm use <notebook_id> | | Show context | notebooklm status | | Add URL source | notebooklm source add "https://..." | | Add file | notebooklm source add ./file.pdf | | Add YouTube | notebooklm source add "https://youtube.com/..." | | List sources | notebooklm source list | | Wait for source processing | notebooklm source wait <source_id> | | Web research (fast) | notebooklm source add-research "query" | | Web research (deep) | notebooklm source add-research "query" --mode deep --no-wait | | Check research status | notebooklm research status | | Wait for research | notebooklm research wait --import-all | | Chat | notebooklm ask "question" | | Chat (new conversation) | notebooklm ask "question" --new | | Chat (specific sources) | notebooklm ask "question" -s src_id1 -s src_id2 | | Chat (with references) | notebooklm ask "question" --json | | Get source fulltext | notebooklm source fulltext <source_id> | | Get source guide | notebooklm source guide <source_id> | | Generate podcast | notebooklm generate audio "instructions" | | Generate podcast (JSON) | notebooklm generate audio --json | | Generate podcast (specific sources) | notebooklm generate audio -s src_id1 -s src_id2 | | Generate video | notebooklm generate video "instructions" | | Generate quiz | notebooklm generate quiz | | Check artifact status | notebooklm artifact list | | Wait for completion | notebooklm artifact wait <artifact_id> | | Download audio | notebooklm download audio ./output.mp3 | | Download video | notebooklm download video ./output.mp4 | | Delete notebook | notebooklm notebook delete <id> |
Parallel safety: Use explicit notebook IDs in parallel workflows. Commands supporting -n shorthand: artifact wait, source wait, research wait/status, download *. Download commands also support -a/--artifact. Other commands use --notebook. For chat, use --new to start fresh conversations (avoids conversation ID conflicts).
Partial IDs: Use first 6+ characters of UUIDs. Must be unique prefix (fails if ambiguous). Works for: use, delete, wait commands. For automation, prefer full UUIDs to avoid ambiguity.
Command Output Formats
Commands with --json return structured data for parsing:
Create notebook:
$ notebooklm create "Research" --json
{"id": "abc123de-...", "title": "Research"}
Add source:
$ notebooklm source add "https://example.com" --json
{"source_id": "def456...", "title": "Example", "status": "processing"}
Generate artifact:
$ notebooklm generate audio "Focus on key points" --json
{"task_id": "xyz789...", "status": "pending"}
Chat with references:
$ notebooklm ask "What is X?" --json
{"answer": "X is... [1] [2]", "conversation_id": "...", "turn_number": 1, "is_follow_up": false, "references": [{"source_id": "abc123...", "citation_number": 1, "cited_text": "Relevant passage from source..."}, {"source_id": "def456...", "citation_number": 2, "cited_text": "Another passage..."}]}
Source fulltext (get indexed content):
$ notebooklm source fulltext <source_id> --json
{"source_id": "...", "title": "...", "char_count": 12345, "content": "Full indexed text..."}
Understanding citations: The cited_text in references is often a snippet or section header, not the full quoted passage. The start_char/end_char positions reference NotebookLM's internal chunked index, not the raw fulltext. Use SourceFulltext.find_citation_context() to locate citations:
fulltext = await client.sources.get_fulltext(notebook_id, ref.source_id)
matches = fulltext.find_citation_context(ref.cited_text) # Returns list[(context, position)]
if matches:
context, pos = matches[0] # First match; check len(matches) > 1 for duplicates
Extract IDs: Parse the id, source_id, or task_id field from JSON output.
Generation Types
All generate commands support:
-s, --sourceto use specific source(s) instead of all sources--jsonfor machine-readable output (returnstask_idandstatus)
| Type | Command | Downloadable | |------|---------|--------------| | Podcast | generate audio | Yes (.mp3) | | Video | generate video | Yes (.mp4) | | Slides | generate slide-deck | Yes (.pdf) | | Infographic | generate infographic | Yes (.png) | | Quiz | generate quiz | No (view in UI) | | Flashcards | generate flashcards | No (view in UI) | | Mind Map | generate mind-map | No (view in UI) | |