Gemini Notebook Automation skill

Install, authenticate, troubleshoot, and operate Gemini Notebook through the notebooklm-py CLI or typed async Python API.

by teng-lin·MIT license·★ 19,597 Stars on the repo·GitHub ↗

Use now

Files of Gemini Notebook Automation

teng-lin/main1 file
SKILL.md
Show the full text316 lines

Gemini Notebook Automation

Use the notebooklm CLI for agent workflows. Prefer --json and explicit IDs so every operation is inspectable and safe under concurrency. Use the typed async Python API only when the user requests application code or the CLI cannot express the workflow. The readiness, identity, authorization, and credential-handling rules below apply to both interfaces.

Setup and Authentication

Requires Python 3.10+. Install the package in the user's existing environment; do not create a separate environment unless requested:

pip install "notebooklm-py[browser]"
pip install "notebooklm-py[cookies]"  # optional browser-cookie extraction

If system pip reports externally-managed-environment, do not use --break-system-packages. For CLI-only use, offer uv tool install "notebooklm-py[browser]" or the equivalent pipx command; for application code, use the user's active project environment.

For unattended or headless work, prefer durable profile-backed master-token auth over a copied cookie snapshot. Install pip install "notebooklm-py[headless]"; the one-time automatic OAuth capture also needs [browser]. On a trusted workstation run notebooklm login --master-token --account <email>, then deploy master_token.json, not storage_state.json, to the selected profile. NOTEBOOKLM_HOME selects the private base directory and NOTEBOOKLM_PROFILE selects its profile; defaults resolve to ~/.notebooklm/profiles/default/master_token.json.

In CI, NOTEBOOKLM_MASTER_TOKEN_JSON is a secret-transport convention, not an environment variable the package reads directly. Write its exact value to the selected profile's master_token.json with mode 0600, unset it, then run notebooklm auth refresh to mint storage_state.json. A sibling master token can automatically re-mint expired file-backed cookies. Inline NOTEBOOKLM_AUTH_JSON is only a short-lived fallback; it bypasses this recovery path.

Use PyPI or a release tag, not an unreleased main checkout. When available, consult the installation guide.

Before a workflow, verify real authentication rather than merely parsing the cookie file:

notebooklm auth check --test --json

Require .status == "ok" and .checks.token_fetch == true. If validation fails:

  • With a display, run notebooklm login and validate again.
  • In a headless environment, install [cookies] and use notebooklm login --browser-cookies <browser>. Use notebooklm auth inspect --browser <browser> first when account selection is unclear.
  • If previously valid cookies became stale, try notebooklm auth refresh; use notebooklm auth refresh --browser-cookies <browser> after signing back into the browser.

The normal --test preflight may heal and persist refreshed cookies. Add --passive when the check must be strictly read-only, including the failure-diagnosis workflow below.

notebooklm status reports selected-notebook context, not authentication.

Treat both auth files as bearer credentials: never print, log, or commit them. A master token is a durable full-account credential that survives password changes; use a dedicated account, protect it in a secret store and as 0600 on disk, and explicitly revoke it if exposed.

Operating Invariants

  1. Use --json for discovery and mutations, then retain the returned full UUIDs. Important envelopes are .notebook.id from create, .source.id from source add, and .task_id from asynchronous generators. generate mind-map instead returns mind_map, note_id, and kind; both kinds return a finished result with no task ID or separate artifact wait step.
  2. Pass -n/--notebook <id> on every notebook-scoped command in automation or concurrent work. Do not rely on notebooklm use. For every concurrent run, also set a unique NOTEBOOKLM_PROFILE=agent-<id> so context and profile writes are isolated. A new profile has no credentials: put a master_token.json copy in that profile and mint its storage before use. Never share one writable storage_state.json across agents.
  3. After adding sources, retain every .source.id, then run source wait for each before chat or generation. The add envelope has no status. Require wait exit 0 and status == "ready"; let the waiter handle media-specific transient error rows.
  4. After an asynchronous generator returns a task/artifact ID, pass it positionally to artifact wait with -n <notebook_id>. Download that exact artifact with -a <artifact_id> -n <notebook_id>; never select the latest visible artifact. Mind-map generation returns its completed result directly and does not need artifact wait.
  5. For overlapping research runs, always pass --run-id <research_run_id>.
  6. Use a host's background facility only when it actually exists. Keep wait and dependent download commands in one sequential job, and download only after the wait exits 0. Otherwise run in the foreground or return exact ID-pinned commands to the user.

