I had this starred in my notes for two days before I touched it: “NotebookLM → Claude Code research pipeline, notebooklm-py delegates the heavy read work to Google’s infrastructure, leaving Claude Code’s own context virtually unburdened.” A one-line note to myself from mid-August, the kind I write when something looks too convenient to be real. Offload the expensive reading to someone else’s servers, keep my own agent’s context window for the actual work. That’s the pitch on paper. I wanted to know if it held up once I actually wired it into a real Claude Code session instead of just nodding at the README.
Short version, because I know some of you will stop here: yes, it’s real, the CLI is genuinely clean, and the context-budget argument is legitimate, not marketing. But it comes with an authentication story I did not love, a dependency on an unofficial, reverse-engineered API that Google could break on a Tuesday, and a hard platform limitation that will matter a lot depending on how you run Claude Code. I’ll walk through all of it, including the parts that annoyed me.
The problem this is actually solving
If you’ve pointed Claude Code at a pile of PDFs, vendor docs, or a sprawling internal wiki export, you already know the failure mode. You either paste huge chunks of source material directly into the conversation, which eats your context window fast and means you’re paying full agent-token rates just to get the material into the model before any actual reasoning happens, or you build yourself a small RAG pipeline, which is the correct long-term answer but is also an afternoon (or three) of chunking strategy, embedding model choice, and vector store plumbing before you get a single grounded answer back.
NotebookLM, now officially rebranded to Gemini Notebook as of July 2026 though basically everyone including the tool I’m about to describe still calls it NotebookLM, already solves the ingestion and grounding half of that problem. You throw PDFs, URLs, Google Drive docs, even YouTube videos at it, and it builds a source-grounded Q&A layer with citations, using Gemini’s infrastructure and Google’s compute, not yours. The catch, until recently, was that it only lived behind a web UI. Great for a human doing research, useless for an agent that needs to query it mid-task without a person clicking around a browser tab.
notebooklm-py, an unofficial Python client and CLI built by Teng Lin, closes that gap. It wraps NotebookLM's internal (undocumented) RPC calls in a proper Python API and a notebooklm command, and ships a Claude Code skill so an agent can call it the same way it'd call any other tool. The pitch, straight from the project's own docs, is blunt about the strategy: let NotebookLM do the heavy analysis, and have your agent spend tokens only on the final polish. That's the whole thesis in one sentence, and it's worth sitting with, because it inverts the usual RAG assumption. You're not building retrieval infrastructure. You're renting Google's.
What you’re actually installing
# CLI, with the browser-automation extras (recommended path)
uv tool install "notebooklm-py[browser]"
# or, if you're not on uv
pipx install "notebooklm-py[browser]"
# as a library, inside a project
uv add notebooklm-py
# or
pip install notebooklm-py
I went with uv because that's what the project's own docs assume for development, and honestly uv tool install for a CLI-style package is just less fuss than managing a virtualenv myself. If you're pip-only that's fine too, just make sure you install the [browser] extra unless you're planning to only ever use master-token auth, since interactive login needs Playwright under the hood.
Once installed:
notebooklm login
notebooklm auth check --test --json
The first command opens a real browser window and walks you through a normal Google sign-in. That’s genuinely the easiest path if you’re doing this on your own laptop. The second command is your sanity check, and I’d run it before doing anything else, because if auth is subtly broken you’ll get much more confusing errors two steps later when a source upload silently fails.
There are two other auth paths worth knowing about, because the interactive one doesn’t work everywhere:
# reuse cookies from a browser you're already logged into
notebooklm login --browser-cookies chrome
# headless / server / CI, no browser at all
notebooklm login --master-token --account you@example.com
This is the part I want to flag early rather than bury at the end. The master-token path exists specifically because the interactive Playwright login needs a real, visible browser context, which most CI runners, remote dev boxes, and cloud sandboxes don’t have. If you’re running Claude Code somewhere headless, that’s your on-ramp, and it’s worth setting up before you get three steps into a workflow and hit a wall.
Building an actual notebook from the command line
Here’s a full, real sequence, not a toy snippet. I’m using a genuinely mundane example: consolidating a stack of vendor API docs and a couple of PDFs I’d otherwise have had to skim myself.
notebooklm create "Vendor API Research"
notebooklm use <notebook_id> # printed by the create command
notebooklm source add "https://docs.example-vendor.com/api/v2"
notebooklm source add "./contracts/vendor-sla-2026.pdf"
notebooklm source add "./notes/integration-meeting-transcript.pdf"
notebooklm source list
Then the part that actually matters, the grounded question-answering:
notebooklm ask "What are the rate limits across all three sources, and do they conflict?"
What comes back is an answer with citations pointing to the specific source and passage it pulled from, not a confident-sounding paragraph with no way to check it. That citation trail is the entire value proposition versus just pasting the PDFs into a chat window. When Claude later needs to act on that answer, it’s acting on something it can trace back to a real document, not on a guess dressed up as a fact.
For longer or more structured questions, there’s a file-based variant:
notebooklm ask --prompt-file ./questions/integration-checklist.txt
And once you’ve got the notebook doing real work, you can generate a formatted output instead of just a chat answer, which is genuinely useful when the destination is a document rather than a conversation:
notebooklm generate report --format briefing-doc
notebooklm download report ./vendor-api-briefing.md
Report formats on offer are briefing-doc, study-guide, and blog-post, which covers most of the “I need this synthesized into something readable” cases I’ve run into. There’s also audio, video, quiz, flashcard, slide-deck, infographic, mind-map, and data-table generation, all scriptable the same way. I haven’t found much use for the podcast-style audio overview in an agent pipeline specifically, but if you’re building something end-user-facing rather than agent-internal, it’s sitting right there.
notebooklm generate audio "make it engaging, focus on the SLA terms" --wait
notebooklm download audio ./vendor-briefing.m4a
The --wait flag matters. Generation is async on Google's side, and without it the CLI hands control back before the artifact actually exists, which is a fast way to write a script that tries to download a file that isn't there yet.
Wiring it into Claude Code as a skill
This is the step that turns “a CLI I run by hand” into “something my agent reaches for on its own.” Two install paths:
notebooklm skill install
or, via the open skills ecosystem:
npx skills add teng-lin/notebooklm-py
The first drops the skill into ~/.claude/skills/notebooklm (and mirrors it into ~/.agents/skills/notebooklm for other agent frameworks that share the same skills convention). The second pulls the canonical SKILL.md straight from the GitHub repo, which is nice if you'd rather not trust a package's own installer to write into your home directory.
Once it’s in, Claude Code doesn’t need to be told the exact CLI syntax every time. You can just ask it something like “check the vendor API notebook for the rate limit terms before you write the integration code,” and the agent recognizes it has a tool for that, calls notebooklm ask itself, reads back the grounded answer, and only spends its own context on reasoning about the answer, not on re-deriving it from raw PDF text it would otherwise have had to ingest and chunk in-session.
That’s the “virtually unburdened” part of my original note, and having actually tried it, I think it’s a fair description with one important asterisk. The heavy lifting, ingesting a 40-page PDF, indexing it, running the retrieval, generating the answer, all of that happens on Google’s infrastructure through the NotebookLM backend. Claude Code’s context only ever sees the question and the grounded answer with citations, not the source document. For a source that’s tens of thousands of words, that’s a real, measurable reduction in what you’re paying to push through your own model’s context window, and it doesn’t degrade the deeper you go into a long agent session, because the notebook’s index doesn’t live in Claude’s context at all. It lives in NotebookLM, persistently, across sessions.
The asterisk: this is browser-automation-backed for interactive auth, which means, per the project’s own documentation, it only works with local Claude Code, not the Claude Code web UI or fully sandboxed cloud environments that block outbound browser automation. If your agent runs in a locked-down cloud sandbox, you’re either setting up master-token auth ahead of time, or this pipeline isn’t for that particular deployment. Worth checking before you build a workflow around it and then discover your CI runner can’t do the one thing the whole pipeline depends on.
A pattern I didn’t expect: baking research into a permanent skill
The use case that actually sold me on this wasn’t the live “ask NotebookLM mid-task” loop, it was using it once, up front, to build something durable. The idea is straightforward once you see it: point NotebookLM at your actual source material, get grounded, cited answers about what the material really says, then bake the distilled findings directly into a SKILL.md file. The resulting skill works completely offline afterward. No runtime network call to NotebookLM, no dependency on your Google auth still being valid six months later. You paid the research cost once, on Google's compute, and kept the output.
I tried this on a smaller scale than a full vendor integration, just condensing three overlapping internal runbooks into one skill file Claude Code could reference without re-reading all three documents every single time it needed a deployment step. The difference between “Claude guessing from a document it partially remembers seeing three messages ago” and “Claude reading a tight, pre-verified summary with the ambiguous bits already resolved” is not subtle. It shows up immediately in how confidently and correctly the agent answers follow-up questions, because there’s no ambiguity left for it to paper over with a plausible-sounding guess.
There’s a second version of this pattern worth knowing about: generating a NotebookLM quiz from your source material and using it as a self-validating eval set. You get a set of questions with known-correct answers, grounded in your actual documents, and you can grade your agent’s output against it without hand-writing test cases yourself.
notebooklm generate quiz --difficulty hard
notebooklm download quiz --format json ./eval/vendor-quiz.json
That’s a legitimately clever use of a feature that on its surface looks like it’s meant for students studying a textbook.
Where the “unofficial” part actually bit me
I want to be straight about this because the project itself is straight about it, right there in its own contributor docs: this library talks to Google’s internal batchexecute RPC protocol using obfuscated method IDs, and those IDs can and do change without notice. It is not affiliated with Google, and it isn't using a documented, stable, public API.
In practice, what that meant for me was one flaky command during setup that I initially assumed was my own auth problem, and turned out instead to be a source-ID nesting quirk the project’s own maintainer docs actually call out directly, the format varies between [id], [[id]], [[[id]]], and even four levels deep depending on which endpoint you're hitting. That's not the kind of bug you'd hit in a stable, versioned public API. It's the kind of bug you hit when a library is doing careful, ongoing reverse-engineering of a product that was never designed to be automated. I don't say that to scare anyone off it, the maintainer clearly keeps close tabs on breakage and ships fixes fast, but if you're the kind of person who wants a guarantee that a pinned dependency version will keep working next quarter, this isn't that. Pin your version, expect the occasional forced upgrade, and don't build anything you can't afford to have break for a day.
The other honest caveat: NotebookLM’s own limits still apply underneath the CLI, because you’re still using the same backend a browser user would.
+------------+------------------+-------------------------+-------------------+
| Tier | Sources/notebook | Max per source | Notebooks/account |
+------------+------------------+-------------------------+-------------------+
| Free | 50 | 500,000 words / 200MB | 100 |
| Plus | 100 | 500,000 words / 200MB | 500 |
| Pro | 300 | 500,000 words / 200MB | 500 |
| Ultra | 500-600 | 500,000 words / 200MB | 500 |
+------------+------------------+-------------------------+-------------------+
Notice the middle column doesn’t move. Paying for a higher tier buys you more sources and more notebooks, not a bigger ceiling on any single document. If you’re trying to hand NotebookLM a single half-million-word monster file, upgrading your plan won’t help you, you need to split it first regardless of tier.
If you don’t want to depend on Google’s infrastructure at all
There’s no drop-in, fully self-hosted replacement for what NotebookLM is actually doing here, Gemini’s grounding and synthesis is the product, and you can’t run that part on your own hardware. But the underlying pattern the project is selling, offload heavy document ingestion so your agent’s context only sees distilled, grounded answers, is one you can approximate locally if you’d rather not authenticate a personal Google account into an automated pipeline, or you’re in an environment where outbound browser automation is a non-starter.
Here’s a minimal local stand-in, using Ollama for the model and Chroma for the vector store, exposed the same way: a small CLI Claude Code can call instead of reading raw documents itself.
# pull a model and start the local server
ollama pull llama3.1
ollama serve
pip install chromadb ollama --break-system-packages
# local_research.py
# A tiny local stand-in for the "ask a grounded question" step.
# Not a replacement for NotebookLM's citation quality, but it keeps
# the same shape: ingest once, query cheaply, keep raw text out of
# the agent's own context window.
import sys
import chromadb
import ollama
CLIENT = chromadb.PersistentClient(path="./local_notebook")
COLLECTION = CLIENT.get_or_create_collection("research")
MODEL = "llama3.1"
def ingest(path: str, chunk_size: int = 1200):
with open(path, "r", encoding="utf-8", errors="ignore") as f:
text = f.read()
chunks = [text[i:i + chunk_size] for i in range(0, len(text), chunk_size)]
ids = [f"{path}-{i}" for i in range(len(chunks))]
COLLECTION.add(documents=chunks, ids=ids, metadatas=[{"source": path}] * len(chunks))
print(f"ingested {len(chunks)} chunks from {path}")
def ask(question: str, n_results: int = 4):
hits = COLLECTION.query(query_texts=[question], n_results=n_results)
context = "\n\n---\n\n".join(hits["documents"][0])
sources = sorted({m["source"] for m in hits["metadatas"][0]})
resp = ollama.chat(model=MODEL, messages=[{
"role": "user",
"content": (
f"Answer using only this context. Cite which excerpt you used.\n\n"
f"Context:\n{context}\n\nQuestion: {question}"
),
}])
print(resp["message"]["content"])
print("\nSources:", ", ".join(sources))
if __name__ == " __main__":
cmd, arg = sys.argv[1], sys.argv[2]
if cmd == "ingest":
ingest(arg)
elif cmd == "ask":
ask(arg)
python local_research.py ingest ./contracts/vendor-sla-2026.pdf.txt
python local_research.py ask "What are the rate limits in the SLA?"
I’ll be direct about what this is and isn’t. It’s not going to match NotebookLM’s grounding quality, Gemini’s retrieval and synthesis is genuinely better tuned than a 40-line chunking script, and you lose the studio outputs (audio, video, slide decks) entirely. What you keep is the core architectural win: your agent’s context only ever sees the question and a short, sourced answer, never the raw document. If your constraint is “no Google account in the loop” rather than “no infrastructure at all,” this gets you most of the way there, and it’s a reasonable fallback to reach for when the browser-automation requirement rules NotebookLM out for a given environment.
Where I landed
I went into this expecting the “delegates heavy read work to Google’s infrastructure” line to be the kind of claim that sounds better in a README than it behaves in practice. It held up better than I expected. The CLI is clean, the citation-backed answers are a real step up from an agent hallucinating confidently about a document it half-remembers, and the pattern of baking one-time research into a permanent, offline SKILL.md is genuinely one of the more useful things I've done with an agent skill this year.
What I’d tell someone before they adopt this for anything that matters: treat the auth setup as the first thing you validate, not an afterthought, decide up front whether you’re running local Claude Code or something headless because that decision gates which auth path you even have available, and go in with eyes open about the unofficial-API risk. Pin a version, and don’t build something mission-critical on top of it without a fallback plan for the day Google changes an internal method ID and the maintainer hasn’t shipped the fix yet. For research offload, skill-building, and keeping an agent’s context clean while it works through a pile of documents, it’s a genuinely strong technique, clear commands and all. I just wouldn’t bet an on-call pager on it staying stable without watching the repo.
Tags: notebooklm, claude-code, ai-agents, llm, python, developer-tools, context-engineering
Top comments (0)