nlm — NotebookLM CLI

SkillFiles & storage

Manages Google NotebookLM notebooks via the nlm CLI. Use for creating notebooks, listing and syncing sources, uploading files/URLs/text, chatting with sources, generating reports/audio/video/slides, running research, managing labels, editing notebook metadata (title/emoji/description/cover), and managing notebook content.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the nlm — NotebookLM CLI skill

What this skill tells your AI

The instructions your AI receives, as published by tmc/nlm in skills/nlm/SKILL.md and read by ahel’s review.

Command Discovery

Run nlm --help for the canonical command tree. Run nlm <command> --help for command-local flags. The stable surface is noun-first: notebook, source, note, artifact, and chat groups.

For a compact command map, read reference/commands.md only when needed. Always prefer live help output when it disagrees with the reference.

Interpreting $ARGUMENTS

ArgumentAction
(empty)Run nlm notebook list, then ask what to do
create or newCreate a notebook with nlm notebook create
upload or addAdd one-off sources with nlm source add
syncSync a directory as a managed source with nlm source sync
chatStart, resume, or run one-shot chat
researchRun nlm research and choose fast/deep mode if needed
audio / video / slides / reportUse the corresponding create or generation command
statusShow notebook, sources, artifacts, and recent chats
a notebook IDShow details for that notebook
a file path or globUpload that file/pattern to a notebook

Critical Practices

  • Surface full UUIDs for notebooks, sources, conversations, notes, and artifacts in responses. Follow-up commands need them.
  • Use -y for destructive operations in non-interactive contexts, for example nlm -y notebook delete <id>.
  • Use nlm auth --authuser N or NLM_AUTHUSER=N for non-default Google accounts.
  • Use --direct-rpc for audio download; if the direct fetch is unavailable, it prints the NotebookLM browser URL. video download enables the required direct-RPC path itself and uses the same browser fallback.
  • Prefer canonical grouped commands in all new guidance.

Common Workflows

List notebooks

nlm notebook list
nlm notebook list --limit 25
nlm notebook list --all

Add one-off sources — use source add for files, URLs, and direct text. Pass - to read newline-delimited source references from stdin.

nlm source add <notebook-id> https://example.com/article
nlm source add <notebook-id> ./paper.pdf
nlm source add --name "API notes" <notebook-id> ./notes.txt
printf '%s\n' ./a.pdf https://example.com/b | nlm source add <notebook-id> -

Sync a directory as one sourcesource sync packs files into txtar, quotes nested txtar markers, chunks large payloads, and skips unchanged chunks using a content-hash cache. Use it whenever the same tree will be re-uploaded. Use source add for one-shot single-file/URL uploads.

nlm source sync <notebook-id> src/
nlm source sync --name "project: src/" <notebook-id> src/
nlm source sync --dry-run <notebook-id> .
nlm source sync --force <notebook-id> ./docs ./notes
nlm source sync --json <notebook-id> .

Preview what sync will uploadsource pack writes the exact txtar bytes sync would upload, no network. Pipe through txtar --list or txtar -x to inspect:

nlm source pack src/ | txtar --list
nlm source pack src/ > preview.txtar
nlm source pack --chunk 2 src/ > pt2.txtar

Focus on specific sources--source-ids and --source-match scope chat, generate-chat, generate-report, source-guide, and content transforms. --source-match is a Go regex matched against titles and UUIDs.

nlm chat --source-match 'internal/sync' <notebook-id> "What changed?"
nlm generate-chat --source-ids a,b,c <notebook-id> "Summarize these"
nlm summarize --source-match '^spec/' <notebook-id>
nlm source list <notebook-id> | grep Q3 | nlm chat --source-ids - <notebook-id> "Risks?"

Chat and continuation

nlm chat <notebook-id>
nlm chat <notebook-id> "What are the main conclusions?"
nlm generate-chat --conversation <conversation-id> <notebook-id> "Follow up"
nlm chat show --citations tail <notebook-id> <conversation-id>

Research