Authorization Boundaries

Safe inspection and explicitly requested creation, source addition, chat, and prompt suggestion can run directly. Diagnose failures with read-only commands before attempting recovery.

Obtain confirmation immediately before an action when it was not already clearly authorized:

  • destructive commands such as notebook/source/note/artifact/label/profile deletion, sharing removal, logout, clear, research cancellation, and ask --new;
  • language set, because the default mode changes the account-global output language (prefer a generation command's --language override);
  • generation or long foreground waits, which can take minutes and be rate-limited;
  • downloads, which write files;
  • research wait --import-all, which imports sources;
  • ask --save-as-note and history --save, which create notes.

User intent, not the presence of a CLI prompt, is the authorization boundary. After authorization, pass --yes/-y where supported. Most destructive JSON commands refuse to prompt without it, but some, including ask --new --json and share remove --json, execute without prompting. Never treat prompt absence as consent.

research cancel is fire-and-forget. After an authorized cancellation, verify the exact run with notebooklm research status -n <notebook_id> --run-id <research_run_id> --json.

Command Discovery

Use the installed CLI's help as the version-matched source of truth instead of guessing flags:

notebooklm --help
notebooklm source --help
notebooklm research --help
notebooklm generate --help
notebooklm artifact --help
notebooklm download --help

Also inspect notebooklm --version and drill down to the exact command, such as notebooklm generate audio --help, whenever its help differs from this skill.

Common operations:

Goal Command
Check compute usage notebooklm usage --json; notebooklm usage --categories for category availability and estimated costs
List or create notebooks notebooklm list --json; notebooklm create "Title" --json
Add and wait for a source notebooklm source add <input> -n <nb> --json; notebooklm source wait <src> -n <nb>
URL recovery notebooklm source add <url> --fallback-fetch
Chat notebooklm ask "question" -n <nb> --json
Research notebooklm source add-research "query" -n <nb> --mode fast --json (deep is also supported)
List or wait for artifacts notebooklm artifact list -n <nb> --json; notebooklm artifact wait <id> -n <nb>
Generate notebooklm generate <type> ... -n <nb> --json
Download notebooklm download <type> <path> -n <nb> -a <artifact>

For the full surface, consult the installed command help or, when available, the CLI reference. For application code, use the baseline below and, when available, the Python API guide.

Canonical Source-to-Artifact Workflow

Keep {notebook_id}, every {source_id}, and {artifact_id} from JSON output:

An explicit request for this completed workflow authorizes its normal prerequisite waits, requested generation, and requested output file. Confirm only work not already authorized by that request.

  1. notebooklm create "Research: topic" --json
  2. notebooklm source add <input> -n {notebook_id} --json for each input.
  3. Once the foreground wait is authorized, run notebooklm source wait {source_id} -n {notebook_id} --timeout 600 for every captured source.
  4. Once generation is authorized, generate the requested type. For audio: notebooklm generate audio "instructions" -n {notebook_id} -s {source_id} --json. Repeat -s for each selected source and capture .task_id as {artifact_id}.
  5. Once the foreground wait is authorized, run notebooklm artifact wait {artifact_id} -n {notebook_id} --timeout 1200.
  6. Once the output write is authorized, run notebooklm download audio ./podcast.m4a -a {artifact_id} -n {notebook_id}.

For analysis without generation, replace steps 4-6 with an ID-pinned chat command only after every source is ready:

notebooklm ask "Summarize the key arguments" -n {notebook_id} --json

Deep Research

Deep research can take 15-30+ minutes. Start it non-blocking and retain .poll_task_id // .task_id as {research_run_id}:

notebooklm source add-research "query" -n {notebook_id} --mode deep --no-wait --json

Import only after explicit authorization, pinning both IDs:

notebooklm research wait -n {notebook_id} --run-id {research_run_id} \
  --import-all --timeout 1800 --json

With --import-all, --timeout is a per-phase budget for polling and import retry, so this example can consume roughly 3600 seconds of host wall time.

Retain newly created source IDs from .imported_sources[].id and wait for readiness before later chat or generation.

Python API Baseline

When the full API guide is unavailable, use the installed typed API and its docstrings; do not guess method names. Keep the same IDs and readiness gates as the CLI workflow:

import asyncio

from notebooklm import NotebookLMClient


async def main(url: str) -> None:
    async with NotebookLMClient.from_storage() as client:
        notebook = await client.notebooks.create("Research: topic")
        source = await client.sources.add_url(notebook.id, url)
        await client.sources.wait_until_ready(notebook.id, source.id, timeout=600)

        answer = await client.chat.ask(
            notebook.id, "Summarize the key arguments", source_ids=[source.id]
        )
        print(answer.answer)

        task = await client.artifacts.generate_audio(
            notebook.id,
            source_ids=[source.id],
            instructions="Focus on the key arguments",
        )
        final = await client.artifacts.wait_for_completion(notebook.id, task.task_id, timeout=1200)
        if not final.is_complete:
            raise RuntimeError(f"Generation ended with {final.status}: {final.error}")
        await client.artifacts.download_audio(
            notebook.id, "./podcast.m4a", artifact_id=task.task_id
        )


asyncio.run(main("https://example.com"))

NotebookLMClient.from_storage() is an async context manager and is not awaited. A client is re-entrant on one event loop but is not thread-safe; create one client per loop. Public namespaces include notebooks, sources, chat, research, artifacts, mind_maps, notes, settings, sharing, labels, and collections. Apply the authorization boundaries above before running state-changing, long-running, or file-writing calls.

Generation Notes

Available generators include audio, video, slide-deck, infographic, report, mind-map, data-table, quiz, and flashcards. Inspect notebooklm generate <type> --help because formats, styles, source selection, language, and retry support vary by type.

Keep these non-obvious distinctions:

  • Mind map (--kind interactive, default) is an asynchronous studio artifact internally, but the CLI polls it to completion and returns {mind_map, note_id, kind}; do not run artifact wait.
  • Mind map (--kind note-backed) is server-synchronous. Both kinds accept --instructions; interactive applies it reliably, while the server may ignore it for note-backed maps.
  • generate video --format cinematic ignores --style, requires Google AI Ultra, and can take roughly 30-40 minutes.
  • Slide-deck has no orientation flag. Request portrait output in the description (for example, 9:16 portrait); slide revision cannot change the deck's orientation.
  • For a custom report, pass the prompt as the positional description with --format custom; --append applies only to built-in report formats.

For prompts too long or awkward for shell quoting, use --prompt-file PATH on ask, source add-research, and supported generators. It contains prompt text; upload source documents with source add instead.

Output and Citations

Use JSON structurally rather than parsing human output. Common lifecycle values are:

  • sources: unknown/preparing/processing -> ready or error; proceed only on ready;
  • artifacts: pending/in_progress -> completed, failed, or removed; not_found may be a brief listing lag. Proceed or download only on completed.

Chat JSON includes answer, conversation_id, and references[].source_id. A reference's start_char/end_char are UTF-16 offsets into the structured source document, not flat SourceFulltext.content. In Python, use from notebooklm import resolve_chat_reference_passage, then call await resolve_chat_reference_passage(client, notebook_id, reference); it uses the exact document range and falls back to find_citation_context() when necessary.

Failure Handling

On failure, run safe read-only diagnosis first:

notebooklm auth check --test --passive --json
notebooklm list --json
notebooklm source list -n {notebook_id} --json
notebooklm artifact list -n {notebook_id} --json
notebooklm research status -n {notebook_id} --run-id {research_run_id} --json

Inspect only the commands relevant to the failed workflow. Do not mutate state during diagnosis.

  • Exit 0 means success. Expected command failures use exit 1. A source wait timeout uses exit 2; artifact wait and research wait timeouts use exit 1.
  • Branch on exit code first. Ordinary handled JSON failures use {error, code, message}, while wait commands return domain envelopes such as {"status": "timeout", "error": "..."}.
  • On auth failure, revalidate checks.token_fetch; log in only if it is not true.
  • On a wait timeout, report it and inspect the exact source, artifact, or research run.
  • Generation is rate-limited by Google. Preserve the task ID, inspect status, and retry only when the user authorizes it; do not loop indefinitely. For an existing failed Studio artifact, inspect notebooklm artifact retry <artifact_id> -n {notebook_id} --help before retrying in place.
  • On a protocol error, record the installed version, exact command, relevant IDs, and redacted error. Check the project's issue tracker when network access exists; do not invent a workaround when it does not.

Keep progress updates brief and include the relevant returned ID. Never expose credential contents.

Skill Installation

If this file is already inside an agent skill directory, the skill itself is installed. Otherwise:

  • notebooklm skill install installs or updates supported local skill targets.
  • notebooklm skill package builds an uploadable archive for sandboxed agent environments.
  • notebooklm skill status --json reports installed versions and content_mismatch.
1---
2name: notebooklm
3description: Install, authenticate, troubleshoot, and operate Gemini Notebook through the notebooklm-py CLI or typed async Python API. Use for notebook and source management, grounded chat and research, and artifact generation or download when the user mentions Gemini Notebook, notebooklm-py, the notebooklm CLI, or its Python API. Do not use for the generic Gemini API or unrelated content creation.
4---
5 
6# Gemini Notebook Automation
7 
8Use the `notebooklm` CLI for agent workflows. Prefer `--json` and explicit IDs so every
9operation is inspectable and safe under concurrency. Use the typed async Python API only when the
10user requests application code or the CLI cannot express the workflow. The readiness, identity,
11authorization, and credential-handling rules below apply to both interfaces.
12 
13## Setup and Authentication
14 
15Requires Python 3.10+. Install the package in the user's existing environment; do not create a
16separate environment unless requested:
17 
18```bash
19pip install "notebooklm-py[browser]"
20pip install "notebooklm-py[cookies]" # optional browser-cookie extraction
21```
22 
23If system `pip` reports `externally-managed-environment`, do not use `--break-system-packages`.
24For CLI-only use, offer `uv tool install "notebooklm-py[browser]"` or the equivalent `pipx`
25command; for application code, use the user's active project environment.
26 
27For unattended or headless work, prefer durable profile-backed master-token auth over a copied
28cookie snapshot. Install `pip install "notebooklm-py[headless]"`; the one-time automatic OAuth
29capture also needs `[browser]`. On a trusted workstation run
30`notebooklm login --master-token --account <email>`, then deploy `master_token.json`, not
31`storage_state.json`, to the selected profile. `NOTEBOOKLM_HOME` selects the private base directory
32and `NOTEBOOKLM_PROFILE` selects its profile; defaults resolve to
33`~/.notebooklm/profiles/default/master_token.json`.
34 
35In CI, `NOTEBOOKLM_MASTER_TOKEN_JSON` is a secret-transport convention, not an environment variable
36the package reads directly. Write its exact value to the selected profile's `master_token.json`
37with mode `0600`, unset it, then run `notebooklm auth refresh` to mint `storage_state.json`. A
38sibling master token can automatically re-mint expired file-backed cookies. Inline
39`NOTEBOOKLM_AUTH_JSON` is only a short-lived fallback; it bypasses this recovery path.
40 
41Use PyPI or a release tag, not an unreleased `main` checkout. When available, consult the
42[installation guide](https://github.com/teng-lin/notebooklm-py/blob/main/docs/installation.md).
43 
44Before a workflow, verify real authentication rather than merely parsing the cookie file:
45 
46```bash
47notebooklm auth check --test --json
48```
49 
50Require `.status == "ok"` and `.checks.token_fetch == true`. If validation fails:
51 
52- With a display, run `notebooklm login` and validate again.
53- In a headless environment, install `[cookies]` and use
54 `notebooklm login --browser-cookies <browser>`. Use
55 `notebooklm auth inspect --browser <browser>` first when account selection is unclear.
56- If previously valid cookies became stale, try `notebooklm auth refresh`; use
57 `notebooklm auth refresh --browser-cookies <browser>` after signing back into the browser.
58 
59The normal `--test` preflight may heal and persist refreshed cookies. Add `--passive` when the
60check must be strictly read-only, including the failure-diagnosis workflow below.
61 
62`notebooklm status` reports selected-notebook context, not authentication.
63 
64Treat both auth files as bearer credentials: never print, log, or commit them. A master token is a
65durable full-account credential that survives password changes; use a dedicated account, protect
66it in a secret store and as `0600` on disk, and explicitly revoke it if exposed.
67 
68## Operating Invariants
69 
701. Use `--json` for discovery and mutations, then retain the returned full UUIDs. Important
71 envelopes are `.notebook.id` from `create`, `.source.id` from `source add`, and `.task_id` from
72 asynchronous generators. `generate mind-map` instead returns `mind_map`, `note_id`, and `kind`;
73 both kinds return a finished result with no task ID or separate `artifact wait` step.
742. Pass `-n/--notebook <id>` on every notebook-scoped command in automation or concurrent work.
75 Do not rely on `notebooklm use`. For every concurrent run, also set a unique
76 `NOTEBOOKLM_PROFILE=agent-<id>` so context and profile writes are isolated. A new profile has no
77 credentials: put a `master_token.json` copy in that profile and mint its storage before use.
78 Never share one writable `storage_state.json` across agents.
793. After adding sources, retain every `.source.id`, then run `source wait` for each before chat or
80 generation. The add envelope has no status. Require wait exit 0 and `status == "ready"`; let the
81 waiter handle media-specific transient `error` rows.
824. After an asynchronous generator returns a task/artifact ID, pass it positionally to
83 `artifact wait` with `-n <notebook_id>`. Download that exact artifact with
84 `-a <artifact_id> -n <notebook_id>`; never select the latest visible artifact. Mind-map generation
85 returns its completed result directly and does not need `artifact wait`.
865. For overlapping research runs, always pass `--run-id <research_run_id>`.
876. Use a host's background facility only when it actually exists. Keep wait and dependent download
88 commands in one sequential job, and download only after the wait exits 0. Otherwise run in the
89 foreground or return exact ID-pinned commands to the user.
90 
91## Authorization Boundaries
92 
93Safe inspection and explicitly requested creation, source addition, chat, and prompt suggestion can
94run directly. Diagnose failures with read-only commands before attempting recovery.
95 
96Obtain confirmation immediately before an action when it was not already clearly authorized:
97 
98- destructive commands such as notebook/source/note/artifact/label/profile deletion, sharing
99 removal, logout, clear, research cancellation, and `ask --new`;
100- `language set`, because the default mode changes the account-global output language (prefer a
101 generation command's `--language` override);
102- generation or long foreground waits, which can take minutes and be rate-limited;
103- downloads, which write files;
104- `research wait --import-all`, which imports sources;
105- `ask --save-as-note` and `history --save`, which create notes.
106 
107User intent, not the presence of a CLI prompt, is the authorization boundary. After authorization,
108pass `--yes`/`-y` where supported. Most destructive JSON commands refuse to prompt without it, but
109some, including `ask --new --json` and `share remove --json`, execute without prompting. Never
110treat prompt absence as consent.
111 
112`research cancel` is fire-and-forget. After an authorized cancellation, verify the exact run with
113`notebooklm research status -n <notebook_id> --run-id <research_run_id> --json`.
114 
115## Command Discovery
116 
117Use the installed CLI's help as the version-matched source of truth instead of guessing flags:
118 
119```bash
120notebooklm --help
121notebooklm source --help
122notebooklm research --help
123notebooklm generate --help
124notebooklm artifact --help
125notebooklm download --help
126```
127 
128Also inspect `notebooklm --version` and drill down to the exact command, such as
129`notebooklm generate audio --help`, whenever its help differs from this skill.
130 
131Common operations:
132 
133| Goal | Command |
134|---|---|
135| Check compute usage | `notebooklm usage --json`; `notebooklm usage --categories` for category availability and estimated costs |
136| List or create notebooks | `notebooklm list --json`; `notebooklm create "Title" --json` |
137| Add and wait for a source | `notebooklm source add <input> -n <nb> --json`; `notebooklm source wait <src> -n <nb>` |
138| URL recovery | `notebooklm source add <url> --fallback-fetch` |
139| Chat | `notebooklm ask "question" -n <nb> --json` |
140| Research | `notebooklm source add-research "query" -n <nb> --mode fast --json` (`deep` is also supported) |
141| List or wait for artifacts | `notebooklm artifact list -n <nb> --json`; `notebooklm artifact wait <id> -n <nb>` |
142| Generate | `notebooklm generate <type> ... -n <nb> --json` |
143| Download | `notebooklm download <type> <path> -n <nb> -a <artifact>` |
144 
145For the full surface, consult the installed command help or, when available, the
146[CLI reference](https://github.com/teng-lin/notebooklm-py/blob/main/docs/cli-reference.md).
147For application code, use the baseline below and, when available, the
148[Python API guide](https://github.com/teng-lin/notebooklm-py/blob/main/docs/python-api.md).
149 
150## Canonical Source-to-Artifact Workflow
151 
152Keep `{notebook_id}`, every `{source_id}`, and `{artifact_id}` from JSON output:
153 
154An explicit request for this completed workflow authorizes its normal prerequisite waits, requested
155generation, and requested output file. Confirm only work not already authorized by that request.
156 
1571. `notebooklm create "Research: topic" --json`
1582. `notebooklm source add <input> -n {notebook_id} --json` for each input.
1593. Once the foreground wait is authorized, run
160 `notebooklm source wait {source_id} -n {notebook_id} --timeout 600` for every captured source.
1614. Once generation is authorized, generate the requested type. For audio:
162 `notebooklm generate audio "instructions" -n {notebook_id} -s {source_id} --json`.
163 Repeat `-s` for each selected source and capture `.task_id` as `{artifact_id}`.
1645. Once the foreground wait is authorized, run
165 `notebooklm artifact wait {artifact_id} -n {notebook_id} --timeout 1200`.
1666. Once the output write is authorized, run
167 `notebooklm download audio ./podcast.m4a -a {artifact_id} -n {notebook_id}`.
168 
169For analysis without generation, replace steps 4-6 with an ID-pinned chat command only after every
170source is ready:
171 
172```bash
173notebooklm ask "Summarize the key arguments" -n {notebook_id} --json
174```
175 
176## Deep Research
177 
178Deep research can take 15-30+ minutes. Start it non-blocking and retain
179`.poll_task_id // .task_id` as `{research_run_id}`:
180 
181```bash
182notebooklm source add-research "query" -n {notebook_id} --mode deep --no-wait --json
183```
184 
185Import only after explicit authorization, pinning both IDs:
186 
187```bash
188notebooklm research wait -n {notebook_id} --run-id {research_run_id} \
189 --import-all --timeout 1800 --json
190```
191 
192With `--import-all`, `--timeout` is a per-phase budget for polling and import retry, so this example
193can consume roughly 3600 seconds of host wall time.
194 
195Retain newly created source IDs from `.imported_sources[].id` and wait for readiness before later
196chat or generation.
197 
198## Python API Baseline
199 
200When the full API guide is unavailable, use the installed typed API and its docstrings; do not guess
201method names. Keep the same IDs and readiness gates as the CLI workflow:
202 
203```python
204import asyncio
205 
206from notebooklm import NotebookLMClient
207 
208 
209async def main(url: str) -> None:
210 async with NotebookLMClient.from_storage() as client:
211 notebook = await client.notebooks.create("Research: topic")
212 source = await client.sources.add_url(notebook.id, url)
213 await client.sources.wait_until_ready(notebook.id, source.id, timeout=600)
214 
215 answer = await client.chat.ask(
216 notebook.id, "Summarize the key arguments", source_ids=[source.id]
217 )
218 print(answer.answer)
219 
220 task = await client.artifacts.generate_audio(
221 notebook.id,
222 source_ids=[source.id],
223 instructions="Focus on the key arguments",
224 )
225 final = await client.artifacts.wait_for_completion(notebook.id, task.task_id, timeout=1200)
226 if not final.is_complete:
227 raise RuntimeError(f"Generation ended with {final.status}: {final.error}")
228 await client.artifacts.download_audio(
229 notebook.id, "./podcast.m4a", artifact_id=task.task_id
230 )
231 
232 
233asyncio.run(main("https://example.com"))
234```
235 
236`NotebookLMClient.from_storage()` is an async context manager and is not awaited. A client is
237re-entrant on one event loop but is not thread-safe; create one client per loop. Public namespaces
238include `notebooks`, `sources`, `chat`, `research`, `artifacts`, `mind_maps`, `notes`, `settings`,
239`sharing`, `labels`, and `collections`. Apply the authorization boundaries above before running
240state-changing, long-running, or file-writing calls.
241 
242## Generation Notes
243 
244Available generators include `audio`, `video`, `slide-deck`, `infographic`, `report`, `mind-map`,
245`data-table`, `quiz`, and `flashcards`. Inspect `notebooklm generate <type> --help` because formats,
246styles, source selection, language, and retry support vary by type.
247 
248Keep these non-obvious distinctions:
249 
250- Mind map (`--kind interactive`, default) is an asynchronous studio artifact internally, but the
251 CLI polls it to completion and returns `{mind_map, note_id, kind}`; do not run `artifact wait`.
252- Mind map (`--kind note-backed`) is server-synchronous. Both kinds accept `--instructions`;
253 interactive applies it reliably, while the server may ignore it for note-backed maps.
254- `generate video --format cinematic` ignores `--style`, requires Google AI Ultra, and can take
255 roughly 30-40 minutes.
256- Slide-deck has no orientation flag. Request portrait output in the description (for example,
257 `9:16 portrait`); slide revision cannot change the deck's orientation.
258- For a custom report, pass the prompt as the positional description with `--format custom`;
259 `--append` applies only to built-in report formats.
260 
261For prompts too long or awkward for shell quoting, use `--prompt-file PATH` on `ask`,
262`source add-research`, and supported generators. It contains prompt text; upload source documents
263with `source add` instead.
264 
265## Output and Citations
266 
267Use JSON structurally rather than parsing human output. Common lifecycle values are:
268 
269- sources: `unknown`/`preparing`/`processing` -> `ready` or `error`; proceed only on `ready`;
270- artifacts: `pending`/`in_progress` -> `completed`, `failed`, or `removed`; `not_found` may be a
271 brief listing lag. Proceed or download only on `completed`.
272 
273Chat JSON includes `answer`, `conversation_id`, and `references[].source_id`. A reference's
274`start_char`/`end_char` are UTF-16 offsets into the structured source document, not flat
275`SourceFulltext.content`. In Python, use
276`from notebooklm import resolve_chat_reference_passage`, then call
277`await resolve_chat_reference_passage(client, notebook_id, reference)`; it uses the exact document
278range and falls back to `find_citation_context()` when necessary.
279 
280## Failure Handling
281 
282On failure, run safe read-only diagnosis first:
283 
284```bash
285notebooklm auth check --test --passive --json
286notebooklm list --json
287notebooklm source list -n {notebook_id} --json
288notebooklm artifact list -n {notebook_id} --json
289notebooklm research status -n {notebook_id} --run-id {research_run_id} --json
290```
291 
292Inspect only the commands relevant to the failed workflow. Do not mutate state during diagnosis.
293 
294- Exit 0 means success. Expected command failures use exit 1. A `source wait` timeout uses exit 2;
295 `artifact wait` and `research wait` timeouts use exit 1.
296- Branch on exit code first. Ordinary handled JSON failures use `{error, code, message}`, while wait
297 commands return domain envelopes such as `{"status": "timeout", "error": "..."}`.
298- On auth failure, revalidate `checks.token_fetch`; log in only if it is not `true`.
299- On a wait timeout, report it and inspect the exact source, artifact, or research run.
300- Generation is rate-limited by Google. Preserve the task ID, inspect status, and retry only when the
301 user authorizes it; do not loop indefinitely. For an existing failed Studio artifact, inspect
302 `notebooklm artifact retry <artifact_id> -n {notebook_id} --help` before retrying in place.
303- On a protocol error, record the installed version, exact command, relevant IDs, and redacted
304 error. Check the project's issue tracker when network access exists; do not invent a workaround
305 when it does not.
306 
307Keep progress updates brief and include the relevant returned ID. Never expose credential contents.
308 
309## Skill Installation
310 
311If this file is already inside an agent skill directory, the skill itself is installed. Otherwise:
312 
313- `notebooklm skill install` installs or updates supported local skill targets.
314- `notebooklm skill package` builds an uploadable archive for sandboxed agent environments.
315- `notebooklm skill status --json` reports installed versions and `content_mismatch`.
316 

Discussion

Alternatives

API and interface designGuides stable API and interface design. Use when designing APIs, module boundaries, or any public interface. Use when creating REST or GraphQL endpoints, defining type contracts between modules, or establishing boundaries between frontend and backend.Coding · MITContext7Pulls up-to-date, version-specific library docs and code examples into the prompt so the AI stops inventing old APIs.Coding · MITContext7 Documentation LookupFetch up-to-date documentation and code examples for any library, framework, SDK, CLI tool, or cloud service. Use whenever the user asks about a specific library — even well-known ones like React, Next.js, Prisma, Express, Tailwind, Django, or Spring Boot — because training data may not reflect recent API changes or version updates. Always use for: API syntax questions, configuration options, version migration issues, "how do I" questions mentioning a library name, debugging that involves library-specific behavior, setup instructions, and CLI tool usage. Use even when you think you know the answer. Do not rely on training data for API details, signatures, or configuration options — they are frequently out of date. Prefer this over web search for library documentation.Coding · MITAdaptyv Bio Foundry APIHow to use the Adaptyv Bio Foundry API and Python SDK for protein experiment design, submission, and results retrieval. Use this skill whenever the user mentions Adaptyv, Foundry API, protein binding assays, protein screening experiments, BLI/SPR assays, thermostability assays, or wants to submit protein sequences for experimental characterization. Also trigger when code imports `adaptyv`, `adaptyv_sdk`, or `FoundryClient`, or references `foundry-api-public.adaptyvbio.com`.Science · MIT