This skill only does one thing:
- batch-collect YouTube videos + web articles for a certain topic, feed them into NotebookLM, run analysis queries, and land the results in a local directory (default
./research/<topic>/, configurable)
Not responsible for:
- writing finished articles (leave that to your own writing tool / skill)
- choosing the main title
- downloading videos (leave that to
yt-dlp-directskill) - publishing to multiple platforms (leave that to
publisher-wechatsyncskill)
One-sentence principle: when the user says "help me collect material on topic X" or "pull a batch of YouTube + articles into NotebookLM", follow this fixed pipeline, don't redesign it every time.
When To Use
Applicable scenarios:
- The user wants to write a recommendation/review/opinion piece on a certain topic and needs to do background research first
- The user says "help me find popular YouTube videos and articles about X"
- The user says "collect them into NotebookLM for analysis"
- The user says "put together a material research report on topic X for me"
Not applicable scenarios:
- The user already has a clear list of materials and just wants a summary → directly run
nlm notebook query - What the user wants to do is real-time conversational research and doesn't need to be persisted to a notebook → use WebSearch + WebFetch
- The user only wants to download a single video → use
yt-dlp-direct
Preconditions
Must confirm before starting:
nlmCLI is installed and logged in:nlm login --checkyt-dlpis in PATH:which yt-dlp- The user clearly stated the topic and angle
- The output directory is writable (default
./research/<topic>/, you can specify another path via theRESEARCH_OUTPUT_DIRenvironment variable or directly in the conversation)
When prerequisites are not met:
nlm login --checkfails → have the user runnlm login, session validity ~20 minutesyt-dlpnot installed → stop and tell the user
Working Rules
- Align with the user on topic, angle, and volume first, then start
- Each round of ytsearch defaults to 15 items, can be adjusted as needed
- NotebookLM deep research can only run one task at a time, no concurrency
- When adding sources, sleep 2 seconds between each one to avoid rate limiting
- All outputs (raw JSON + summary markdown) go under
./research/<topic>/(or the directory specified by the user) - This skill is only responsible for collection and analysis, don't go off and write finished articles on your own
- Don't delete the notebook, the user may want to go back and run queries later
Core Workflow
Phase 0: Align goals
Must clarify with the user before starting:
- What the topic is(needs to be a keyword that can be fed to ytsearch in one sentence)
- Angle(e.g. "most commonly used + personal creation" vs "latest releases + technical details")
- Notebook naming(default
<主题> 素材) - Volume(default: 15 YouTube + deep research automatically ~40 web pages)
Phase 1: Create notebook + set alias
nlm notebook create "<话题> 素材"
# 从输出提取 ID,然后:
nlm alias set <short-name> <notebook-id>
Pick a short name for the alias, e.g. skills-research、vps-2026, all subsequent commands use the alias.
Phase 2: yt-dlp ytsearch to find popular YouTube
Run 2-3 searches from different angles in parallel, 15 items each:
yt-dlp --simulate --print "%(title)s|%(webpage_url)s|%(view_count)s|%(uploader)s" \
"ytsearch15:<关键词 A>"
yt-dlp --simulate --print "%(title)s|%(webpage_url)s|%(view_count)s|%(uploader)s" \
"ytsearch15:<关键词 B>"
JS runtime warnings in the output can be ignored.
Filter the top 15 from the results according to the following rules:
- Deduplicate (same video appearing in multiple searches)
- Prioritize official accounts (e.g. Anthropic, OpenAI, etc.)
- Sort by view count from high to low, but leave 2-3 mid-tier videos from vertical angles, to avoid everything being viral press releases
- Keep at least 5 per angle
Phase 3: Add YouTube as a source
Add them one by one with a bash loop, sleeping 2 seconds each time:
cat > /tmp/yt_urls.txt <<'EOF'
https://www.youtube.com/watch?v=XXX1
https://www.youtube.com/watch?v=XXX2
...
EOF
while IFS= read -r url; do
echo "=== Adding: $url ==="
nlm source add <alias> --url "$url" 2>&1 | tail -5
sleep 2
done < /tmp/yt_urls.txt
Occasionally a single item fails (video is private, region-restricted); ignore it and continue, then report the success rate at the end.
Phase 4: Run NotebookLM deep research to discover web articles
nlm research start "<英文查询,适合 web 研究>" \
--notebook-id <alias> --mode deep
Deep mode takes ~5 minutes and returns ~40 web sources.
Key: a notebook can only have one research task running at a time. If you want to run a second round, you must wait for the first round to finish importing, or use --force.
Wait for completion:
nlm research status <alias> --max-wait 360
The Bash tool defaults to a timeout of 120 seconds, so you must add timeout: 400000(i.e., 400 seconds).
Phase 5: Import the research results
After the research completes, get the task-id from the output, then:
nlm research import <alias> <task-id> --timeout 600
Add to the Bash tool timeout: 700000。
Note: the user sometimes says "the material is enough, no need to import more", in which case stop and go directly to Phase 6.
Phase 6: Run 3 analysis queries
By default, run 3 angles, redirecting the command directly to a file to avoid overly large output:
mkdir -p "./research/<topic>"
nlm notebook query <alias> "<问题 1 的中文提示>" \
> "./research/<topic>/query1-<slug>-raw.json" 2>&1
nlm notebook query <alias> "<问题 2 的中文提示>" \
> "./research/<topic>/query2-<slug>-raw.json" 2>&1
nlm notebook query <alias> "<问题 3 的中文提示>" \
> "./research/<topic>/query3-<slug>-raw.json" 2>&1
The Bash call for each query must add timeout: 240000。
Default 3 query templates (change the keywords as needed):
- Top list:"Based on all sources, please list the Top 10 X recommended by the most sources. For each X, explain: (1) name (2) what it specifically does (3) main use cases (4) number of sources that recommend it (5) type classification. Order from highest to lowest recommendation frequency, output in Chinese."
- Target reader oriented:"I want to write an article aimed at <reader persona>. Please filter out the Top 8 X most helpful to <readers>, and for each explain: (1) name (2) specific pain point (3) one-sentence typical usage (4) type (5) the most specific source number. Remove irrelevant ones, focus on <scenario>, in Chinese."
- Getting started + pitfalls:"For <readers> using X, please summarize: (1) the fastest way to get started (2) where to get it (3) the 5 most common pitfalls (4) when it is actually not needed (5) the latest important updates. Attach a source number to each point, in Chinese."
Phase 7: Extract the answer field and generate a summary markdown
The raw output is JSON containing answer + citations; use Python to extract the value.answer field:
python3 <<'PY'
import json, pathlib
base = pathlib.Path("./research/<topic>")
files = [
("query1-<slug>-raw.json", "## Query 1:<标题>"),
("query2-<slug>-raw.json", "## Query 2:<标题>"),
("query3-<slug>-raw.json", "## Query 3:<标题>"),
]
out = ["# <话题> 素材研究", "",
"> 基于 NotebookLM 笔记本 `<notebook-name>` 的分析结果", "",
"---", ""]
for fname, heading in files:
out.append(heading)
out.append("")
raw = (base/fname).read_text()
try:
data = json.loads(raw)
out.append(data.get("value",{}).get("answer",""))
except Exception as e:
out.append(f"(解析失败: {e})")
out.append("")
out.append("---")
out.append("")
(base/"素材研究汇总.md").write_text("\n".join(out))
print("Written:", (base/"素材研究汇总.md").stat().st_size, "bytes")
PY
Output Contract
After execution, report to the user:
- Notebook name + alias + actual source count
- The save paths of the 3 raw JSON files and 1 summary markdown file
- Failed/skipped sources (if any)
- A preview of the summary file's header (around the first 20 lines)
- Suggested next steps (leave it to the user to decide how to use the downstream output; this skill ends here)
Safety and Boundaries
- Do not run audio/video/slides generation by default; these consume quota, so don't touch them unless the user asks
- Do not automatically run a second round of research; one round is enough for the vast majority of scenarios
- Do not overwrite existing
素材研究汇总.md, if it exists append first-v2 - Do not put the user's private information into research queries (notebooks are searchable)
Troubleshooting
nlm login invalid
nlm login --check # 会告诉你是否有效
nlm login # 重新登录
The session is valid for about 20 minutes.
yt-dlp search returns no output
First check the version:
yt-dlp --version
If it's too old, prompt the user to update. Warnings about JS runtime / ffmpeg can be ignored and don't affect --simulate mode.
research times out or gets stuck
Check the status separately (non-blocking):
nlm research status <alias> --max-wait 0
If the status stays in_progress for more than 10 minutes, use --force Restart:
nlm research start "..." --notebook-id <alias> --mode deep --force
query output is too large to view directly
Redirect all query output to a file, then use Python to extract the answer; do not try to print large JSON directly in the terminal.
source add fails repeatedly
- Check whether there is rate limiting → increase sleep to 3-5 seconds
- Check the URL format (YouTube must use
watch?v=standard format, not shorts/live) - Check login state →
nlm login --check
References
- NotebookLM CLI complete guide:
notebooklm-mcp-cli(pip package, author jacob-bd) bundled nlm-skill, or upstream README https://github.com/jacob-bd/notebooklm-mcp-cli - yt-dlp command library: same repository
../yt-dlp-direct/SKILL.md - Project's own conventions: if your working directory has
CLAUDE.md/AGENTS.md, this skill does not depend on it strongly; optional reading