Home / All Skills / Content & Media Creation / notebooklm-skill
Content & Media Creation · PleasePrompto/notebooklm-skill

notebooklm-skill

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.

L5 Restricted · Isolated sandbox & strict auditV2 Human-AuditedTerms / ComplianceCredential / SessionExecute CommandInstall DepsNetwork AccessWrite FileDual-pass Audit
Author PleasePromptoGitHub PleasePrompto/notebooklm-skill ↗Stars 7772License MIT(仓库根 LICENSE:L1 'MIT License'、L3 'Copyright (c) 2025 Please Prompto!')Commit c80722d3f2
Control levels describe skill capabilities and suggested control measures; they do not represent quality or safety certifications, nor do they dictate usability. Usage decisions rest entirely with users and administrators. Different agent hosts apply varying constraints; do not assume hosts provide automatic protection. Third-party skill copyrights belong to their original authors. Use at your own risk.

1How It Works & Mechanism

Launches a **persistent user profile in a real Chrome browser** using patchright (an anti-detection fork of Playwright) instead of an ephemeral browser instance—serving as the foundation for maintaining a 'logged-in' state across multiple invocations.

scripts/browser_utils.py
channel="chrome", # Use real Chrome
During a single call, it passes user_data_dir=user_data_dir, ignore_default_args=["--enable-automation"], user_agent=USER_AGENT, args=BROWSER_ARGS; the profile directory is <skill>/data/browser_state/browser_profile (config.py's BROWSER_PROFILE_DIR).

During the authentication phase, it opens a visible browser waiting for manual user login, then persists cookies + localStorage into state.json—this file acts as the credential for the entire pipeline, not an API key.

scripts/auth_manager.py
context.storage_state(path=str(self.state_file))
state_file = <skill>/data/browser_state/state.json (config.py:13); waiting for login relies on a URL regex + a 10-minute timeout (LOGIN_TIMEOUT_MINUTES = 10).

At runtime, it manually injects cookies from state.json into the browser context to work around Playwright's known limitation where 'session cookies are not written to user_data_dir'.

scripts/browser_utils.py
context.add_cookies(state['cookies'])
launch_persistent_context internally calls _inject_cookies by default; read failures only log warnings without interrupting execution. The code example in AUTHENTICATION.md labels this step as `# ← Workaround for session cookies!`.

Each question operates as 'one question, one browser session': creates a new page → navigates to the user-provided notebook URL → waits on a DNS-level whitelist (only allowing returns to the notebooklm.google.com domain to confirm it has not been kicked back to the login page).

scripts/ask_question.py
page.goto(notebook_url, wait_until="domcontentloaded")
Immediately followed by page.wait_for_url(re.compile(r"^https://notebooklm\.google\.com/"), timeout=10000); both SKILL.md and README state 'Each question opens a fresh browser session', with a maximum timeout of 120s (QUERY_TIMEOUT_SECONDS = 120).

Question text is typed into the textarea character-by-character using 'human-like typing', featuring a three-tier selector fallback (including German aria-label); if input box location fails, the entire pipeline fails.

scripts/config.py
"textarea.query-box-input", # Primary
Fallback items are 'textarea[aria-label="Feld für Anfragen"]' (German text) and 'textarea[aria-label="Input for queries"]' (English); actual submission is triggered via the keyboard Enter key.

Retrieves the answer via polling stability checks: waits for `div.thinking-message` to disappear, grabs the text of the last element in the response container, and requires it to remain identical across multiple consecutive checks before considering the answer complete.

scripts/ask_question.py
thinking_element = page.query_selector('div.thinking-message')
The response container selector is `.to-user-container .message-text-content` (config.py:25); after retrieving elements[-1].inner_text().strip(), it requires stable_count >= 3 without exceeding the 120s deadline.

The script forcibly appends an imperative prompt directed at Claude to the end of the answer text before returning it to stdout, forming a closed loop that mandates 'must continue asking follow-up questions'.

scripts/ask_question.py
return answer + FOLLOW_UP_REMINDER
FOLLOW_UP_REMINDER states its origin as adapted from a stateless MCP server version; the Follow-Up Mechanism section in SKILL.md further mandates that Claude must STOP / ANALYZE / IDENTIFY GAPS / ASK FOLLOW-UP.

run.py is the sole officially recommended entry point: if .venv is missing, it first bootstraps using the system Python via setup_environment.py, then executes the target script using the venv interpreter.

scripts/run.py
result = subprocess.run([sys.executable, str(setup_script)])
Subsequently, cmd = [str(venv_python), str(script_path)] + script_args and subprocess.run(cmd); setup_environment.py executes `pip install -r requirements.txt` and `python -m patchright install chrome`.

The notebook library is purely local JSON metadata (url/name/description/topics/use_count) without any vector database or content cache—the 'grounding' actually occurs on Google's side, not locally.

scripts/notebook_manager.py
self.library_file = self.data_dir / "library.json"
data_dir is derived via Path(__file__).parent.parent / 'data'; _save_library persists to disk using json.dump(data, f, indent=2).

2Core Capabilities

01Query a specified NotebookLM notebook and retrieve Gemini's answer text
02Log in to Google once and reuse credentials long-term (persistent profile + state.json cookie injection)
03Multi-notebook library management (add/delete/search/activate/statistics, stored in local library.json)
04Environment bootstrapping: automatically create .venv, install dependencies, and download Chrome binaries
05Anti-detection interactions (character-by-character typing + random delays + disabling automation features)
06Local data cleanup (can preserve the library while never deleting .venv)

3External Dependencies

KindDependency / Endpoint
networkGoogle NotebookLM 站点(浏览器自动化目标)
network提问页 URL 白名单校验(确认未被重定向去登录)
networkGoogle 账号登录态判定(字符串检测,非主动请求)
packagepatchright(Playwright 反检测分支,浏览器自动化核心)
packagepython-dotenv(声明为依赖,但代码从未使用)
clipip 安装依赖(走默认 PyPI)
cli下载安装 Google Chrome 二进制
cli另一条安装路径装的是 chromium(与上一条不一致)

4Recommended Governance & Evidence

Suggested Controls for Safe Operation
For Agent Runtime
Isolated environment, per-use explicit authorization
For Administrators
Strict authorization, full audit, compliance signoff
Evidence & Triggers (File Paths & Excerpts)
  • SKILL.md / 脚本参数: Involves bypassing automation detection, disabling host sandbox, or skipping SSL certificate validation
  • SKILL.md / 会话存储: Reads or reuses browser user login state and session cookies
  • 本地凭据 / 浏览器配置: Reads user login cookies/sessions/keyrings: The cookie database in the browser profile is read and written by Chrome itself (user_data_dir points to <skill>/data/browse
  • scripts/: Executes local scripts or commands: run.py runs setup_environment.py using the system interpreter when .venv is missing: `result = subprocess.run([sy
  • scripts/ 或 SKILL.md: Declares dynamic installation of external language package dependencies
  • 网络端点: Declares external network access: Browser automation accesses Google NotebookLM: `page.goto("https://notebooklm.google.com", wait
  • 本地工作目录: File read/write and artifact output: Writes state.json (containing all Google session cookies): `context.storage_state(path=str(self.st
Audit Notes: 🔴 Red: Strictly controlled. This skill triggers three red flags simultaneously, each supported by source code evidence: ① Anti-scraping bypass / automation detection evasion—relies on patchright (requirements.txt comments state 'Core browser automation with anti-detection') and passes `'--disable-blink-features=AutomationControlled', # Patches navigator.webdriver`, launching the browser specifically to conceal automation flags; ② Security degradation—the same BROWSER_ARGS includes `'--no-sandbox'`, running the browser without sandbox protection; ③ Credential access—the authentication artifact is data/browser_state/state.json containing Google session cookies, which the code actively reads and injects back into the browser context at runtime (.gitignore notes this directory 'contains auth and personal notebooks'). Additionally, the first run automatically creates a venv, installs dependencies from PyPI, and downloads Chrome binaries during import. These behaviors stem from its architecture (driving a web-only Google product requires a browser) rather than hidden malicious intent, but users must be clearly informed: login state is written in plain text to disk, the browser is intentionally disguised as non-automated, and the sandbox is disabled.

5Second-Pass Verification

  • [ok] skill.path = '.'(根级 SKILL.md) — 重读 SKILL.md L1-4 确认 frontmatter 位于仓库根文件;glob 根 *.json 无命中(无 plugin.json / marketplace.json),故技能入口就是仓库根。
  • [ok] official_desc 逐字 — 重读 SKILL.md L2-4:name: notebooklm、description 为单行完整句,与 README L15 的同一句(README 用连字符 'Drastically reduced hallucinations - answers only from your uploaded documents.')措辞略异,已按 frontmatter 原文收录。
  • [ok] 混合认证机制(persistent profile + state.json 注入) — 重读 browser_utils.py(launch_persistent_context 与 `context.add_cookies(state['cookies'])`)与 auth_manager.py(`context.storage_state(path=str(self.state_file))`),行号与首遍一致;AUTHENTICATION.md 的说明标注的脚本行号与实码相差数行(文档漂移),机制描述本身正确。
  • [ok] 安全结论:反检测与沙箱关闭 — 重读 config.py 的 BROWSER_ARGS 列表:`'--disable-blink-features=AutomationControlled', # Patches navigator.webdriver` 与 `'--no-sandbox',` 逐字确认;重读 requirements.txt 首段注释确认 'anti-detection' 表述与 patchright pin。三条红色判据均在源码可定位。
  • [ok] 安全结论:凭证读取范围 — 独立重扫 os.environ|getenv|API_KEY|token|keychain|.env|ssh|credentials:scripts 下零命中(唯二 token 字样在 requirements.txt 与文档中的 python-dotenv)。凭证只有 state.json 里的 Google cookie,路径由 config.py 常量推导,无 ~/.claude 硬编码。
  • [ok] 安全结论:网络外发范围 — 重扫 requests|urllib|socket|http.client 于 scripts:零命中;网络只经浏览器(notebooklm.google.com / accounts.google.com)、pip(PyPI)与 patchright 下载 Chrome(域名不可定位,已记入 unlocated)。
  • [ok] 安全结论:写盘与删除边界 — 重读 auth_manager、notebook_manager、cleanup_manager、__init__ 的写路径:state.json / auth_info.json / library.json / .venv,全部位于 <skill>/data 与 <skill>/.venv;删除限定在 data/ 且显式排除 .venv(`Virtual environment (.venv) is never deleted`)。
  • [discrepancy] 宣称 vs 实际:citation-backed — 脚本内无任何 citation/来源条目的解析代码,唯一取数路径是响应容器最后一元素的 inner_text;README L65 与 SKILL.md 的 citation 表述实际描述的是 NotebookLM/Gemini 侧行为,本 skill 只做纯文本透传,不能保证引用随答案回到模型上下文。

6Verdict & Scenarios

  • Turns 'grounded Q&A using web products' into a reusable CLI pipeline, providing independent executable entry points for Q&A, library management, authentication, environment bootstrapping, and cleanup
  • Achieves a 'login once, use long-term' authentication experience while explicitly working around and documenting Playwright's known cookie limitations
  • Restricts answer sources to the user's own document collection, genuinely minimizing hallucinations—a core selling point over generic web search
  • Clear local data boundaries: writes are confined to data/ and .venv, the cleanup utility explicitly excludes .venv, and deletions require --confirm and interactive confirmation
  • Best for: Ideal for individual researchers and content creators who already manage documents with Google NotebookLM and want to query notebooks directly from their coding agent sessions (requiring answers sourced strictly from their uploaded documents). Also suitable as a reference implementation for developers studying the 'browser automation + persistent login' pattern (authentication, cookie injection, and answer stability polling checks are clearly written and readable). Prerequisites include accepting that Google login state is saved locally on disk and bearing the account risks associated with web automation.
    Not for: Not suitable for account-security-sensitive or managed environments—it runs the browser in anti-detection mode, disables the sandbox, and stores full session cookies on disk. Not suitable for pipelines requiring long-term operational stability: the repository is archived, selectors are hardcoded, and upstream web UI changes can break the entire workflow. Not suitable for scenarios requiring audit trails or reproducible citations (citations are only claimed at the document level; the script does not parse sources). Not suitable for users expecting 'local RAG': grounding occurs on Google's side, and the local machine only stores notebook metadata without content indexing or vector databases.
    Install Agent-Ready
    ① Verified Mirror 2026-09-15
    Option A · Direct DownloadDownload notebooklm-skill.tar.gz
    sha256: edda31a0efaa9b1c…
    Option B · Copy Guide for Agent
    install.json
    Agents automatically download and verify mirrors from this JSON guide.
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit c80722d3f2.