nlm research <notebook-id> "What changed in the source set?"
nlm research --mode fast <notebook-id> "Which docs should I read first?"
nlm research --md <notebook-id> "Write a concise brief" > report.md
nlm research --import <notebook-id> "Find source material"

Content creation — creation may take time. Poll with artifact list, audio list, or video list.

nlm create-audio <notebook-id> "Conversational, focus on key decisions"
nlm create-video <notebook-id> "Whiteboard walkthrough"
nlm create-slides <notebook-id> "Presentation summary"
nlm generate-report --sections 3 <notebook-id>
nlm artifact list <notebook-id>
nlm --direct-rpc audio download <notebook-id> output.wav
nlm --direct-rpc video download <notebook-id> output.mp4

Rename after stdin upload — stdin text defaults to "Pasted Text"; use --name during upload or rename after:

nlm source rename <source-id> "descriptive name"

Notebook metadata — title, emoji, description, and cover are separate commands. cover takes a built-in preset ID; cover-image uploads a custom image. unrecent only hides from the recents list, it does not delete.

nlm notebook rename <notebook-id> "New Title"
nlm notebook emoji <notebook-id> "📓"
nlm notebook description <notebook-id> "One-line summary"
echo "long description" | nlm notebook description <notebook-id>
nlm notebook cover <notebook-id> 4
nlm notebook cover-image <notebook-id> ./cover.png
nlm notebook unrecent <notebook-id>

Labels (autolabel clusters) — labels are server-side clusters over sources. generate and relabel-all are heavy server jobs (relabel-all can exceed the 60s deadline on large notebooks); unlabeled only touches sources without a label. attach takes one source per call.

nlm label list <notebook-id>
nlm label generate <notebook-id>
nlm label create <notebook-id> "Important" "⭐"
nlm label rename <notebook-id> <label-id> "New Name"
nlm label emoji <notebook-id> <label-id> "🐛"
nlm label delete <notebook-id> <label-id> [<label-id>...]
nlm label unlabeled <notebook-id>
nlm label relabel-all <notebook-id>
nlm label attach <notebook-id> <label-id|name> <source-id|name>

Discover sources vs chatdiscover-sources calls a server-driven source-discovery RPC (Es3dTe) that returns ranked source IDs for a query. If the server rejects it (error or transient code-13), the CLI falls back to a regular chat call asking the model to list relevant sources. Use it to pick --source-ids for a follow-up; use nlm chat when you want a narrative answer rather than just IDs.

nlm discover-sources <notebook-id> "Q3 revenue assumptions"

Source Freshness Strategy

Pick the lightest tool that does the job:

  • nlm source check <source-id> [notebook-id] — Drive-only. Asks Google whether the indexed copy is still current. No re-index, no upload. Use to decide whether anything else is needed.
  • nlm source refresh <notebook-id> <source-id> — Drive-only. Re-indexes the existing source in place. Use when check reports stale and the source is still a Google Drive document.
  • Re-upload — for non-Drive sources (files, URLs, pasted text) check and refresh do not apply. Use nlm source delete then nlm source add, or for a synced tree run nlm source sync (it auto-detects changed chunks; --force to re-upload unchanged content).

Binary upload workarounds — if a binary upload fails, convert to text:

pdftotext paper.pdf - | nlm source add --name "paper text" <notebook-id> -
plutil -convert xml1 -o - file.plist | nlm source add --name "plist text" <notebook-id> -

Error Recovery

ErrorFix
"Authentication required"Run nlm auth
"Service unavailable" on uploadRetry after a few seconds (rate limit)
"source limit reached" or "Failed precondition" on addRemove unused sources or use a smaller target notebook
"upload init failed (status 500)"Try text extraction workaround
--source-match matched no sourcesRe-run nlm source list <notebook-id> and adjust the regex

Signals

GitHub stars
389
Forks
53
Last commit
Aug 2026
Advanced
Catalog kind
skill
Gateway key
nlm
Source
github.com/tmc/nlm