nlm

star 371

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.

tmc By tmc schedule Updated 5/24/2026

name: nlm description: "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." when_to_use: "User mentions NotebookLM, nlm, notebook IDs, source upload/sync, chat with sources, report/audio/video/slides generation, research, labels/autolabel clusters, notebook metadata (rename/emoji/description/cover), or managing NotebookLM notes/artifacts." allowed-tools: Bash(*), Read, Glob, Grep, Write argument-hint: "[action] [args...]"

nlm — NotebookLM CLI

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

Argument Action
(empty) Run nlm notebook list, then ask what to do
create or new Create a notebook with nlm notebook create
upload or add Add one-off sources with nlm source add
sync Sync a directory as a managed source with nlm source sync
chat Start, resume, or run one-shot chat
research Run nlm research and choose fast/deep mode if needed
audio / video / slides / report Use the corresponding create or generation command
status Show notebook, sources, artifacts, and recent chats
a notebook ID Show details for that notebook
a file path or glob Upload 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

Error Fix
"Authentication required" Run nlm auth
"Service unavailable" on upload Retry after a few seconds (rate limit)
"source limit reached" or "Failed precondition" on add Remove unused sources or use a smaller target notebook
"upload init failed (status 500)" Try text extraction workaround
--source-match matched no sources Re-run nlm source list <notebook-id> and adjust the regex
Install via CLI
npx skills add https://github.com/tmc/nlm --skill nlm
Repository Details
star Stars 371
call_split Forks 53
navigation Branch main
article Path SKILL.md
More from Creator