{"id":"b77cb9fc-cde1-44cd-9b90-45c70f9ea72f","shortId":"PG9EpR","kind":"skill","title":"blog-notebooklm","tagline":"Query Google NotebookLM notebooks for source-grounded, citation-backed answers from user-uploaded documents. Manages notebook library, handles Google authentication, and supports smart discovery. Works standalone via /blog notebooklm or internally from blog-write and blog-researc","description":"# Blog NotebookLM -- Source-Grounded Research from Your Documents\n\nQuery Google NotebookLM notebooks directly from Claude Code for citation-backed\nanswers from Gemini. Each question opens a headless browser session, retrieves\nthe answer exclusively from your uploaded documents, and closes. Responses are\nTier 1 quality (user's own primary sources) -- zero hallucination risk.\nAnswers satisfy the FLOW evidence triple: use the returned source title as the\ninline citation and the notebook URL plus retrieval date as the bibliography\nentry. This is the highest-confidence path to meeting the \"verified source\"\nbar that FLOW requires before any statistic goes public.\n\n## Quick Reference\n\n| Command | What it does |\n|---------|-------------|\n| `/blog notebooklm ask <question>` | Query a notebook for source-grounded answers |\n| `/blog notebooklm discover <url>` | Smart-discover notebook content before cataloging |\n| `/blog notebooklm library list` | List all notebooks in library |\n| `/blog notebooklm library add <url>` | Add a notebook to library |\n| `/blog notebooklm library search <query>` | Search notebooks by keyword |\n| `/blog notebooklm library remove <id>` | Remove a notebook from library |\n| `/blog notebooklm setup` | One-time Google authentication (browser visible) |\n| `/blog notebooklm status` | Check authentication status |\n| `/blog notebooklm cleanup` | Clean browser state (preserves library) |\n\n## Prerequisites\n\n- Google account with NotebookLM access\n- Python 3.11+ (venv managed automatically by `run.py`)\n- Google Chrome (installed automatically on first run via Patchright)\n- One-time authentication setup (interactive Google login in visible browser)\n\n## Always Use run.py Wrapper\n\n**NEVER call scripts directly. ALWAYS use `python3 scripts/run.py [script]`:**\n\n```bash\n# CORRECT:\npython3 scripts/run.py auth_manager.py status\npython3 scripts/run.py ask_question.py --question \"...\"\n\n# WRONG -- fails without venv:\npython3 scripts/auth_manager.py status\n```\n\nThe `run.py` wrapper automatically creates `.venv`, installs dependencies,\nsets up Chrome, and executes the target script.\n\n## Auth Check (Gate Pattern)\n\nBefore any query operation, check authentication:\n\n```bash\npython3 scripts/run.py auth_manager.py status\n```\n\n- If authenticated: proceed with the query\n- If not authenticated: inform user and guide to setup:\n  \"NotebookLM requires Google login. Run `/blog notebooklm setup` to authenticate.\"\n- **When called internally** (from blog-write or blog-researcher): return silently\n  with no error if not authenticated. Never block the writing workflow.\n\n## Setup Workflow\n\nFor `/blog notebooklm setup`:\n\n```bash\n# Opens a visible browser for manual Google login (one-time)\npython3 scripts/run.py auth_manager.py setup\n```\n\nTell the user: \"A browser window will open. Please log in to your Google account.\"\nAuthentication persists via browser profile + cookie injection (hybrid approach).\n\nOther auth commands:\n```bash\npython3 scripts/run.py auth_manager.py status   # Check auth\npython3 scripts/run.py auth_manager.py reauth   # Re-authenticate\npython3 scripts/run.py auth_manager.py clear     # Clear all auth data\n```\n\n## Query Workflow\n\nFor `/blog notebooklm ask <question>`:\n\n### Step 1: Check Auth\nRun auth check (see gate pattern above). If not authenticated, guide to setup.\n\n### Step 2: Resolve Notebook\nDetermine which notebook to query:\n- If `--notebook-url` provided: use directly\n- If `--notebook-id` provided: look up in library\n- If neither: use active notebook from library\n- If no active notebook: show library and ask user to select\n\n### Step 3: Ask the Question\n```bash\n# Basic query (uses active notebook)\npython3 scripts/run.py ask_question.py --question \"Your question here\"\n\n# Query specific notebook by ID\npython3 scripts/run.py ask_question.py --question \"...\" --notebook-id notebook-id\n\n# Query by URL directly\npython3 scripts/run.py ask_question.py --question \"...\" --notebook-url \"https://...\"\n\n# JSON output (for internal/programmatic use)\npython3 scripts/run.py ask_question.py --question \"...\" --json\n\n# Show browser for debugging\npython3 scripts/run.py ask_question.py --question \"...\" --show-browser\n```\n\n### Step 4: Analyze and Follow Up\nEvery response ends with a follow-up prompt. **Required behavior:**\n1. **STOP** -- do not immediately respond to the user\n2. **ANALYZE** -- compare the answer to the user's original request\n3. **IDENTIFY GAPS** -- determine if more information is needed\n4. **ASK FOLLOW-UP** -- if gaps exist, immediately ask a follow-up question\n5. **REPEAT** -- continue until information is complete\n6. **SYNTHESIZE** -- combine all answers before responding to the user\n\n## Smart Discovery Workflow\n\nFor `/blog notebooklm discover <url>`:\n\nWhen adding a notebook without knowing its content, query it first:\n\n```bash\n# Step 1: Discover content\npython3 scripts/run.py ask_question.py \\\n  --question \"What is the content of this notebook? What topics are covered? Provide a complete overview briefly and concisely\" \\\n  --notebook-url \"<URL>\"\n\n# Step 2: Add with discovered metadata\npython3 scripts/run.py notebook_manager.py add \\\n  --url \"<URL>\" \\\n  --name \"<Based on content>\" \\\n  --description \"<Based on content>\" \\\n  --topics \"<Extracted topics>\"\n```\n\n**NEVER guess or use generic descriptions.** Always discover or ask the user.\n\n## Library Management\n\n```bash\n# List all notebooks\npython3 scripts/run.py notebook_manager.py list\n\n# Add notebook (all params required -- discover or ask user!)\npython3 scripts/run.py notebook_manager.py add \\\n  --url \"https://notebooklm.google.com/notebook/...\" \\\n  --name \"Descriptive Name\" \\\n  --description \"What this notebook contains\" \\\n  --topics \"topic1,topic2,topic3\"\n\n# Search by keyword\npython3 scripts/run.py notebook_manager.py search --query \"keyword\"\n\n# Set active notebook\npython3 scripts/run.py notebook_manager.py activate --id notebook-id\n\n# Remove notebook\npython3 scripts/run.py notebook_manager.py remove --id notebook-id\n\n# Library statistics\npython3 scripts/run.py notebook_manager.py stats\n```\n\n## Internal API (for blog-write / blog-researcher)\n\nWhen invoked as a Task subagent from blog-write or blog-researcher:\n\n**Input** (provided by calling skill):\n- `question`: Research question relevant to the blog topic\n- `notebook_id` or `notebook_url`: Which notebook to query\n- `context`: \"internal\" (signals graceful fallback mode)\n\n**Process:**\n1. Check auth status -- if not authenticated, return empty result silently\n2. Query the notebook with the research question\n3. Parse and return structured response\n\n**Output** (returned to calling skill):\n```markdown\n### NotebookLM Research\n- **Source:** [Notebook name]\n- **Question:** [What was asked]\n- **Answer:** [Source-grounded response from user's documents]\n- **Source Quality:** Tier 1 (user-uploaded primary documents)\n```\n\n**Graceful fallback:** If auth is missing or query fails, return immediately\nwith no error. The calling workflow continues with WebSearch-based research.\nNever block blog-write or blog-rewrite because NotebookLM is unavailable.\n\n## Data Storage\n\nAll data stored inside the skill directory:\n- `scripts/data/library.json` -- Notebook metadata and library\n- `scripts/data/auth_info.json` -- Authentication status\n- `scripts/data/browser_state/` -- Chrome profile with cookies\n\n**Security:** All data directories are gitignored. Never commit auth or browser state.\n\n## Error Handling\n\n| Error | Resolution |\n|-------|-----------|\n| Not authenticated | Run `/blog notebooklm setup` |\n| ModuleNotFoundError | Always use `run.py` wrapper |\n| Browser crash | `cleanup_manager.py --confirm --preserve-library`, then re-auth |\n| Rate limit (50/day) | Wait until midnight PST or switch Google account |\n| Notebook not found | Check with `notebook_manager.py list` |\n| Query timeout (120s) | Retry with simpler question or `--show-browser` to debug |\n| MCP unavailable (internal) | Return silently -- writing workflow uses WebSearch |\n\n## Limitations\n\n- No session persistence (each question = new browser session)\n- Rate limits on free Google accounts (50 queries/day)\n- Manual upload required (user must add docs to NotebookLM web UI)\n- Browser overhead (few seconds per question for launch + teardown)\n- Local Claude Code only (not available in web UI)\n\n## Reference Documentation\n\nLoad on-demand -- do NOT load all at startup:\n- `references/commands.md` -- Full CLI commands, parameters, and workflow patterns\n- `references/troubleshooting.md` -- Error solutions, recovery procedures, debugging","tags":["blog","notebooklm","claude","agricidaniel","agent-skills","ai-citations","ai-content","ai-marketing","ai-marketing-hub","blog-writing","claude-code","claude-code-skill"],"capabilities":["skill","source-agricidaniel","skill-blog-notebooklm","topic-agent-skills","topic-ai-citations","topic-ai-content","topic-ai-marketing","topic-ai-marketing-hub","topic-blog","topic-blog-writing","topic-claude-code","topic-claude-code-skill","topic-claude-plugin","topic-claude-skill","topic-content-creation"],"categories":["claude-blog"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/AgriciDaniel/claude-blog/blog-notebooklm","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add AgriciDaniel/claude-blog","source_repo":"https://github.com/AgriciDaniel/claude-blog","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 753 github stars · SKILL.md body (8,521 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:53:30.791Z","embedding":null,"createdAt":"2026-05-18T12:54:53.684Z","updatedAt":"2026-05-18T18:53:30.791Z","lastSeenAt":"2026-05-18T18:53:30.791Z","tsv":"'/blog':34,153,164,174,183,192,200,209,219,225,347,379,450,660,992 '/notebook/...':756 '1':90,454,595,676,857,909 '120s':1031 '2':471,604,705,868 '3':514,615,876 '3.11':240 '4':579,624 '5':639 '50':1066 '50/day':1013 '6':646 'access':238 'account':235,412,1021,1065 'activ':498,504,522,779,784 'ad':664 'add':186,187,706,713,740,752,1073 'alway':266,274,724,996 'analyz':580,605 'answer':15,67,79,100,163,608,650,897 'api':806 'approach':421 'ask':155,452,509,515,625,633,727,747,896 'ask_question.py':287,526,538,552,564,573,681 'auth':312,423,431,445,456,458,859,918,981,1010 'auth_manager.py':283,325,396,428,434,441 'authent':26,216,223,258,321,328,335,351,370,413,438,466,863,966,990 'automat':243,249,299 'avail':1093 'back':14,66 'bar':138 'base':936 'bash':279,322,382,425,518,674,732 'basic':519 'behavior':594 'bibliographi':124 'block':372,939 'blog':2,40,44,46,357,361,809,812,822,826,839,941,945 'blog-notebooklm':1 'blog-researc':43 'blog-research':360,811,825 'blog-rewrit':944 'blog-writ':39,356,808,821,940 'briefli':698 'browser':75,217,229,265,386,402,416,568,577,983,1000,1039,1058,1079 'call':271,353,831,885,930 'catalog':173 'check':222,313,320,430,455,459,858,1025 'chrome':247,306,969 'citat':13,65,114 'citation-back':12,64 'claud':61,1089 'clean':228 'cleanup':227 'cleanup_manager.py':1002 'clear':442,443 'cli':1111 'close':86 'code':62,1090 'combin':648 'command':149,424,1112 'commit':980 'compar':606 'complet':645,696 'concis':700 'confid':131 'confirm':1003 'contain':764 'content':171,670,678,686 'context':850 'continu':641,932 'cooki':418,972 'correct':280 'cover':693 'crash':1001 'creat':300 'data':446,951,954,975 'date':121 'debug':570,1041,1122 'demand':1102 'depend':303 'descript':716,723,758,760 'determin':474,618 'direct':59,273,485,549 'directori':959,976 'discov':166,169,662,677,708,725,745 'discoveri':30,657 'doc':1074 'document':20,54,84,905,914,1098 'empti':865 'end':586 'entri':125 'error':367,928,985,987,1118 'everi':584 'evid':104 'exclus':80 'execut':308 'exist':631 'fail':290,923 'fallback':854,916 'first':251,673 'flow':103,140 'follow':582,590,627,636 'follow-up':589,626,635 'found':1024 'free':1063 'full':1110 'gap':617,630 'gate':314,461 'gemini':69 'generic':722 'gitignor':978 'goe':145 'googl':5,25,56,215,234,246,261,344,389,411,1020,1064 'grace':853,915 'ground':11,50,162,900 'guess':719 'guid':339,467 'hallucin':98 'handl':24,986 'headless':74 'highest':130 'highest-confid':129 'hybrid':420 'id':489,535,542,545,785,788,795,798,842 'identifi':616 'immedi':599,632,925 'inform':336,621,643 'inject':419 'inlin':113 'input':828 'insid':956 'instal':248,302 'interact':260 'intern':37,354,805,851,1044 'internal/programmatic':560 'invok':815 'json':557,566 'keyword':199,771,777 'know':668 'launch':1086 'librari':23,176,182,185,191,194,202,208,232,494,501,507,730,799,964,1006 'limit':1012,1051,1061 'list':177,178,733,739,1028 'load':1099,1105 'local':1088 'log':407 'login':262,345,390 'look':491 'manag':21,242,731 'manual':388,1068 'markdown':887 'mcp':1042 'meet':134 'metadata':709,962 'midnight':1016 'miss':920 'mode':855 'modulenotfounderror':995 'must':1072 'name':715,757,759,892 'need':623 'neither':496 'never':270,371,718,938,979 'new':1057 'notebook':7,22,58,117,158,170,180,189,197,206,473,476,481,488,499,505,523,533,541,544,555,666,689,702,735,741,763,780,787,790,797,841,844,847,871,891,961,1022 'notebook-id':487,540,543,786,796 'notebook-url':480,554,701 'notebook_manager.py':712,738,751,774,783,793,803,1027 'notebooklm':3,6,35,47,57,154,165,175,184,193,201,210,220,226,237,342,348,380,451,661,888,948,993,1076 'notebooklm.google.com':755 'notebooklm.google.com/notebook/...':754 'on-demand':1100 'one':213,256,392 'one-tim':212,255,391 'open':72,383,405 'oper':319 'origin':613 'output':558,882 'overhead':1080 'overview':697 'param':743 'paramet':1113 'pars':877 'patchright':254 'path':132 'pattern':315,462,1116 'per':1083 'persist':414,1054 'pleas':406 'plus':119 'prerequisit':233 'preserv':231,1005 'preserve-librari':1004 'primari':95,913 'procedur':1121 'proceed':329 'process':856 'profil':417,970 'prompt':592 'provid':483,490,694,829 'pst':1017 'public':146 'python':239 'python3':276,281,285,293,323,394,426,432,439,524,536,550,562,571,679,710,736,749,772,781,791,801 'qualiti':91,907 'queri':4,55,156,318,332,447,478,520,531,546,671,776,849,869,922,1029 'queries/day':1067 'question':71,288,517,527,529,539,553,565,574,638,682,833,835,875,893,1035,1056,1084 'quick':147 'rate':1011,1060 're':437,1009 're-auth':1008 're-authent':436 'reauth':435 'recoveri':1120 'refer':148,1097 'references/commands.md':1109 'references/troubleshooting.md':1117 'relev':836 'remov':203,204,789,794 'repeat':640 'request':614 'requir':141,343,593,744,1070 'researc':45 'research':51,362,813,827,834,874,889,937 'resolut':988 'resolv':472 'respond':600,652 'respons':87,585,881,901 'result':866 'retri':1032 'retriev':77,120 'return':108,363,864,879,883,924,1045 'rewrit':946 'risk':99 'run':252,346,457,991 'run.py':245,268,297,998 'satisfi':101 'script':272,278,311 'scripts/auth_manager.py':294 'scripts/data/auth_info.json':965 'scripts/data/browser_state':968 'scripts/data/library.json':960 'scripts/run.py':277,282,286,324,395,427,433,440,525,537,551,563,572,680,711,737,750,773,782,792,802 'search':195,196,769,775 'second':1082 'secur':973 'see':460 'select':512 'session':76,1053,1059 'set':304,778 'setup':211,259,341,349,376,381,397,469,994 'show':506,567,576,1038 'show-brows':575,1037 'signal':852 'silent':364,867,1046 'simpler':1034 'skill':832,886,958 'skill-blog-notebooklm' 'smart':29,168,656 'smart-discov':167 'solut':1119 'sourc':10,49,96,109,137,161,890,899,906 'source-agricidaniel' 'source-ground':9,48,160,898 'specif':532 'standalon':32 'startup':1108 'stat':804 'state':230,984 'statist':144,800 'status':221,224,284,295,326,429,860,967 'step':453,470,513,578,675,704 'stop':596 'storag':952 'store':955 'structur':880 'subag':819 'support':28 'switch':1019 'synthes':647 'target':310 'task':818 'teardown':1087 'tell':398 'tier':89,908 'time':214,257,393 'timeout':1030 'titl':110 'topic':691,717,765,840 'topic-agent-skills' 'topic-ai-citations' 'topic-ai-content' 'topic-ai-marketing' 'topic-ai-marketing-hub' 'topic-blog' 'topic-blog-writing' 'topic-claude-code' 'topic-claude-code-skill' 'topic-claude-plugin' 'topic-claude-skill' 'topic-content-creation' 'topic1':766 'topic2':767 'topic3':768 'tripl':105 'ui':1078,1096 'unavail':950,1043 'upload':19,83,912,1069 'url':118,482,548,556,703,714,753,845 'use':106,267,275,484,497,521,561,721,997,1049 'user':18,92,337,400,510,603,611,655,729,748,903,911,1071 'user-upload':17,910 'venv':241,292,301 'verifi':136 'via':33,253,415 'visibl':218,264,385 'wait':1014 'web':1077,1095 'websearch':935,1050 'websearch-bas':934 'window':403 'without':291,667 'work':31 'workflow':375,377,448,658,931,1048,1115 'wrapper':269,298,999 'write':41,358,374,810,823,942,1047 'wrong':289 'zero':97","prices":[{"id":"c35de2bf-a13f-4ef4-91c9-a5e1a830fa7b","listingId":"b77cb9fc-cde1-44cd-9b90-45c70f9ea72f","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"AgriciDaniel","category":"claude-blog","install_from":"skills.sh"},"createdAt":"2026-05-18T12:54:53.684Z"}],"sources":[{"listingId":"b77cb9fc-cde1-44cd-9b90-45c70f9ea72f","source":"github","sourceId":"AgriciDaniel/claude-blog/blog-notebooklm","sourceUrl":"https://github.com/AgriciDaniel/claude-blog/tree/main/skills/blog-notebooklm","isPrimary":false,"firstSeenAt":"2026-05-18T12:54:53.684Z","lastSeenAt":"2026-05-18T18:53:30.791Z"}],"details":{"listingId":"b77cb9fc-cde1-44cd-9b90-45c70f9ea72f","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"AgriciDaniel","slug":"blog-notebooklm","github":{"repo":"AgriciDaniel/claude-blog","stars":753,"topics":["agent-skills","ai","ai-citations","ai-content","ai-marketing","ai-marketing-hub","blog","blog-writing","claude-code","claude-code-skill","claude-plugin","claude-skill","content-creation","content-optimization","content-strategy","eeat","geo","multilingual","open-source","seo"],"license":"mit","html_url":"https://github.com/AgriciDaniel/claude-blog","pushed_at":"2026-05-15T04:45:18Z","description":"Claude Code blog skill suite: 30 sub-skills, 5 agents, 5-gate v1.9.0 Blog Delivery Contract, dual-optimized for Google rankings and AI citations. Active development at AI-Marketing-Hub/claude-blog (AI Marketing Hub Pro community); public releases ship here.","skill_md_sha":"3dd686855e420352eb849b673d4d66591988653b","skill_md_path":"skills/blog-notebooklm/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/AgriciDaniel/claude-blog/tree/main/skills/blog-notebooklm"},"layout":"multi","source":"github","category":"claude-blog","frontmatter":{"name":"blog-notebooklm","license":"MIT","description":"Query Google NotebookLM notebooks for source-grounded, citation-backed answers from user-uploaded documents. Manages notebook library, handles Google authentication, and supports smart discovery. Works standalone via /blog notebooklm or internally from blog-write and blog-researcher for Tier 1 research data. Falls back gracefully when not configured. Use when user says \"notebooklm\", \"notebook\", \"query notebook\", \"ask notebook\", \"notebook research\", \"source grounded research\", \"document query\", \"notebook library\"."},"skills_sh_url":"https://skills.sh/AgriciDaniel/claude-blog/blog-notebooklm"},"updatedAt":"2026-05-18T18:53:30.791Z"}}