
Notebooklm Create
- 49 installs
- 6 repo stars
- Updated July 22, 2026
- julianobarbosa/claude-code-skills
Helps with productivity & planning tasks.
About
notebooklm-create is a Claude Code skill for productivity & planning. It helps solo builders move faster with AI-assisted development.
- notebooklm-create
- Productivity & Planning
- AI-coding skill
Notebooklm Create by the numbers
- 49 all-time installs (skills.sh)
- +1 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #1,626 of 3,282 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/julianobarbosa/claude-code-skills --skill notebooklm-createAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 49 |
|---|---|
| repo stars | ★ 6 |
| Last updated | July 22, 2026 |
| Repository | julianobarbosa/claude-code-skills ↗ |
What it does
Helps with productivity & planning tasks.
Files
notebooklm-create
End-to-end workflow for building a complete NotebookLM topic notebook: deep research, source loading, full Studio, curated prompts. Orchestrates the notebooklm-rpc MCP tools with domain-specific gotcha handling encoded.
Relationship to notebooklm-skill
notebooklm-skill= low-level API reference (notebooklm-py CLI)- This skill (`notebooklm-create`) = high-level workflow orchestration using the
notebooklm-rpcMCP tools available in this session
If the user just wants to call a single API (e.g., "list my notebooks"), use notebooklm-skill or the MCP tool directly. If they want to BUILD a research notebook from a topic, use this skill.
Why this workflow exists
Building a rich NotebookLM notebook for a topic has repeatable shape but is strewn with gotchas that cost real time if rediscovered:
- Some domains silently refuse NotebookLM's URL fetcher (Medium, Quora)
- URL adds cascade-fail when issued in parallel — must be sequential
llms.txtURLs need the trailing.mdstripped before adding- Studio artifacts split into synchronous (mind map, reports, flashcards, quiz, data table) and async (audio, video, infographic, slide deck) with different polling behavior
- The Studio API classifies quiz artifacts as
type: flashcardsonce generated (title disambiguates) confirm=Trueis mandatory on every Studio creation tool AND requires explicit user approval
This skill encodes all of that so future runs don't relearn it.
Workflow — the 7 phases
Run these in order. Each phase has a clear hand-off to the next.
Phase 1 — Capture intent
Ask or infer:
1. What's the topic? (e.g., "cmux", "ArgoCD image updater", "Azure landing zones") 2. Any seed URLs the user already wants included (videos, blog posts, GitHub repos)? 3. Which forums to cover? Defaults: Reddit, Hacker News, GitHub Discussions. Optional: Discord (captured as text — not URL-indexable), Quora (usually empty for technical topics; confirm via research) 4. Target notebook title — default convention: {topic} :: docs (matches user's existing naming pattern visible via notebook_list) 5. Does the user want the full Studio (all 10 artifacts) or selective?
If the topic name is ambiguous (multiple projects share the name — common: cmux = manaflow-ai vs craigsc vs coder), anchor disambiguation on the user's seed URLs before researching.
Phase 2 — Deep research
Goal: produce two artifacts — a research synthesis and a community content dossier. Both become text sources in the notebook.
Read references/prompt-library.md for prompt starters. Use WebFetch on user-provided seed URLs first to lock in disambiguation, then WebSearch for canonical repo / docs / llms.txt.
Dispatch two parallel agents (via the Agent tool with general-purpose subagent):
1. Research synthesis agent — produces 2000–3000 word markdown covering overview, architecture, features, comparisons, installation, traction, limitations, official URLs. Output template: assets/research_synthesis_template.md.
2. Community content agent — searches Reddit, Hacker News, GitHub Discussions for threads, extracts verbatim quotes with attribution. Captures Discord community texture by pulling equivalent content from GitHub Discussions (Discord isn't publicly scrapeable). Confirms Quora status (usually no threads for technical topics). Output template: assets/community_content_template.md.
Both agents should return ready-to-paste markdown. Save locally under MEMORY/WORK/<slug>/.
Phase 3 — Create the notebook
Use mcp__notebooklm-rpc__notebook_create with the agreed title.
mcp__notebooklm-rpc__notebook_create(title="{topic} :: docs")Capture the returned notebook.id — you'll need it for every subsequent call.
Verify no duplicate exists first via mcp__notebooklm-rpc__notebook_list (filter titles case-insensitively for the topic term).
Phase 4 — Load sources (SEQUENTIAL — critical)
Read references/url-gotchas.md for the domain blocklist and URL-cleaning rules before calling any add tool.
Order of source types to add (each as a separate, sequential call — never in parallel):
1. User's seed URLs (YouTube, blog posts, etc.) 2. Official repo / website / docs 3. Hacker News discussion(s) 4. Reddit thread URL(s) — keep the trailing / that Reddit prefers 5. GitHub Discussions / Issues URLs with relevant community content 6. Third-party reviews / comparative discussions 7. After all URL sources: add the research synthesis and community content as text sources via mcp__notebooklm-rpc__notebook_add_text
DO NOT attempt to add:
medium.com/*— always failsquora.com/*— always fails (as of 2026-04-21; see url-gotchas.md)linkedin.com/*— typically fails (auth gates)
If a domain is uncertain, probe with WebFetch first — if that returns bot-detection content, assume NotebookLM will fail too and capture as text instead.
If adding an llms.txt URL, strip any trailing .md before the call (e.g., foo.com/llms.txt, not foo.com/llms.txt.md).
Sequential sample pattern:
# For each url in ordered_list:
mcp__notebooklm-rpc__notebook_add_url(notebook_id=NB, url=url)
# wait for success, then nextPhase 5 — Generate full Studio (requires user approval)
Every Studio tool takes confirm=True. The MCP server explicitly states user approval is required before setting it. Present the plan to the user, get approval, then dispatch.
Read references/studio-quirks.md for sync vs async classification and known API quirks.
Recommended order (async-first minimizes total wall-clock):
1. audio_overview_create — async, ~60s+ 2. video_overview_create — async, several minutes 3. infographic_create — async, several minutes 4. slide_deck_create — async, several minutes 5. mind_map_create — synchronous 6. report_create(format="Briefing Doc") — synchronous 7. report_create(format="Study Guide") — synchronous 8. flashcards_create — synchronous 9. quiz_create(question_count=10) — synchronous (note: classified as type: flashcards in studio_status) 10. data_table_create(description=...) — synchronous
For each async artifact, pass a focus_prompt tailored to the topic — see references/mcp-tool-map.md for recommended focus prompts per tool.
After dispatching, poll once via mcp__notebooklm-rpc__studio_status after ~45s, then again after 2–3 minutes. Async media can take 5–10 minutes to render.
Phase 6 — Curate chat prompts
Add a text source containing 9 NotebookLM chat prompts adapted to the topic. Base templates live in references/prompt-library.md — they come from two public articles (XDA Developers, AI Fire) and are pre-mapped to structural goals:
1. Five Essential Questions (study) 2. Find the Interesting Bits (insight mining) 3. Quiz Show (gamified review) 4. Content Analyst Report (repurposing) 5. Community → Action Plan (roadmap synthesis) 6. SEO Outline (competitive content) 7. 360° Feedback on Marketing (voice-of-multi-persona critique) 8. Study Guide Kit (onboarding curriculum) 9. Conference Talk Script (narrative pitch)
Replace the topic-specific placeholders in each template with concrete references from the research (actors, quotes, key architectural facts). Save to both:
- A local markdown file under
MEMORY/WORK/<slug>/prompts.mdfor reuse - A text source inside the notebook via
mcp__notebooklm-rpc__notebook_add_texttitled"9 Curated NotebookLM Prompts for {topic}"
Phase 7 — Verify
mcp__notebooklm-rpc__notebook_get(notebook_id=NB)
mcp__notebooklm-rpc__studio_status(notebook_id=NB)Confirm:
- Notebook title matches
{topic} :: docs - Source count matches expected (seed URLs + forum URLs + 2 text research sources + 1 prompts text source)
- Studio artifacts completed or still rendering (video/infographic/slide deck commonly still rendering at verification time — that's fine)
- No duplicate notebook was created
Report back to the user with:
- Notebook URL (
notebooklm.google.com/notebook/{id}) - Table of studio artifacts with status
- Pointer to the 9 curated prompts
Tools & resources included
scripts/add_urls_sequential.py— wraps the sequential-add pattern with the domain blocklist built inscripts/build_full_studio.py— dispatches all 10 Studio artifacts in the correct async-first order (prints the MCP call plan; actual MCP invocation happens from Claude's tool layer)scripts/adapt_prompts.py— takes a topic facts dict and emits the 9 prompts with placeholders filledreferences/url-gotchas.md— domain blocklist + URL-cleaning rulesreferences/studio-quirks.md— sync vs async, quiz classification, confirm guardreferences/prompt-library.md— 9 base prompts with source attribution (XDA + AI Fire)references/mcp-tool-map.md— which MCP tool per phase + recommended focus promptsassets/research_synthesis_template.md— 9-section research doc scaffoldassets/community_content_template.md— forum/community dossier scaffoldassets/workflow_checklist.md— phase-by-phase checklist to copy into a work PRDsamples/cmux_docs_walkthrough.md— worked example from the original session
When NOT to use this skill
- User wants to modify or dedupe an existing notebook — use
notebooklm-skillor direct MCP calls - User just wants to LIST notebooks or describe one — use the MCP tools directly
- User wants to add a single source to an existing notebook — direct MCP call is fine, no orchestration needed
- The task has no "build a research notebook" shape (e.g., "convert this PDF to audio") — use
notebooklm-skill
References to read during execution
| When | Read |
|---|---|
| Before Phase 4 (URL adds) | references/url-gotchas.md |
| Before Phase 5 (Studio) | references/studio-quirks.md, references/mcp-tool-map.md |
| Before Phase 6 (Prompts) | references/prompt-library.md |
| If stuck on a tool choice | references/mcp-tool-map.md |
Anti-patterns (learned from real runs)
- Parallel URL adds → cascade fail. Always sequential.
- Adding Medium or Quora URLs → silently fail. Scrape content, add as text.
- Treating Studio like a single batch → confirm guard will block. Each tool needs its own
confirm=True. - Polling `studio_status` immediately → async artifacts show
in_progress; wait 45s minimum. - Checking `type` field to distinguish quiz from flashcards → both classify as flashcards post-generation. Use the artifact title.
- Forgetting to save the `notebook_id` → costs a redundant
notebook_listcall to recover it.
---
Gotchas
- Web research phase truncates at ~50 URLs — large topics need batching and manual aggregation; the truncation is silent.
- Sequential source upload preserves order; parallel upload doesn't — workflows that use
&andwaitin bash get random ordering and unstable citations. - Source quotas reset at midnight Pacific — a script that hits the daily limit at 23:55 PT silently waits 5 minutes; one running at noon waits 12 hours.
- Full-studio generation: audio/video/slides/quiz/flashcards/etc. run in parallel after upload — if upload fails midway, the partial set still generates without error; verify all sources before generating.
- Notebook ID vs notebook title: the title is mutable; the ID isn't. Scripts that look up by title break on rename.
{TOPIC} Community Discussion: Reddit, Hacker News, GitHub, Discord, Quora
Subject: brief one-paragraph identity of {TOPIC}, including any name collisions to disambiguate.
Traction: one paragraph of quantitative signal — stars, forks, issue count, HN points, notable endorsements.
---
SOURCE 1: Hacker News — [Submission title]
URL: https://news.ycombinator.com/item?id=... Submitted: [date] by [user] | [X] points | [Y] comments
Author pitch (verbatim): "..."
Notable community comments:
- @user1: "verbatim quote"
- @user2: "verbatim quote"
- @user3 (critical): "verbatim quote"
Sentiment: [POSITIVE / MIXED / NEGATIVE] — [one-line rationale]
---
SOURCE 2: Reddit r/[subreddit] — [Thread title]
URL: https://reddit.com/r/[subreddit]/comments/...
- @user: "verbatim quote"
- @user (critical): "verbatim quote"
Sentiment: [...]
---
SOURCE 3: GitHub Discussion #[N] — [Title]
URL: https://github.com/org/repo/discussions/N
OP: "verbatim quote" Key reply (@user): "verbatim quote"
Sentiment: [...]
---
SOURCE N: X / Twitter
Notable posts with attribution.
---
SOURCE N+1: YouTube
Relevant videos with URLs.
---
SOURCE N+2: Discord
Discord content isn't publicly scrapeable by NotebookLM and should be captured here as text. If the Discord server is accessible to you, paste excerpts with [Discord: channel] attribution. Otherwise, note the invite URL and substitute equivalent content from GitHub Discussions.
Discord invite: [url if public]
---
SOURCE N+3: Quora
Status: [Usually: no threads found specifically discuss {TOPIC} — most technical audiences do not use Quora. Document the absence.]
If any threads exist, list URLs and verbatim question/answer excerpts.
---
OVERALL COMMUNITY SENTIMENT SUMMARY
Positive themes: 1. 2. 3.
Mixed/critical themes: 1. 2. 3.
Sentiment ratio across all sources: ~X% positive, ~Y% constructively critical, ~Z% hard negative.
{TOPIC}: Deep Research Synthesis
1. Overview
What {TOPIC} is, who built it, when it launched, positioning. Include the verbatim tagline from the official site and README. Capture the origin story in the creators' own words if quotable.
2. Architecture
- Core runtime/platform
- Key technical dependencies
- Rendering / execution model
- Configuration surface (what files it reads, how it extends)
- Persistence model (what survives restart)
3. Key Features
List and explain distinguishing features — each with at least one concrete example from the sources.
4. Integrations / Ecosystem
- Adjacent tools it works with
- Plugins, extensions, MCPs, skills built on it
- Import/export capabilities
5. Comparison
{TOPIC} vs alternatives. Use a table where possible. Explicitly call out which layer {TOPIC} operates at (e.g., substrate vs orchestrator vs review tool).
6. Installation & Usage
- Install steps (verbatim commands)
- Core commands and basic workflows
- Default shortcuts / keybindings
7. Traction & Reception
- GitHub stars over time
- HN / Reddit / social signal
- Notable endorsements (verbatim quotes with attribution)
- Geographic / community reach
- License
8. Limitations
Explicit, known trade-offs. Prefer maintainer statements over speculation.
9. Official URLs
Exhaustive list — every canonical URL you find:
Code & repo: -
Websites & docs: -
Creators & company: -
Community: -
Press / third-party: -
llms.txt: (if it exists — strip any trailing .md before adding to NotebookLM)
notebooklm-create — Workflow Checklist
Copy this checklist into a PRD.md under MEMORY/WORK/<slug>/ at the start of a run. Tick items as you complete them.
Phase 1 — Capture intent
- [ ] Topic name confirmed:
_______________ - [ ] Seed URLs collected (user-provided):
- [ ] URL 1:
_______________ - [ ] URL 2:
_______________ - [ ] Forum coverage scope: Reddit ☐ HN ☐ GitHub Discussions ☐ Discord ☐ Quora ☐
- [ ] Notebook title decided:
____ :: docs - [ ] Studio scope: full (all 10) ☐ selective ☐ (list: ____)
- [ ] Ambiguity check: multiple projects share this name? ☐ yes ☐ no
- If yes, disambiguation strategy: ____
Phase 2 — Deep research
- [ ] Seed URLs fetched (WebFetch) to anchor disambiguation
- [ ] Canonical repo URL identified
- [ ] Official docs / website URL identified
- [ ] llms.txt URL located (or confirmed absent)
- [ ] Research synthesis agent dispatched → artifact saved
- [ ] Community content agent dispatched → artifact saved
Phase 3 — Create notebook
- [ ]
notebook_listrun — no duplicate title exists - [ ]
notebook_create(title="____ :: docs")called - [ ] Notebook ID captured:
_______________
Phase 4 — Load sources (sequential)
- [ ]
references/url-gotchas.mdconsulted - [ ] URLs filtered: no Medium, no Quora, no LinkedIn
- [ ] Any
llms.txtURLs have.mdstripped - [ ] Sequential URL adds executed — one at a time
- [ ] Research synthesis added as text source
- [ ] Community content added as text source
Phase 5 — Studio (requires user approval)
- [ ] User approval obtained for full studio dispatch
- [ ]
references/studio-quirks.mdconsulted - [ ] Async media dispatched first:
- [ ] audio_overview_create
- [ ] video_overview_create
- [ ] infographic_create
- [ ] slide_deck_create
- [ ] Synchronous dispatched second:
- [ ] mind_map_create
- [ ] report_create (Briefing Doc)
- [ ] report_create (Study Guide)
- [ ] flashcards_create
- [ ] quiz_create
- [ ] data_table_create
- [ ] studio_status polled after 45s
- [ ] studio_status polled again after 2–3 min
Phase 6 — Curate prompts
- [ ] 9 base prompts adapted to topic (via scripts/adapt_prompts.py)
- [ ] Prompts saved to
MEMORY/WORK/<slug>/prompts.md - [ ] Prompts added to notebook via
notebook_add_text
Phase 7 — Verify
- [ ]
notebook_get(notebook_id=NB)called - [ ] Source count matches expected
- [ ] No duplicate placeholder sources from failed URL adds
- [ ] Studio artifacts: N completed, M in_progress
- [ ] Reported notebook URL to user
- [ ] Reported studio artifact status to user
- [ ] Memory entries updated if new gotchas discovered
{
"skill_name": "notebooklm-create",
"evals": [
{
"id": 1,
"name": "devtool-topic-build",
"prompt": "Please build me a NotebookLM notebook called 'bun :: docs' for the Bun JavaScript runtime. Pull in the official bun.sh site, the GitHub repo at oven-sh/bun, the Show HN thread, and at least two Reddit threads from r/javascript or r/node. Also grab community discussion from GitHub Discussions. Then generate the full studio (audio overview, video, mind map, a Briefing Doc and a Study Guide, flashcards, a 10-question quiz, an infographic, a slide deck, and a comparison table of Bun vs Node vs Deno). Finally add the 9 curated NotebookLM prompts as a text source, adapted for Bun. This is for my team's eval of whether to migrate our build tooling off Node.",
"expected_output": "A new NotebookLM notebook titled 'bun :: docs' with ~11+ URL sources (Bun site, GitHub repo, HN, ≥2 Reddit, ≥1 GitHub Discussions), 2 text research sources (synthesis + community), 1 text prompts source, and 10 studio artifacts dispatched with confirm=true (some completed, async ones rendering). No Medium URLs added, URL adds executed sequentially, quiz/flashcards/data-table all created. Final report includes notebook URL and studio status.",
"files": []
},
{
"id": 2,
"name": "ambiguous-topic-disambiguation",
"prompt": "Hey I need a research notebook on 'cline' — it's that AI coding thing. Can you build the full NotebookLM studio for it with all the sources you can find? I have a blog post I want included: https://cline.bot/blog",
"expected_output": "Skill disambiguates between possible 'cline' projects (cline.bot AI coding assistant VS other projects named cline) using the user's seed URL as anchor. Creates notebook 'cline :: docs', loads the user's seed URL plus discovered official repo, docs, HN threads, Reddit discussions. Adds research synthesis + community content as text. Generates all 10 studio artifacts with confirm=true and user-approval check. Final report lists what 'cline' was disambiguated to, notebook URL, source count, studio status.",
"files": []
},
{
"id": 3,
"name": "medium-quora-blocklist-respect",
"prompt": "Build a NotebookLM notebook on the topic 'Astro framework' with sources from everywhere — Medium, Quora, Reddit, GitHub, Hacker News, the official astro.build site, and a YouTube intro video. Include a full studio and curated prompts.",
"expected_output": "Notebook 'Astro framework :: docs' (or similar) created. Reddit, GitHub, HN, official site, YouTube all added as URL sources sequentially. Medium URLs are NOT added as URLs — skill scrapes content via WebFetch and includes in the community content text source instead. Quora either produces no results (noted in community content) or is similarly handled as text. Full studio dispatched with confirm=true. Skill explicitly reports which domains were routed through text vs URL and why.",
"files": []
}
]
}
MCP Tool Map — notebooklm-rpc
Which MCP tool to call at each workflow phase. All tools live under the mcp__notebooklm-rpc__ prefix.
Phase 1 — Capture intent
_No MCP calls. Conversation only._
Phase 2 — Deep research
_No notebooklm-rpc calls. Use WebFetch, WebSearch, and Agent (subagents) for research._
Phase 3 — Create notebook
| Tool | Purpose | Required params |
|---|---|---|
notebook_list | Pre-flight: check for duplicate title | (none) |
notebook_create | Create the notebook | title |
Capture notebook.id from the notebook_create response.
Phase 4 — Load sources (sequential)
| Tool | Purpose | Required params |
|---|---|---|
notebook_add_url | Add a web URL (article, YouTube, GitHub, HN, Reddit) | notebook_id, url |
notebook_add_text | Add pasted text (research synthesis, community content, Discord captures) | notebook_id, text, optional title |
notebook_add_drive | Add a Google Drive document | notebook_id, file_id |
source_delete | Remove a failed/broken source | notebook_id, source_id |
Order sensitivity: one-at-a-time. Wait for success response before next call.
Phase 5 — Studio generation
All require confirm: true AND user approval.
Async media (dispatch FIRST — longer render time)
| Tool | Key options | Recommended focus prompt shape |
|---|---|---|
audio_overview_create | `format: deep_dive\ | brief\ |
video_overview_create | `format: explainer\ | brief, visual_style: auto_select\ |
infographic_create | `orientation: landscape\ | portrait\ |
slide_deck_create | `format: detailed_deck\ | presenter_slides, length: short\ |
Synchronous / fast-async (dispatch SECOND)
| Tool | Key options | Notes |
|---|---|---|
mind_map_create | title | Returns fully rendered mind map in response |
report_create | `report_format: "Briefing Doc"\ | "Study Guide"\ |
flashcards_create | `difficulty: easy\ | medium\ |
quiz_create | question_count (default 2 — override to 10), difficulty | Will be classified as type: flashcards post-generation — use title to identify |
data_table_create | description (REQUIRED — describe columns & rows) | Good for comparison tables; specify columns explicitly |
Polling & management
| Tool | Purpose |
|---|---|
studio_status | Poll artifact generation status |
studio_delete | Remove a failed/poor artifact |
Phase 6 — Curate prompts
| Tool | Purpose |
|---|---|
notebook_add_text | Add the 9 curated prompts as a text source titled "9 Curated NotebookLM Prompts for {topic}" |
Phase 7 — Verify
| Tool | Purpose |
|---|---|
notebook_get | Retrieve full notebook metadata + source list |
notebook_describe | AI-generated notebook summary + suggested topics |
studio_status | Final check on artifact completion |
Auth refresh
If any tool returns an auth error: do not save_auth_tokens manually. Run notebooklm-mcp-auth in the terminal (Bash tool) — it handles auth end-to-end.
Quick reference — full pipeline call order
1. notebook_list # dedup check
2. notebook_create → capture notebook_id
3. notebook_add_url × N (SEQUENTIAL, skip Medium/Quora)
4. notebook_add_text × 2 (research synthesis + community content)
5. audio_overview_create(confirm=true, focus_prompt=...)
6. video_overview_create(confirm=true, focus_prompt=...)
7. infographic_create(confirm=true, focus_prompt=...)
8. slide_deck_create(confirm=true, focus_prompt=...)
9. mind_map_create(confirm=true)
10. report_create(report_format="Briefing Doc", confirm=true)
11. report_create(report_format="Study Guide", confirm=true)
12. flashcards_create(confirm=true)
13. quiz_create(question_count=10, confirm=true)
14. data_table_create(description=..., confirm=true)
15. notebook_add_text (curated prompts)
16. studio_status # poll 45s later
17. notebook_get # final verifyPrompt Library — 9 curated NotebookLM chat prompts
Base templates for the 9 prompts this skill adds to every topic notebook. Three from XDA Developers, six from AI Fire. Adapted to be topic-agnostic — replace {TOPIC}, {CENTRAL_THEME}, {KEY_FACTS}, {KEY_ACTORS}, etc. with the topic-specific facts from Phase 2 research.
Attribution (preserve when adapting):
- Prompts 1–3: Alex Blake, XDA Developers, "3 prompts I use to get the most out of NotebookLM" — https://www.xda-developers.com/prompts-i-use-to-get-most-out-of-noteboooklm/
- Prompts 4–9: AI Fire, "6 NotebookLM Prompts That Do Your Hard Work For You" — https://www.aifire.co/p/6-notebooklm-prompts-that-do-your-hard-work-for-you
---
Prompt 1 — Five Essential Questions (XDA #1)
1.) Analyze all sources in this notebook about {TOPIC} and generate 5 essential questions that, when answered, capture the main points and core meaning of the material.
2.) When formulating your questions:
a. Address the central theme — {CENTRAL_THEME}
b. Identify key supporting ideas ({KEY_CONCEPTS})
c. Highlight important facts or evidence ({KEY_FACTS})
d. Reveal the creators' purpose or perspective ({ORIGIN_STORY})
e. Explore significant implications — {IMPLICATIONS}
3.) Answer all 5 questions one-by-one in detail, citing specific sources.Prompt 2 — Find the Interesting Bits (XDA #2)
What are the most surprising or interesting pieces of information or narratives in these sources about {TOPIC}? Focus on:
- Counter-intuitive design decisions
- Verbatim quotes from the creators, notable endorsers, or commenters
- Unexpected community dynamics
- Technical choices that differ from conventional wisdom
- Quotable lines that capture {TOPIC}'s identity
Include at least 8 key quotes with attribution.Prompt 3 — Quiz Show (XDA #3)
You're hosting a fun quiz show with two hosts. The first host quizzes the second on concepts from this notebook about {TOPIC}. Include a mix of multiple choice and true/false questions covering: {KEY_CONCEPTS_LIST}.
Occasionally, the second host should get an answer wrong, and the first host should step in to explain the correct answer clearly, quoting sources. At the end, share the final score and a brief summary of how the second host did.Prompt 4 — Content Analyst Report (AI Fire #1)
Act as a content strategy expert. Based on the sources in this notebook about {TOPIC}, create a full analysis with:
**1. Quick Summary:** 3 bullet points summarizing the most important ideas.
**2. Deep Analysis:**
- Target Audience: Who is {TOPIC} for? Be specific.
- Main Arguments: List the 3 main arguments {TOPIC} makes.
- Best Quotes: 3 powerful sentences or facts from the sources, with attribution.
**3. Creative Ideas:**
- Alternative Taglines: 2 other taglines (one curiosity-driven, one benefit-driven).
- Social Media: A short LinkedIn post and a tweet/X post, with hashtags.Prompt 5 — Community → Action Plan (AI Fire #2)
Act as a professional project secretary. Based on the community discussion sources in this notebook (forums, issues, threads), treat the collective conversation as a product meeting. Create a markdown summary with:
**1. Goal of the Meeting:** One sentence — what is the community collectively asking {TOPIC} to solve next?
**2. Main Voices:** Key speakers with handles/attribution.
**3. Summary of Main Discussions:** Main topics across threads.
**4. Important Decisions Made:** Concrete commitments maintainers announced.
**5. To-Do List:** Table with Task | Likely Owner | Priority for community-requested improvements.
**6. Unresolved Issues:** Open questions.Prompt 6 — SEO Outline (AI Fire #3)
Act as an SEO expert and content editor. Based on ALL sources in this notebook about {TOPIC}:
**Part A: Competitor & Landscape Analysis**
1. Search Intent: When people search {EXPECTED_QUERIES}, what do they actually want?
2. Common Topics: 5 sub-topics every existing article/thread covers.
3. Content Gaps: Important sub-topics that are under-covered.
**Part B: Outline for a New Article**
1. 3 H1 suggestions (curiosity, benefit, authority).
2. Full H2/H3 structure including a gap-filling section from Part A.
3. Writer notes under each heading with specific facts/quotes/data from the notebook.Prompt 7 — 360° Feedback on Marketing (AI Fire #4)
Create a "360-Degree Feedback Report" for the {TOPIC} README/homepage/marketing content captured in this notebook. Include:
**Section 1: Strict Editor's View**
- 3 longest or weakest sentences with shorter rewrites.
- Weakest claim — what needs more proof?
**Section 2: New Reader's View**
- Confusing terms/concepts for someone new to the domain.
- Most boring section. Why?
**Section 3: Marketing Expert's View**
- Is the opening hook strong enough? If not, rewrite.
- Stronger call-to-action for the end.Prompt 8 — Study Guide Kit (AI Fire #5)
Act as a dedicated tutor for someone onboarding to {TOPIC}. Based on all sources, create a "Complete Study Guide Kit":
**1. Summary of Key Concepts:**
The 5 most important ideas in {TOPIC}, each explained simply with a specific example from the sources.
**2. Terminology Flashcards:**
12 important terms with short definitions. Format: "Term: Definition."
**3. Practice Questions:**
- 5 essay-style questions covering architecture, philosophy, comparison, limitations, extensibility.
- 10-question multiple-choice quiz (A, B, C, D).
**4. Answer Key:** Answers for the 10 MCQs with one-sentence rationale each, citing sources.Prompt 9 — Conference Talk Script (AI Fire #6, adapted)
Act as a developer/product-advocate coach. I'm preparing a 15-minute conference talk about {TOPIC}, positioned as a maintainer or power user. Based on all sources, create a "Talk Prep Plan":
**Part 1: Audience Fit Analysis**
3 biggest matches between {TOPIC}'s design choices and real pains evidenced in the community sources.
**Part 2: Talk Script**
- 3–4 sentence opening hook naming the specific pain and pivoting to the {TOPIC} answer.
- 3 "story moments" from the sources in STAR format (Situation, Task, Action, Result).
**Part 3: Audience Q&A Prep**
3 smart questions the audience will likely ask, with grounded answers using direct source quotes.---
Adaptation checklist
When adapting for a specific topic, replace:
{TOPIC}— the project/subject name{CENTRAL_THEME}— one-line identity statement{KEY_CONCEPTS}— 4–6 technical sub-concepts{KEY_FACTS}— 3–5 verifiable data points (version, launch date, stars, funding){ORIGIN_STORY}— who built it and why (one sentence){IMPLICATIONS}— what layering/positioning matters{KEY_CONCEPTS_LIST}— comma-separated list for Quiz Show{EXPECTED_QUERIES}— 2–3 likely search queries
Replace every placeholder. Generic prompts produce generic outputs.
Studio Quirks — NotebookLM artifact generation
Quirks observed when calling the notebooklm-rpc Studio tools. Consult before Phase 5.
The confirm guard
Every Studio creation tool takes confirm: bool (default false). Calling with confirm=false returns an error.
Per the notebooklm-rpc MCP server instructions: Tools with confirm param require user approval before setting confirm=True.
Workflow: 1. Present the studio plan to the user (list of artifacts, options, focus prompts) 2. Get explicit approval (or treat a clear user request like "build the full studio" as scoped approval) 3. Then dispatch each tool with confirm=true
Do NOT hide this guard from the user. If in doubt, ask.
Sync vs async
| Artifact | Mode | Typical time |
|---|---|---|
mind_map_create | Synchronous — returns full mind map in the create response | <5s |
report_create (all formats) | Async | 30–90s |
flashcards_create | Async | 30–90s |
quiz_create | Async | 30–90s |
data_table_create | Async | 30–90s |
audio_overview_create | Async | 1–3 min |
infographic_create | Async | 2–5 min |
slide_deck_create | Async | 2–5 min |
video_overview_create | Async | 3–10 min |
Implication: Dispatch the longest async ones FIRST so they render in parallel with the shorter ones.
Quiz classified as flashcards
When you call quiz_create, the synchronous response correctly reports type: "quiz". But after generation completes, studio_status shows the quiz artifact with type: "flashcards" and a flashcard_count field.
Do not rely on the `type` field to distinguish quiz from flashcards post-generation. Use the artifact title (e.g., "Quiz cmux") or the original artifact_id you captured at creation.
Counts are approximations
Requested question_count: 10 → NotebookLM commonly returns 9. Flashcards behave similarly. Budget ±1–2 from the requested count.
Focus prompts
audio_overview_create, video_overview_create, infographic_create, slide_deck_create, and the "Create Your Own" report format accept a focus_prompt parameter. Use it. A targeted focus prompt dramatically improves grounding vs the default "summarize everything" behavior.
Good focus prompts:
- Name the topic explicitly
- List 3–5 specific sub-themes to emphasize
- Mention key actors, quotes, or facts from the sources
- Indicate the audience (e.g., "for developers evaluating X")
Bad focus prompts:
- Generic ("make it good")
- Longer than ~3 sentences (NotebookLM truncates)
- Instructions about structure the tool already knows (e.g., telling an audio overview to "have two hosts")
Polling
After dispatch, call mcp__notebooklm-rpc__studio_status(notebook_id=NB) after ~45s. Most synchronous artifacts will be complete. Async media (audio/video/infographic/slide deck) may still show in_progress — poll again after 2–3 minutes, or tell the user they'll finish rendering in the NotebookLM UI.
Audio overview formats
deep_dive— two-host podcast, default, most engagingbrief— shorter summary formatcritique— adversarial / analytical framingdebate— two opposing positions
deep_dive is the right default. Pick brief only if the user explicitly wants ≤5 min.
Video overview visual styles
Accepted values: auto_select | classic | whiteboard | kawaii | anime | watercolor | retro_print | heritage | paper_craft.
Default to auto_select; NotebookLM picks based on content. Override only if the user specifies a style.
Report formats
"Briefing Doc"— executive summary style"Study Guide"— student-facing, with study questions"Blog Post"— narrative, shareable"Create Your Own"— requirescustom_prompt
For a typical topic notebook, generating both Briefing Doc and Study Guide covers the two dominant consumption modes (skim vs learn).
Recovery
If an artifact fails or produces poor output, delete and regenerate:
mcp__notebooklm-rpc__studio_delete(notebook_id=NB, artifact_id=AID)
# then re-call the create toolURL Gotchas — NotebookLM source adds
Rules learned from real notebook builds. Consult before calling mcp__notebooklm-rpc__notebook_add_url.
Domain blocklist (known-failing)
NotebookLM's URL fetcher silently fails — or registers a broken placeholder source — on these domains. Scrape content with WebFetch/WebSearch, then add as text via `notebook_add_text` instead.
| Domain | Failure mode | Verified |
|---|---|---|
medium.com/* | Silent fail; common user frustration | Recurring in NotebookLM community discussion |
*.medium.com | Same as above | Same |
quora.com/* | Returns status: error, Failed to add URL source; bot detection | 2026-04-21 |
linkedin.com/* | Auth-gated; typically fails | Reported pattern |
If a Quora or Medium URL add fails, NotebookLM may still create a broken placeholder source in the notebook — visible as the raw URL string with no title. Remove these via source_delete if they appear.
Sequential-only rule
notebook_add_url cascade-fails when called in parallel. The second call while the first is pending will frequently error or produce an incomplete source.
Always add URLs sequentially — wait for each call's success response before issuing the next. Parallel-tool-call is the wrong pattern here.
Same rule applies to notebook_add_text if you're adding many text sources back-to-back, though text adds are more tolerant.
URL cleaning
llms.txt
Strip any trailing .md from llms.txt URLs before adding:
- ✅
https://example.com/llms.txt - ❌
https://example.com/llms.txt.md
NotebookLM fetches the URL literally; .md suffix produces a 404 or wrong content type.
Reddit is tolerant of both forms, but prefer the old.reddit.com redirect target or the canonical reddit.com form with the trailing slug. Example:
- ✅
https://reddit.com/r/ClaudeCode/comments/1r9g45u/i_made_a_ghosttybased_terminal_with_vertical_tabs/ - ❌
https://www.reddit.com/r/ClaudeCode/comments/1r9g45u/(works but loses the slug — title may be less informative)
GitHub
Direct links to /blob/main/README.md work. Prefer the root repo URL (e.g., github.com/org/repo) for the best auto-title; NotebookLM fetches the README automatically.
GitHub Discussions (/discussions/NNN) and Issues (/issues/NNN) load fine as URLs.
Hacker News
news.ycombinator.com/item?id=NNNNN works reliably. Include the top-level discussion, not individual comment permalinks.
YouTube
Full watch URLs work: youtube.com/watch?v=ID or youtu.be/ID. Short URLs are fine.
When in doubt, probe first
If the domain isn't on this list but you're unsure:
1. Run WebFetch on the URL with a trivial prompt 2. If WebFetch returns bot-detection content, auth-wall language, or empty body → NotebookLM will likely fail too. Scrape content and add as text. 3. If WebFetch returns real content → notebook_add_url usually succeeds.
Recovery if a bad URL was added
mcp__notebooklm-rpc__source_delete(notebook_id=NB, source_id=<bad_source_id>)Source IDs are in the error-response metadata or visible via notebook_get.
Sample: cmux :: docs End-to-End Walkthrough
Real worked example of this skill applied to the topic cmux (manaflow-ai) — the native macOS terminal for parallel AI coding agents. Built on 2026-04-21. All IDs and URLs are verifiable.
Inputs from the user
"create a entirely cmux :: docs notebooklm, go to the web and make a deepresearch about that and add as source for this notebooklm- https://www.youtube.com/watch?v=8oLP8oxqtOE
- https://vibecoding.app/blog/cmux-review
go to forum likediscord,quora"
Phase 1 — Intent
- Topic: cmux — ambiguous (multiple projects share the name); anchor on user URLs
- Seed URLs: YouTube video + vibecoding blog
- Forums: Reddit, Discord, Quora explicitly named
- Title:
cmux :: docs(matches existing{topic} :: docsconvention) - Studio: deferred to a second user turn ("entirely studio")
- Disambiguation: WebFetch on the two seed URLs confirmed manaflow-ai/cmux, not craigsc/cmux or coder/cmux
Phase 2 — Deep Research
Two parallel subagents dispatched:
Synthesis agent produced research_synthesis.md (12.8 KB, 9 sections per template). Key findings:
- cmux = native Swift/AppKit macOS terminal, built on libghostty
- Founders: Austin Wang + Lawrence Chen (Manaflow, YC S24)
- Launched Feb 19, 2026 — hit #2 on HN
- ~15k stars by April 2026
- Mitchell Hashimoto (Ghostty creator) publicly endorsed it
- Positioning: "primitive, not a solution"
- Layering: board → orchestrator → review → terminal (cmux) → agent
Community agent produced community_content.md (14.9 KB). Key findings:
- Hacker News Show HN (
id=47079718) — 198 points, 77 comments, strongly positive - 3 active Reddit threads (r/ClaudeCode, r/tmux, r/SaasDevelopers)
- GitHub Discussion #681 (session persistence gap) — most cited critical feedback
- Quora: no cmux threads exist — confirmed absent
- Discord server exists (
discord.gg/xsgFEVrWCZ) — content captured indirectly from GitHub Discussions
Phase 3 — Create notebook
mcp__notebooklm-rpc__notebook_create(title="cmux :: docs")
→ notebook_id = e0ed6d5f-abdc-4957-9ccd-fd988f88970fPre-flight notebook_list confirmed no existing cmux-named notebooks.
Phase 4 — Sources (sequential)
11 URL sources added one at a time:
1. youtube.com/watch?v=8oLP8oxqtOE ✅ 2. vibecoding.app/blog/cmux-review ✅ 3. github.com/manaflow-ai/cmux ✅ 4. www.cmux.dev/ ✅ 5. cmux.com/docs/getting-started ✅ 6. news.ycombinator.com/item?id=47079718 ✅ 7. reddit.com/r/ClaudeCode/comments/1r9g45u/... ✅ 8. reddit.com/r/tmux/comments/1s2rnln/... ✅ 9. reddit.com/r/SaasDevelopers/comments/1sfecai/... ✅ 10. github.com/ComposioHQ/agent-orchestrator/discussions/526 ✅ 11. github.com/manaflow-ai/cmux/discussions/681 ✅
Failed adds (expected, per url-gotchas.md):
quora.com/topic/Terminal-Emulators❌ — NotebookLM returnedFailed to add URL sourcequora.com/What-are-some-of-the-best-free-AI-agents-9❌ — same
Recovery: Captured Quora absence in the community content text source instead. Added a new feedback memory (feedback_quora_urls_fail.md) after observing the failure.
2 text sources added:
cmux: Deep Research Synthesis(source id4074bf68)cmux Community (Reddit, HN, GitHub, Discord, Quora)(source id57e0fc1e)
Final count: 13 usable sources.
Phase 5 — Studio (second user turn)
User explicitly requested "entirely studio" — treated as scoped approval.
Dispatched in async-first order, all with confirm=true:
| # | Tool | Result |
|---|---|---|
| 1 | audio_overview_create(format=deep_dive, focus_prompt=...) | ✅ "cmux creates mission control for agents" |
| 2 | video_overview_create(format=explainer) | 🕐 rendering |
| 3 | mind_map_create | ✅ "Cmux: O Terminal Nativo para Orquestração de Agentes IA" |
| 4 | report_create(Briefing Doc) | ✅ "cmux: The Terminal Substrate for AI Agent Multitasking" |
| 5 | report_create(Study Guide) | ✅ "cmux: A Comprehensive Study Guide for the AI-Native Terminal" |
| 6 | flashcards_create | ✅ 9 cards |
| 7 | quiz_create(question_count=10) | ✅ "Quiz cmux" — 9 questions (NOTE: classified as type: flashcards in studio_status) |
| 8 | infographic_create(orientation=portrait, detail_level=detailed) | 🕐 rendering |
| 9 | slide_deck_create(format=detailed_deck) | 🕐 rendering |
| 10 | data_table_create(description="Comparison of AI-Agent Terminals and Orchestrators") | ✅ |
studio_status polled at 45s (6 completed) and again at 2 min (7 completed). Video/infographic/slide deck left rendering — reported to user with expected completion time.
Phase 6 — Curate prompts
adapt_prompts.py with the following facts:
{
"topic": "cmux",
"central_theme": "native macOS terminal for AI coding agents built on libghostty",
"key_concepts": "libghostty rendering, OSC notification protocols, claude-teams, Ghostty config reuse",
"key_facts": "YC S24 backed, launched Feb 19 2026, ~15k stars, #2 on Hacker News",
"origin_story": "Austin Wang and Lawrence Chen built it after frustration with generic 'Claude is waiting for your input' notifications",
"implications": "cmux is a terminal substrate, not an orchestrator",
"key_concepts_list": "libghostty, OSC 9/99/777, claude-teams, Ghostty config, vertical tabs, notification rings, remote workspaces, AGPL",
"expected_queries": "cmux, terminal for Claude Code, parallel AI agents macOS"
}Emitted prompts.md, saved locally, then added to notebook as text source 4dfd83a6 titled "9 Curated NotebookLM Prompts for cmux".
Phase 7 — Verify
notebook_get(notebook_id=e0ed6d5f-...) returned:
- Title:
cmux :: docs✅ - 14 sources total (11 URL + 3 text: research, community, prompts)
- 2 Quora placeholder errors (noted, left in place — harmless)
Final reported to user:
- Notebook URL: https://notebooklm.google.com/notebook/e0ed6d5f-abdc-4957-9ccd-fd988f88970f
- 7/10 studio artifacts completed at verification time
- 9 curated prompts available as text source for chat use
Lessons captured as memory
New memory entries added during this run:
feedback_quora_urls_fail.md— Quora URLs silently fail like Mediumfeedback_notebooklm_studio_quirks.md— quiz classification quirk, sync vs async pollingproject_cmux_notebook.md— notebook pointer with ID and metadata
These memories now prevent rediscovery in future runs of this skill.
#!/usr/bin/env python3
"""
adapt_prompts.py — fill the 9 base prompt templates with topic-specific facts.
Reads the base templates from references/prompt-library.md (or a JSON facts
file passed in) and emits a ready-to-save markdown document with placeholders
replaced. The emitted document is suitable for:
1. Saving locally under MEMORY/WORK/<slug>/prompts.md
2. Passing as text to mcp__notebooklm-rpc__notebook_add_text
Usage:
python scripts/adapt_prompts.py --facts facts.json
facts.json schema:
{
"topic": "cmux",
"central_theme": "native macOS terminal for AI coding agents",
"key_concepts": "libghostty rendering, OSC notifications, claude-teams",
"key_facts": "YC S24, launched Feb 2026, ~15k stars, #2 on HN",
"origin_story": "Austin Wang and Lawrence Chen built it after frustration with generic 'Claude is waiting' notifications",
"implications": "positions as a terminal substrate, not an orchestrator",
"key_concepts_list": "libghostty, OSC 9/99/777, claude-teams, Ghostty config, vertical tabs, notification rings, remote workspaces, AGPL",
"expected_queries": "cmux, terminal for Claude Code, parallel AI agents macOS"
}
"""
import argparse
import json
import sys
from pathlib import Path
TEMPLATES = {
1: (
"Five Essential Questions (XDA #1)",
"""1.) Analyze all sources in this notebook about {topic} and generate 5 essential questions that, when answered, capture the main points and core meaning of the material.
2.) When formulating your questions:
a. Address the central theme — {central_theme}
b. Identify key supporting ideas ({key_concepts})
c. Highlight important facts or evidence ({key_facts})
d. Reveal the creators' purpose or perspective ({origin_story})
e. Explore significant implications — {implications}
3.) Answer all 5 questions one-by-one in detail, citing specific sources.""",
),
2: (
"Find the Interesting Bits (XDA #2)",
"""What are the most surprising or interesting pieces of information or narratives in these sources about {topic}? Focus on:
- Counter-intuitive design decisions
- Verbatim quotes from the creators, notable endorsers, or commenters
- Unexpected community dynamics
- Technical choices that differ from conventional wisdom
- Quotable lines that capture {topic}'s identity
Include at least 8 key quotes with attribution.""",
),
3: (
"Quiz Show (XDA #3)",
"""You're hosting a fun quiz show with two hosts. The first host quizzes the second on concepts from this notebook about {topic}. Include a mix of multiple choice and true/false questions covering: {key_concepts_list}.
Occasionally, the second host should get an answer wrong, and the first host should step in to explain the correct answer clearly, quoting sources. At the end, share the final score and a brief summary of how the second host did.""",
),
4: (
"Content Analyst Report (AI Fire #1)",
"""Act as a content strategy expert. Based on the sources in this notebook about {topic}, create a full analysis with:
**1. Quick Summary:** 3 bullet points summarizing the most important ideas.
**2. Deep Analysis:**
- Target Audience: Who is {topic} for? Be specific.
- Main Arguments: List the 3 main arguments {topic} makes.
- Best Quotes: 3 powerful sentences or facts from the sources, with attribution.
**3. Creative Ideas:**
- Alternative Taglines: 2 other taglines (one curiosity-driven, one benefit-driven).
- Social Media: A short LinkedIn post and a tweet/X post, with hashtags.""",
),
5: (
"Community → Action Plan (AI Fire #2)",
"""Act as a professional project secretary. Based on the community discussion sources in this notebook (forums, issues, threads), treat the collective conversation as a {topic} product meeting. Create a markdown summary with:
**1. Goal of the Meeting:** One sentence — what is the community collectively asking {topic} to solve next?
**2. Main Voices:** Key speakers with handles/attribution.
**3. Summary of Main Discussions:** Main topics across threads.
**4. Important Decisions Made:** Concrete commitments maintainers announced.
**5. To-Do List:** Table with Task | Likely Owner | Priority for community-requested improvements.
**6. Unresolved Issues:** Open questions.""",
),
6: (
"SEO Outline (AI Fire #3)",
"""Act as an SEO expert and content editor. Based on ALL sources in this notebook about {topic}:
**Part A: Competitor & Landscape Analysis**
1. Search Intent: When people search for {expected_queries}, what do they actually want?
2. Common Topics: 5 sub-topics every existing article/thread covers.
3. Content Gaps: Important sub-topics that are under-covered.
**Part B: Outline for a New Article**
1. 3 H1 suggestions (curiosity, benefit, authority).
2. Full H2/H3 structure including a gap-filling section from Part A.
3. Writer notes under each heading with specific facts/quotes/data from the notebook.""",
),
7: (
"360° Feedback on Marketing (AI Fire #4)",
"""Create a "360-Degree Feedback Report" for the {topic} README/homepage/marketing content captured in this notebook. Include:
**Section 1: Strict Editor's View**
- 3 longest or weakest sentences with shorter rewrites.
- Weakest claim — what needs more proof?
**Section 2: New Reader's View**
- Confusing terms/concepts for someone new to the domain.
- Most boring section. Why?
**Section 3: Marketing Expert's View**
- Is the opening hook strong enough? If not, rewrite.
- Stronger call-to-action for the end.""",
),
8: (
"Study Guide Kit (AI Fire #5)",
"""Act as a dedicated tutor for someone onboarding to {topic}. Based on all sources, create a "Complete Study Guide Kit":
**1. Summary of Key Concepts:**
The 5 most important ideas in {topic}, each explained simply with a specific example from the sources.
**2. Terminology Flashcards:**
12 important terms with short definitions. Format: "Term: Definition."
**3. Practice Questions:**
- 5 essay-style questions covering architecture, philosophy, comparison, limitations, extensibility.
- 10-question multiple-choice quiz (A, B, C, D).
**4. Answer Key:** Answers for the 10 MCQs with one-sentence rationale each, citing sources.""",
),
9: (
"Conference Talk Script (AI Fire #6)",
"""Act as a developer/product-advocate coach. I'm preparing a 15-minute conference talk about {topic}, positioned as a maintainer or power user. Based on all sources, create a "Talk Prep Plan":
**Part 1: Audience Fit Analysis**
3 biggest matches between {topic}'s design choices and real pains evidenced in the community sources.
**Part 2: Talk Script**
- 3–4 sentence opening hook naming the specific pain and pivoting to the {topic} answer.
- 3 "story moments" from the sources in STAR format (Situation, Task, Action, Result).
**Part 3: Audience Q&A Prep**
3 smart questions the audience will likely ask, with grounded answers using direct source quotes.""",
),
}
REQUIRED_KEYS = [
"topic", "central_theme", "key_concepts", "key_facts",
"origin_story", "implications", "key_concepts_list", "expected_queries",
]
def main() -> int:
p = argparse.ArgumentParser()
p.add_argument("--facts", required=True, help="Path to facts.json")
p.add_argument("--out", default="-", help="Output path (default: stdout)")
args = p.parse_args()
facts = json.loads(Path(args.facts).read_text())
missing = [k for k in REQUIRED_KEYS if k not in facts]
if missing:
print(f"ERROR: facts.json missing keys: {missing}", file=sys.stderr)
return 1
out_lines = [
f"# {facts['topic']} :: docs — 9 Curated NotebookLM Prompts",
"",
"Paste any of these into the NotebookLM chat for this notebook.",
"Prompts 1–3 adapted from XDA Developers; prompts 4–9 adapted from AI Fire.",
"",
"- XDA: https://www.xda-developers.com/prompts-i-use-to-get-most-out-of-noteboooklm/",
"- AI Fire: https://www.aifire.co/p/6-notebooklm-prompts-that-do-your-hard-work-for-you",
"",
"---",
"",
]
for num, (title, body) in TEMPLATES.items():
filled = body.format(**facts)
out_lines.append(f"## Prompt {num} — {title}")
out_lines.append("")
out_lines.append(filled)
out_lines.append("")
out_lines.append("---")
out_lines.append("")
text = "\n".join(out_lines)
if args.out == "-":
print(text)
else:
Path(args.out).write_text(text)
print(f"wrote {args.out}", file=sys.stderr)
return 0
if __name__ == "__main__":
sys.exit(main())
#!/usr/bin/env python3
"""
add_urls_sequential.py — plan-printer for sequential NotebookLM URL adds.
This script does NOT call the MCP tool itself (that happens from Claude's tool
layer). Instead it:
1. Reads a list of candidate URLs
2. Filters out known-failing domains (Medium, Quora, LinkedIn)
3. Cleans URL quirks (strips trailing .md from llms.txt)
4. Emits the sequential call plan for Claude to execute
Usage:
python scripts/add_urls_sequential.py --notebook-id NB_UUID --urls urls.txt
where urls.txt has one URL per line (blank lines and # comments ignored).
Output: prints each filtered URL on its own line, prefixed with
`CALL:` for URLs to add and `SKIP:` for filtered-out ones with a reason.
Claude should execute the CALL lines as separate sequential
mcp__notebooklm-rpc__notebook_add_url calls — one at a time, waiting for each
success response before the next.
"""
import argparse
import re
import sys
from urllib.parse import urlparse
# Domains that silently fail in NotebookLM's URL fetcher.
# Add as a text source instead (scrape with WebFetch).
BLOCKED_DOMAINS = {
"medium.com",
"quora.com",
"linkedin.com",
}
BLOCKED_SUBDOMAIN_SUFFIXES = (
".medium.com",
".quora.com",
".linkedin.com",
)
def clean_url(url: str) -> str:
"""Apply known URL-quirk fixes."""
# Strip trailing .md from llms.txt
url = re.sub(r"(/llms\.txt)\.md(\?|$|#)", r"\1\2", url)
return url.strip()
def is_blocked(url: str) -> tuple[bool, str]:
"""Return (blocked, reason)."""
try:
host = urlparse(url).hostname or ""
except Exception:
return True, "unparseable URL"
host = host.lower()
if host in BLOCKED_DOMAINS:
return True, f"domain {host} silently fails in NotebookLM"
for suffix in BLOCKED_SUBDOMAIN_SUFFIXES:
if host.endswith(suffix):
return True, f"subdomain of {suffix.lstrip('.')} silently fails"
return False, ""
def load_urls(path: str) -> list[str]:
with open(path) as f:
lines = [ln.strip() for ln in f]
return [ln for ln in lines if ln and not ln.startswith("#")]
def main() -> int:
p = argparse.ArgumentParser()
p.add_argument("--notebook-id", required=True)
p.add_argument("--urls", required=True, help="path to file with one URL per line")
args = p.parse_args()
urls = [clean_url(u) for u in load_urls(args.urls)]
call_count = 0
skip_count = 0
print(f"# Sequential add plan for notebook {args.notebook_id}")
print(f"# {len(urls)} candidate URL(s)")
print()
for u in urls:
blocked, reason = is_blocked(u)
if blocked:
print(f"SKIP: {u} # {reason} — scrape content with WebFetch and add as text")
skip_count += 1
else:
print(f"CALL: mcp__notebooklm-rpc__notebook_add_url(notebook_id=\"{args.notebook_id}\", url=\"{u}\")")
call_count += 1
print()
print(f"# Summary: {call_count} to add sequentially, {skip_count} skipped")
print("# Execute each CALL line one at a time. Wait for success before the next.")
return 0
if __name__ == "__main__":
sys.exit(main())
#!/usr/bin/env python3
"""
build_full_studio.py — plan-printer for the full NotebookLM Studio dispatch.
Emits the ordered, topic-customized MCP call plan for generating all 10
Studio artifact types. Claude executes each line as a separate MCP tool call.
The order is tuned to minimize wall-clock time: async media first (audio,
video, infographic, slide deck), then synchronous/fast-async artifacts.
Each call includes confirm=true; user approval MUST be obtained before
executing the emitted plan.
Usage:
python scripts/build_full_studio.py \\
--notebook-id NB_UUID \\
--topic "cmux" \\
--theme "native macOS terminal for parallel AI coding agents" \\
--features "libghostty rendering,notification rings,claude-teams,remote workspaces" \\
--comparison "tmux,Agent Orchestrator,T3 Code,OpenAI Symphony" \\
--audience "macOS developers running parallel Claude Code / Codex sessions"
"""
import argparse
import sys
STUDIO_PLAN = [
# (mcp_tool_name, kwargs_template)
# --- Async media first (longest rendering) ---
(
"audio_overview_create",
lambda t: dict(
notebook_id=t["notebook_id"],
format="deep_dive",
length="default",
language="en",
focus_prompt=(
f"Focus on {t['topic']}: {t['theme']}. Why it was built, key features "
f"({t['features']}), and comparison to {t['comparison']}. Audience: {t['audience']}."
),
confirm=True,
),
),
(
"video_overview_create",
lambda t: dict(
notebook_id=t["notebook_id"],
format="explainer",
visual_style="auto_select",
language="en",
focus_prompt=(
f"Explain {t['topic']} visually: the problem it solves, architecture, "
f"key features ({t['features']}), and traction."
),
confirm=True,
),
),
(
"infographic_create",
lambda t: dict(
notebook_id=t["notebook_id"],
orientation="portrait",
detail_level="detailed",
language="en",
focus_prompt=(
f"Visual overview of {t['topic']}: key features ({t['features']}), "
f"traction metrics, architecture layering, community sentiment themes."
),
confirm=True,
),
),
(
"slide_deck_create",
lambda t: dict(
notebook_id=t["notebook_id"],
format="detailed_deck",
length="default",
language="en",
focus_prompt=(
f"A presentation on {t['topic']}: the problem, the solution, architecture "
f"deep-dive, comparison to {t['comparison']}, installation, traction, limitations."
),
confirm=True,
),
),
# --- Synchronous / fast-async ---
(
"mind_map_create",
lambda t: dict(
notebook_id=t["notebook_id"],
title=f"{t['topic']} Architecture & Ecosystem",
confirm=True,
),
),
(
"report_create",
lambda t: dict(
notebook_id=t["notebook_id"],
report_format="Briefing Doc",
language="en",
confirm=True,
),
),
(
"report_create",
lambda t: dict(
notebook_id=t["notebook_id"],
report_format="Study Guide",
language="en",
confirm=True,
),
),
(
"flashcards_create",
lambda t: dict(
notebook_id=t["notebook_id"],
difficulty="medium",
confirm=True,
),
),
(
"quiz_create",
lambda t: dict(
notebook_id=t["notebook_id"],
question_count=10,
difficulty="medium",
confirm=True,
),
),
(
"data_table_create",
lambda t: dict(
notebook_id=t["notebook_id"],
description=(
f"Comparison table: {t['topic']} vs {t['comparison']}. Columns: Tool, "
f"Layer, Platform, Key differentiator, License. Include a one-line "
f"source quote per row."
),
language="en",
confirm=True,
),
),
]
def fmt_kwargs(kwargs: dict) -> str:
parts = []
for k, v in kwargs.items():
if isinstance(v, bool):
parts.append(f"{k}={str(v).lower()}")
elif isinstance(v, (int, float)):
parts.append(f"{k}={v}")
else:
escaped = str(v).replace('"', '\\"')
parts.append(f'{k}="{escaped}"')
return ", ".join(parts)
def main() -> int:
p = argparse.ArgumentParser()
p.add_argument("--notebook-id", required=True)
p.add_argument("--topic", required=True)
p.add_argument("--theme", required=True, help="One-line topic identity")
p.add_argument("--features", required=True, help="Comma-separated key features")
p.add_argument("--comparison", required=True, help="Comma-separated comparable tools")
p.add_argument("--audience", required=True, help="Target audience")
args = p.parse_args()
topic_ctx = dict(
notebook_id=args.notebook_id,
topic=args.topic,
theme=args.theme,
features=args.features,
comparison=args.comparison,
audience=args.audience,
)
print(f"# Full Studio dispatch plan for {args.topic}")
print(f"# Notebook: {args.notebook_id}")
print("# OBTAIN USER APPROVAL before executing these calls.")
print()
for tool, kwargs_fn in STUDIO_PLAN:
kwargs = kwargs_fn(topic_ctx)
print(f"CALL: mcp__notebooklm-rpc__{tool}({fmt_kwargs(kwargs)})")
print()
print("# After dispatch, wait 45s then call:")
print(f'CALL: mcp__notebooklm-rpc__studio_status(notebook_id="{args.notebook_id}")')
print("# Poll again 2-3 min later for async media (audio/video/infographic/slide deck).")
return 0
if __name__ == "__main__":
sys.exit(main())