{"owner":"teng-lin","repo":"notebooklm-py","hasSkills":true,"totalSkillsCount":5,"totalTokensCount":2865,"categories":["root-instruction","claude-rule","mcp-config","marketplace","plugin-manifest"],"hasMcp":true,"mcpConfig":{"mcpServers":{"notebooklm-py":{"command":"npx","args":["-y","@modelcontextprotocol/server-notebooklm-py"]}}},"found":["AGENTS.md","CLAUDE.md",".cursor/mcp.json",".claude-plugin/marketplace.json",".claude-plugin/plugin.json"],"skills":{"AGENTS.md":"# Repository Guidelines\n\n**Status:** Active\n**Last Updated:** 2026-09-07\n\n## Structure & Modules\n\n`src/notebooklm/` contains the async client (`client.py`) and typed exports (`__init__.py`).\n- **Internal:** `_*.py` and `_*/` (`_app/`, `_auth/`, `_runtime/`, `_sources.py`, `_artifacts.py`).\n- **Adapters & Wire:** `cli/` (Click), `mcp/` (FastMCP), `server/` (FastAPI), `rpc/` (batchexecute RPC facade), `_android/` (gRPC session & codecs).\n- **Tests & Data:** `tests/unit/`, `tests/integration/` (VCR), `tests/server/`, `tests/e2e/`, `tests/_guardrails/`, `tests/_fault_server/`, `tests/cassettes/` (`web/`, `android/`). Examples in `examples/`, tools in `scripts/`.\n\n## Development Commands\n\nCanonical contributor install (full guide: [docs/installation.md](docs/installation.md)):\n\n```bash\nuv sync --frozen --extra browser --extra dev --extra markdown \\\n        --extra mcp --extra server --extra impersonate\nsource .venv/bin/activate\nuv run playwright install chromium\n\nuv run pytest\nuv run pytest -n auto --dist loadgroup  # faster parallel run\nuv run ruff check .\nuv run ruff format --check .\nuv run mypy src/notebooklm\n```\n\n## Conventions & Testing\n\n- **Style:** Python 3.10+, 4 spaces, double quotes, 100-char line limit (Ruff enforced).\n- **Naming:** `snake_case` modules and tests (`test_<behavior>.py`). Preserve public/internal split (`_*.py`).\n- **Testing:** Unit logic in `tests/unit/`, REST in `tests/server/`, VCR replay in `tests/integration/` (record: `NOTEBOOKLM_VCR_RECORD=1 uv run pytest tests/integration/ -v`), e2e in `tests/e2e/`. 90% coverage gate.\n- **Commits/PRs:** Conventional commits (`feat(cli):`, `fix:`, `refactor:`, `style:`). Link issues and report test runs.\n\n## Parallel & Autonomous Agents\n\n- Prefer `--json` output and pass explicit notebook IDs instead of relying on stateful `notebooklm use`.\n- Isolate concurrent runs with `NOTEBOOKLM_PROFILE=agent-<id>` (`~/.notebooklm/profiles/<name>/`) or `NOTEBOOKLM_HOME=/tmp/agent-<id>`.\n- In headless environments, authenticate with `notebooklm login --browser-cookies <browser>` (requires `pip install \"notebooklm-py[cookies]\"`).\n\n","CLAUDE.md":"# CLAUDE.md\n\nGuidance for Claude Code working in this repository. Follow conventions in [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Project Overview\n\n`notebooklm-py` is an unofficial **async** Python client for Google NotebookLM, driving Google's internal `batchexecute` RPC protocol to automate notebooks, sources, chat, and studio artifacts.\n\n**Critical constraint:** Obfuscated RPC method IDs in `src/notebooklm/rpc/_identifiers.py` are undocumented and Google changes them periodically — the #1 breakage class. `rpc/types.py` re-exports them for backwards compatibility.\n\n## Development Commands\n\nSee [docs/installation.md](docs/installation.md) for the full installation guide.\n\n```bash\n# Contributor install (matches CI test jobs):\nuv sync --frozen --extra browser --extra dev --extra markdown \\\n        --extra mcp --extra server --extra impersonate\nsource .venv/bin/activate\nuv run playwright install chromium\n\nuv run pytest                     # all tests (e2e excluded by default)\nuv run pytest --cov               # with coverage\nuv run pytest tests/e2e -m e2e    # e2e (requires auth)\nuv run notebooklm --help          # CLI\n```\n\nAlways install the full extras set (`mcp`, `server`, `impersonate`); omitting them causes adapter suites to skip silently, masking errors and failing the 90% coverage threshold.\n\n```bash\n# Approximate nightly coverage gate:\nuv run pytest -n auto --dist loadgroup --cov=src/notebooklm \\\n  --cov-report=term-missing --cov-fail-under=90\n```\n\n`--dist loadgroup` is required to honor `@pytest.mark.xdist_group`. Avoid piping test commands into `tail`/`grep` to prevent masking non-zero exit codes.\n\n## Before Pushing\n\nCI enforces formatting, linting, type checks, and tests:\n\n```bash\nuv run ruff check .\nuv run ruff format --check .\nuv run mypy src/notebooklm scripts/_live_auth_scenarios --ignore-missing-imports\nuv run pytest\n```\n\n## Architecture\n\nAdapters (`cli/`, `mcp/`, `server/`) → `_app/` (business logic) → `client.py` + `_runtime/` → selected backend (`_web/` or `_android/`) → `raw.py` (`rpc/` is Web compatibility facade).\n\nSee [docs/architecture.md](docs/architecture.md) for layered design, call flows, cross-cutting policies (loop affinity, idempotency, schema validation), and the full file map.\n\n## Common Pitfalls\n\n1. **RPC method IDs change** — re-capture network traffic and update `rpc/_identifiers.py`.\n2. **Position-sensitive nested params** — mirror existing shapes; source-id nesting varies (`[id]` / `[[id]]` / `[[[id]]]` / `[[[[id]]]]`).\n3. **CSRF tokens expire** — call `client.refresh_auth()` or re-run `notebooklm login`.\n4. **Rate limiting** — add delays between bulk operations.\n5. **Concurrency** — one `NotebookLMClient` is bound to its `open()` event loop: one per thread, never reuse across loops or `AuthTokens` tenants (see [concurrency contract](docs/python-api.md#concurrency-contract)).\n\n## Usage\n\n```python\nasync with NotebookLMClient.from_storage() as client:\n    notebooks = await client.notebooks.list()\n    await client.sources.add_url(nb_id, url)\n    answer = await client.chat.ask(nb_id, question)\n    status = await client.artifacts.generate_audio(nb_id)\n```\n\n- **CLI:** Top-level commands (`login`, `use`, `status`, `list`, `ask`) and groups (`source`, `label`, `artifact`, `generate`, `download`, `note`, `mcp`, `research`). Reference: [docs/cli-reference.md](docs/cli-reference.md).\n- **MCP Server:** Console script `notebooklm-mcp` exposes `_app/` logic over MCP. Install with `notebooklm mcp install <client>`. Reference: [docs/mcp-guide.md](docs/mcp-guide.md).\n- **REST Server:** Console script `notebooklm-server` exposes `/v1` routes over `_app/`. Requires `NOTEBOOKLM_SERVER_TOKEN`. Reference: [docs/installation.md#rest-api-server](docs/installation.md#rest-api-server).\n\n## Testing\n\n- **Unit:** `tests/unit/` (offline; includes `_app`, CLI, server, guardrails).\n- **Integration:** `tests/integration/` (VCR cassette replay matching method, scheme, host, port, path, rpcids, freq). Record with `NOTEBOOKLM_VCR_RECORD=1 uv run pytest tests/integration/ -v`.\n- **E2E:** `tests/e2e/` (real API, `@pytest.mark.e2e`, requires auth).\n- Details: [docs/development.md](docs/development.md).\n\n## Documentation Map\n\nKey references in `docs/`: [installation](docs/installation.md), [cli-reference](docs/cli-reference.md), [python-api](docs/python-api.md), [architecture](docs/architecture.md), [development](docs/development.md), [mcp-guide](docs/mcp-guide.md), [troubleshooting](docs/troubleshooting.md), and [adr/](docs/adr/).\n\n## Pull Request Workflow (required)\n\nDrive PRs to merge:\n\n1. Poll `gh pr checks <PR>` until all pass; investigate and fix any failures.\n2. Trigger Claude review by commenting `@claude review` on the PR.\n3. Address every review comment (`gemini-code-assist`, `coderabbitai`, `claude[bot]`): fix, push, reply on the thread (`Addressed in <SHA>: …`), and resolve threads.\n4. Merge only when all checks pass, all threads are resolved, and `mergeStateStatus` is `CLEAN`.\n\n**Note on `@claude review`:**\n- `claude[bot]` posts a sticky summary issue comment and inline diff comments (`gh api /repos/<owner>/<repo>/pulls/<PR>/comments`). It does not submit a formal GitHub `reviewDecision`, so check comments directly.\n- Ensure all inline `claude[bot]` review threads are addressed and resolved before merging.\n",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.claude-plugin/plugin.json)"},"files":{"AGENTS.md":"# Repository Guidelines\n\n**Status:** Active\n**Last Updated:** 2026-09-07\n\n## Structure & Modules\n\n`src/notebooklm/` contains the async client (`client.py`) and typed exports (`__init__.py`).\n- **Internal:** `_*.py` and `_*/` (`_app/`, `_auth/`, `_runtime/`, `_sources.py`, `_artifacts.py`).\n- **Adapters & Wire:** `cli/` (Click), `mcp/` (FastMCP), `server/` (FastAPI), `rpc/` (batchexecute RPC facade), `_android/` (gRPC session & codecs).\n- **Tests & Data:** `tests/unit/`, `tests/integration/` (VCR), `tests/server/`, `tests/e2e/`, `tests/_guardrails/`, `tests/_fault_server/`, `tests/cassettes/` (`web/`, `android/`). Examples in `examples/`, tools in `scripts/`.\n\n## Development Commands\n\nCanonical contributor install (full guide: [docs/installation.md](docs/installation.md)):\n\n```bash\nuv sync --frozen --extra browser --extra dev --extra markdown \\\n        --extra mcp --extra server --extra impersonate\nsource .venv/bin/activate\nuv run playwright install chromium\n\nuv run pytest\nuv run pytest -n auto --dist loadgroup  # faster parallel run\nuv run ruff check .\nuv run ruff format --check .\nuv run mypy src/notebooklm\n```\n\n## Conventions & Testing\n\n- **Style:** Python 3.10+, 4 spaces, double quotes, 100-char line limit (Ruff enforced).\n- **Naming:** `snake_case` modules and tests (`test_<behavior>.py`). Preserve public/internal split (`_*.py`).\n- **Testing:** Unit logic in `tests/unit/`, REST in `tests/server/`, VCR replay in `tests/integration/` (record: `NOTEBOOKLM_VCR_RECORD=1 uv run pytest tests/integration/ -v`), e2e in `tests/e2e/`. 90% coverage gate.\n- **Commits/PRs:** Conventional commits (`feat(cli):`, `fix:`, `refactor:`, `style:`). Link issues and report test runs.\n\n## Parallel & Autonomous Agents\n\n- Prefer `--json` output and pass explicit notebook IDs instead of relying on stateful `notebooklm use`.\n- Isolate concurrent runs with `NOTEBOOKLM_PROFILE=agent-<id>` (`~/.notebooklm/profiles/<name>/`) or `NOTEBOOKLM_HOME=/tmp/agent-<id>`.\n- In headless environments, authenticate with `notebooklm login --browser-cookies <browser>` (requires `pip install \"notebooklm-py[cookies]\"`).\n\n","CLAUDE.md":"# CLAUDE.md\n\nGuidance for Claude Code working in this repository. Follow conventions in [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Project Overview\n\n`notebooklm-py` is an unofficial **async** Python client for Google NotebookLM, driving Google's internal `batchexecute` RPC protocol to automate notebooks, sources, chat, and studio artifacts.\n\n**Critical constraint:** Obfuscated RPC method IDs in `src/notebooklm/rpc/_identifiers.py` are undocumented and Google changes them periodically — the #1 breakage class. `rpc/types.py` re-exports them for backwards compatibility.\n\n## Development Commands\n\nSee [docs/installation.md](docs/installation.md) for the full installation guide.\n\n```bash\n# Contributor install (matches CI test jobs):\nuv sync --frozen --extra browser --extra dev --extra markdown \\\n        --extra mcp --extra server --extra impersonate\nsource .venv/bin/activate\nuv run playwright install chromium\n\nuv run pytest                     # all tests (e2e excluded by default)\nuv run pytest --cov               # with coverage\nuv run pytest tests/e2e -m e2e    # e2e (requires auth)\nuv run notebooklm --help          # CLI\n```\n\nAlways install the full extras set (`mcp`, `server`, `impersonate`); omitting them causes adapter suites to skip silently, masking errors and failing the 90% coverage threshold.\n\n```bash\n# Approximate nightly coverage gate:\nuv run pytest -n auto --dist loadgroup --cov=src/notebooklm \\\n  --cov-report=term-missing --cov-fail-under=90\n```\n\n`--dist loadgroup` is required to honor `@pytest.mark.xdist_group`. Avoid piping test commands into `tail`/`grep` to prevent masking non-zero exit codes.\n\n## Before Pushing\n\nCI enforces formatting, linting, type checks, and tests:\n\n```bash\nuv run ruff check .\nuv run ruff format --check .\nuv run mypy src/notebooklm scripts/_live_auth_scenarios --ignore-missing-imports\nuv run pytest\n```\n\n## Architecture\n\nAdapters (`cli/`, `mcp/`, `server/`) → `_app/` (business logic) → `client.py` + `_runtime/` → selected backend (`_web/` or `_android/`) → `raw.py` (`rpc/` is Web compatibility facade).\n\nSee [docs/architecture.md](docs/architecture.md) for layered design, call flows, cross-cutting policies (loop affinity, idempotency, schema validation), and the full file map.\n\n## Common Pitfalls\n\n1. **RPC method IDs change** — re-capture network traffic and update `rpc/_identifiers.py`.\n2. **Position-sensitive nested params** — mirror existing shapes; source-id nesting varies (`[id]` / `[[id]]` / `[[[id]]]` / `[[[[id]]]]`).\n3. **CSRF tokens expire** — call `client.refresh_auth()` or re-run `notebooklm login`.\n4. **Rate limiting** — add delays between bulk operations.\n5. **Concurrency** — one `NotebookLMClient` is bound to its `open()` event loop: one per thread, never reuse across loops or `AuthTokens` tenants (see [concurrency contract](docs/python-api.md#concurrency-contract)).\n\n## Usage\n\n```python\nasync with NotebookLMClient.from_storage() as client:\n    notebooks = await client.notebooks.list()\n    await client.sources.add_url(nb_id, url)\n    answer = await client.chat.ask(nb_id, question)\n    status = await client.artifacts.generate_audio(nb_id)\n```\n\n- **CLI:** Top-level commands (`login`, `use`, `status`, `list`, `ask`) and groups (`source`, `label`, `artifact`, `generate`, `download`, `note`, `mcp`, `research`). Reference: [docs/cli-reference.md](docs/cli-reference.md).\n- **MCP Server:** Console script `notebooklm-mcp` exposes `_app/` logic over MCP. Install with `notebooklm mcp install <client>`. Reference: [docs/mcp-guide.md](docs/mcp-guide.md).\n- **REST Server:** Console script `notebooklm-server` exposes `/v1` routes over `_app/`. Requires `NOTEBOOKLM_SERVER_TOKEN`. Reference: [docs/installation.md#rest-api-server](docs/installation.md#rest-api-server).\n\n## Testing\n\n- **Unit:** `tests/unit/` (offline; includes `_app`, CLI, server, guardrails).\n- **Integration:** `tests/integration/` (VCR cassette replay matching method, scheme, host, port, path, rpcids, freq). Record with `NOTEBOOKLM_VCR_RECORD=1 uv run pytest tests/integration/ -v`.\n- **E2E:** `tests/e2e/` (real API, `@pytest.mark.e2e`, requires auth).\n- Details: [docs/development.md](docs/development.md).\n\n## Documentation Map\n\nKey references in `docs/`: [installation](docs/installation.md), [cli-reference](docs/cli-reference.md), [python-api](docs/python-api.md), [architecture](docs/architecture.md), [development](docs/development.md), [mcp-guide](docs/mcp-guide.md), [troubleshooting](docs/troubleshooting.md), and [adr/](docs/adr/).\n\n## Pull Request Workflow (required)\n\nDrive PRs to merge:\n\n1. Poll `gh pr checks <PR>` until all pass; investigate and fix any failures.\n2. Trigger Claude review by commenting `@claude review` on the PR.\n3. Address every review comment (`gemini-code-assist`, `coderabbitai`, `claude[bot]`): fix, push, reply on the thread (`Addressed in <SHA>: …`), and resolve threads.\n4. Merge only when all checks pass, all threads are resolved, and `mergeStateStatus` is `CLEAN`.\n\n**Note on `@claude review`:**\n- `claude[bot]` posts a sticky summary issue comment and inline diff comments (`gh api /repos/<owner>/<repo>/pulls/<PR>/comments`). It does not submit a formal GitHub `reviewDecision`, so check comments directly.\n- Ensure all inline `claude[bot]` review threads are addressed and resolved before merging.\n",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.claude-plugin/plugin.json)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Repository Guidelines\n\n**Status:** Active\n**Last Updated:** 2026-09-07\n\n## Structure & Modules\n\n`src/notebooklm/` contains the async client (`client.py`) and typed exports (`__init__.py`).\n- **Internal:** `_*.py` and `_*/` (`_app/`, `_auth/`, `_runtime/`, `_sources.py`, `_artifacts.py`).\n- **Adapters & Wire:** `cli/` (Click), `mcp/` (FastMCP), `server/` (FastAPI), `rpc/` (batchexecute RPC facade), `_android/` (gRPC session & codecs).\n- **Tests & Data:** `tests/unit/`, `tests/integration/` (VCR), `tests/server/`, `tests/e2e/`, `tests/_guardrails/`, `tests/_fault_server/`, `tests/cassettes/` (`web/`, `android/`). Examples in `examples/`, tools in `scripts/`.\n\n## Development Commands\n\nCanonical contributor install (full guide: [docs/installation.md](docs/installation.md)):\n\n```bash\nuv sync --frozen --extra browser --extra dev --extra markdown \\\n        --extra mcp --extra server --extra impersonate\nsource .venv/bin/activate\nuv run playwright install chromium\n\nuv run pytest\nuv run pytest -n auto --dist loadgroup  # faster parallel run\nuv run ruff check .\nuv run ruff format --check .\nuv run mypy src/notebooklm\n```\n\n## Conventions & Testing\n\n- **Style:** Python 3.10+, 4 spaces, double quotes, 100-char line limit (Ruff enforced).\n- **Naming:** `snake_case` modules and tests (`test_<behavior>.py`). Preserve public/internal split (`_*.py`).\n- **Testing:** Unit logic in `tests/unit/`, REST in `tests/server/`, VCR replay in `tests/integration/` (record: `NOTEBOOKLM_VCR_RECORD=1 uv run pytest tests/integration/ -v`), e2e in `tests/e2e/`. 90% coverage gate.\n- **Commits/PRs:** Conventional commits (`feat(cli):`, `fix:`, `refactor:`, `style:`). Link issues and report test runs.\n\n## Parallel & Autonomous Agents\n\n- Prefer `--json` output and pass explicit notebook IDs instead of relying on stateful `notebooklm use`.\n- Isolate concurrent runs with `NOTEBOOKLM_PROFILE=agent-<id>` (`~/.notebooklm/profiles/<name>/`) or `NOTEBOOKLM_HOME=/tmp/agent-<id>`.\n- In headless environments, authenticate with `notebooklm login --browser-cookies <browser>` (requires `pip install \"notebooklm-py[cookies]\"`).\n\n","isInternal":false,"tokens":604,"sizeBytes":2114},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# CLAUDE.md\n\nGuidance for Claude Code working in this repository. Follow conventions in [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Project Overview\n\n`notebooklm-py` is an unofficial **async** Python client for Google NotebookLM, driving Google's internal `batchexecute` RPC protocol to automate notebooks, sources, chat, and studio artifacts.\n\n**Critical constraint:** Obfuscated RPC method IDs in `src/notebooklm/rpc/_identifiers.py` are undocumented and Google changes them periodically — the #1 breakage class. `rpc/types.py` re-exports them for backwards compatibility.\n\n## Development Commands\n\nSee [docs/installation.md](docs/installation.md) for the full installation guide.\n\n```bash\n# Contributor install (matches CI test jobs):\nuv sync --frozen --extra browser --extra dev --extra markdown \\\n        --extra mcp --extra server --extra impersonate\nsource .venv/bin/activate\nuv run playwright install chromium\n\nuv run pytest                     # all tests (e2e excluded by default)\nuv run pytest --cov               # with coverage\nuv run pytest tests/e2e -m e2e    # e2e (requires auth)\nuv run notebooklm --help          # CLI\n```\n\nAlways install the full extras set (`mcp`, `server`, `impersonate`); omitting them causes adapter suites to skip silently, masking errors and failing the 90% coverage threshold.\n\n```bash\n# Approximate nightly coverage gate:\nuv run pytest -n auto --dist loadgroup --cov=src/notebooklm \\\n  --cov-report=term-missing --cov-fail-under=90\n```\n\n`--dist loadgroup` is required to honor `@pytest.mark.xdist_group`. Avoid piping test commands into `tail`/`grep` to prevent masking non-zero exit codes.\n\n## Before Pushing\n\nCI enforces formatting, linting, type checks, and tests:\n\n```bash\nuv run ruff check .\nuv run ruff format --check .\nuv run mypy src/notebooklm scripts/_live_auth_scenarios --ignore-missing-imports\nuv run pytest\n```\n\n## Architecture\n\nAdapters (`cli/`, `mcp/`, `server/`) → `_app/` (business logic) → `client.py` + `_runtime/` → selected backend (`_web/` or `_android/`) → `raw.py` (`rpc/` is Web compatibility facade).\n\nSee [docs/architecture.md](docs/architecture.md) for layered design, call flows, cross-cutting policies (loop affinity, idempotency, schema validation), and the full file map.\n\n## Common Pitfalls\n\n1. **RPC method IDs change** — re-capture network traffic and update `rpc/_identifiers.py`.\n2. **Position-sensitive nested params** — mirror existing shapes; source-id nesting varies (`[id]` / `[[id]]` / `[[[id]]]` / `[[[[id]]]]`).\n3. **CSRF tokens expire** — call `client.refresh_auth()` or re-run `notebooklm login`.\n4. **Rate limiting** — add delays between bulk operations.\n5. **Concurrency** — one `NotebookLMClient` is bound to its `open()` event loop: one per thread, never reuse across loops or `AuthTokens` tenants (see [concurrency contract](docs/python-api.md#concurrency-contract)).\n\n## Usage\n\n```python\nasync with NotebookLMClient.from_storage() as client:\n    notebooks = await client.notebooks.list()\n    await client.sources.add_url(nb_id, url)\n    answer = await client.chat.ask(nb_id, question)\n    status = await client.artifacts.generate_audio(nb_id)\n```\n\n- **CLI:** Top-level commands (`login`, `use`, `status`, `list`, `ask`) and groups (`source`, `label`, `artifact`, `generate`, `download`, `note`, `mcp`, `research`). Reference: [docs/cli-reference.md](docs/cli-reference.md).\n- **MCP Server:** Console script `notebooklm-mcp` exposes `_app/` logic over MCP. Install with `notebooklm mcp install <client>`. Reference: [docs/mcp-guide.md](docs/mcp-guide.md).\n- **REST Server:** Console script `notebooklm-server` exposes `/v1` routes over `_app/`. Requires `NOTEBOOKLM_SERVER_TOKEN`. Reference: [docs/installation.md#rest-api-server](docs/installation.md#rest-api-server).\n\n## Testing\n\n- **Unit:** `tests/unit/` (offline; includes `_app`, CLI, server, guardrails).\n- **Integration:** `tests/integration/` (VCR cassette replay matching method, scheme, host, port, path, rpcids, freq). Record with `NOTEBOOKLM_VCR_RECORD=1 uv run pytest tests/integration/ -v`.\n- **E2E:** `tests/e2e/` (real API, `@pytest.mark.e2e`, requires auth).\n- Details: [docs/development.md](docs/development.md).\n\n## Documentation Map\n\nKey references in `docs/`: [installation](docs/installation.md), [cli-reference](docs/cli-reference.md), [python-api](docs/python-api.md), [architecture](docs/architecture.md), [development](docs/development.md), [mcp-guide](docs/mcp-guide.md), [troubleshooting](docs/troubleshooting.md), and [adr/](docs/adr/).\n\n## Pull Request Workflow (required)\n\nDrive PRs to merge:\n\n1. Poll `gh pr checks <PR>` until all pass; investigate and fix any failures.\n2. Trigger Claude review by commenting `@claude review` on the PR.\n3. Address every review comment (`gemini-code-assist`, `coderabbitai`, `claude[bot]`): fix, push, reply on the thread (`Addressed in <SHA>: …`), and resolve threads.\n4. Merge only when all checks pass, all threads are resolved, and `mergeStateStatus` is `CLEAN`.\n\n**Note on `@claude review`:**\n- `claude[bot]` posts a sticky summary issue comment and inline diff comments (`gh api /repos/<owner>/<repo>/pulls/<PR>/comments`). It does not submit a formal GitHub `reviewDecision`, so check comments directly.\n- Ensure all inline `claude[bot]` review threads are addressed and resolved before merging.\n","isInternal":false,"tokens":1361,"sizeBytes":5335},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.claude-plugin/marketplace.json","title":"Claude Plugin Marketplace Catalog","category":"marketplace","format":"json","content":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.claude-plugin/marketplace.json)","tokens":300,"sizeBytes":201},{"name":"plugin.json","path":".claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.claude-plugin/plugin.json","title":"claude-plugin Plugin Manifest","category":"plugin-manifest","format":"json","content":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.claude-plugin/plugin.json)","tokens":300,"sizeBytes":187},{"name":"mcp.json","path":".cursor/mcp.json","rawUrl":"https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.cursor/mcp.json","title":"Model Context Protocol (MCP) Configuration","category":"mcp-config","format":"json","content":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.cursor/mcp.json)","tokens":300,"sizeBytes":180}],"systemPromptSnippet":"<yakaai_skills repo=\"teng-lin/notebooklm-py\">\n<!-- File: AGENTS.md (Tokens: ~604 | Category: root-instruction) -->\n# Repository Guidelines\n\n**Status:** Active\n**Last Updated:** 2026-09-07\n\n## Structure & Modules\n\n`src/notebooklm/` contains the async client (`client.py`) and typed exports (`__init__.py`).\n- **Internal:** `_*.py` and `_*/` (`_app/`, `_auth/`, `_runtime/`, `_sources.py`, `_artifacts.py`).\n- **Adapters & Wire:** `cli/` (Click), `mcp/` (FastMCP), `server/` (FastAPI), `rpc/` (batchexecute RPC facade), `_android/` (gRPC session & codecs).\n- **Tests & Data:** `tests/unit/`, `tests/integration/` (VCR), `tests/server/`, `tests/e2e/`, `tests/_guardrails/`, `tests/_fault_server/`, `tests/cassettes/` (`web/`, `android/`). Examples in `examples/`, tools in `scripts/`.\n\n## Development Commands\n\nCanonical contributor install (full guide: [docs/installation.md](docs/installation.md)):\n\n```bash\nuv sync --frozen --extra browser --extra dev --extra markdown \\\n        --extra mcp --extra server --extra impersonate\nsource .venv/bin/activate\nuv run playwright install chromium\n\nuv run pytest\nuv run pytest -n auto --dist loadgroup  # faster parallel run\nuv run ruff check .\nuv run ruff format --check .\nuv run mypy src/notebooklm\n```\n\n## Conventions & Testing\n\n- **Style:** Python 3.10+, 4 spaces, double quotes, 100-char line limit (Ruff enforced).\n- **Naming:** `snake_case` modules and tests (`test_<behavior>.py`). Preserve public/internal split (`_*.py`).\n- **Testing:** Unit logic in `tests/unit/`, REST in `tests/server/`, VCR replay in `tests/integration/` (record: `NOTEBOOKLM_VCR_RECORD=1 uv run pytest tests/integration/ -v`), e2e in `tests/e2e/`. 90% coverage gate.\n- **Commits/PRs:** Conventional commits (`feat(cli):`, `fix:`, `refactor:`, `style:`). Link issues and report test runs.\n\n## Parallel & Autonomous Agents\n\n- Prefer `--json` output and pass explicit notebook IDs instead of relying on stateful `notebooklm use`.\n- Isolate concurrent runs with `NOTEBOOKLM_PROFILE=agent-<id>` (`~/.notebooklm/profiles/<name>/`) or `NOTEBOOKLM_HOME=/tmp/agent-<id>`.\n- In headless environments, authenticate with `notebooklm login --browser-cookies <browser>` (requires `pip install \"notebooklm-py[cookies]\"`).\n\n<!-- File: CLAUDE.md (Tokens: ~1361 | Category: claude-rule) -->\n# CLAUDE.md\n\nGuidance for Claude Code working in this repository. Follow conventions in [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Project Overview\n\n`notebooklm-py` is an unofficial **async** Python client for Google NotebookLM, driving Google's internal `batchexecute` RPC protocol to automate notebooks, sources, chat, and studio artifacts.\n\n**Critical constraint:** Obfuscated RPC method IDs in `src/notebooklm/rpc/_identifiers.py` are undocumented and Google changes them periodically — the #1 breakage class. `rpc/types.py` re-exports them for backwards compatibility.\n\n## Development Commands\n\nSee [docs/installation.md](docs/installation.md) for the full installation guide.\n\n```bash\n# Contributor install (matches CI test jobs):\nuv sync --frozen --extra browser --extra dev --extra markdown \\\n        --extra mcp --extra server --extra impersonate\nsource .venv/bin/activate\nuv run playwright install chromium\n\nuv run pytest                     # all tests (e2e excluded by default)\nuv run pytest --cov               # with coverage\nuv run pytest tests/e2e -m e2e    # e2e (requires auth)\nuv run notebooklm --help          # CLI\n```\n\nAlways install the full extras set (`mcp`, `server`, `impersonate`); omitting them causes adapter suites to skip silently, masking errors and failing the 90% coverage threshold.\n\n```bash\n# Approximate nightly coverage gate:\nuv run pytest -n auto --dist loadgroup --cov=src/notebooklm \\\n  --cov-report=term-missing --cov-fail-under=90\n```\n\n`--dist loadgroup` is required to honor `@pytest.mark.xdist_group`. Avoid piping test commands into `tail`/`grep` to prevent masking non-zero exit codes.\n\n## Before Pushing\n\nCI enforces formatting, linting, type checks, and tests:\n\n```bash\nuv run ruff check .\nuv run ruff format --check .\nuv run mypy src/notebooklm scripts/_live_auth_scenarios --ignore-missing-imports\nuv run pytest\n```\n\n## Architecture\n\nAdapters (`cli/`, `mcp/`, `server/`) → `_app/` (business logic) → `client.py` + `_runtime/` → selected backend (`_web/` or `_android/`) → `raw.py` (`rpc/` is Web compatibility facade).\n\nSee [docs/architecture.md](docs/architecture.md) for layered design, call flows, cross-cutting policies (loop affinity, idempotency, schema validation), and the full file map.\n\n## Common Pitfalls\n\n1. **RPC method IDs change** — re-capture network traffic and update `rpc/_identifiers.py`.\n2. **Position-sensitive nested params** — mirror existing shapes; source-id nesting varies (`[id]` / `[[id]]` / `[[[id]]]` / `[[[[id]]]]`).\n3. **CSRF tokens expire** — call `client.refresh_auth()` or re-run `notebooklm login`.\n4. **Rate limiting** — add delays between bulk operations.\n5. **Concurrency** — one `NotebookLMClient` is bound to its `open()` event loop: one per thread, never reuse across loops or `AuthTokens` tenants (see [concurrency contract](docs/python-api.md#concurrency-contract)).\n\n## Usage\n\n```python\nasync with NotebookLMClient.from_storage() as client:\n    notebooks = await client.notebooks.list()\n    await client.sources.add_url(nb_id, url)\n    answer = await client.chat.ask(nb_id, question)\n    status = await client.artifacts.generate_audio(nb_id)\n```\n\n- **CLI:** Top-level commands (`login`, `use`, `status`, `list`, `ask`) and groups (`source`, `label`, `artifact`, `generate`, `download`, `note`, `mcp`, `research`). Reference: [docs/cli-reference.md](docs/cli-reference.md).\n- **MCP Server:** Console script `notebooklm-mcp` exposes `_app/` logic over MCP. Install with `notebooklm mcp install <client>`. Reference: [docs/mcp-guide.md](docs/mcp-guide.md).\n- **REST Server:** Console script `notebooklm-server` exposes `/v1` routes over `_app/`. Requires `NOTEBOOKLM_SERVER_TOKEN`. Reference: [docs/installation.md#rest-api-server](docs/installation.md#rest-api-server).\n\n## Testing\n\n- **Unit:** `tests/unit/` (offline; includes `_app`, CLI, server, guardrails).\n- **Integration:** `tests/integration/` (VCR cassette replay matching method, scheme, host, port, path, rpcids, freq). Record with `NOTEBOOKLM_VCR_RECORD=1 uv run pytest tests/integration/ -v`.\n- **E2E:** `tests/e2e/` (real API, `@pytest.mark.e2e`, requires auth).\n- Details: [docs/development.md](docs/development.md).\n\n## Documentation Map\n\nKey references in `docs/`: [installation](docs/installation.md), [cli-reference](docs/cli-reference.md), [python-api](docs/python-api.md), [architecture](docs/architecture.md), [development](docs/development.md), [mcp-guide](docs/mcp-guide.md), [troubleshooting](docs/troubleshooting.md), and [adr/](docs/adr/).\n\n## Pull Request Workflow (required)\n\nDrive PRs to merge:\n\n1. Poll `gh pr checks <PR>` until all pass; investigate and fix any failures.\n2. Trigger Claude review by commenting `@claude review` on the PR.\n3. Address every review comment (`gemini-code-assist`, `coderabbitai`, `claude[bot]`): fix, push, reply on the thread (`Addressed in <SHA>: …`), and resolve threads.\n4. Merge only when all checks pass, all threads are resolved, and `mergeStateStatus` is `CLEAN`.\n\n**Note on `@claude review`:**\n- `claude[bot]` posts a sticky summary issue comment and inline diff comments (`gh api /repos/<owner>/<repo>/pulls/<PR>/comments`). It does not submit a formal GitHub `reviewDecision`, so check comments directly.\n- Ensure all inline `claude[bot]` review threads are addressed and resolved before merging.\n\n<!-- File: .claude-plugin/marketplace.json (Tokens: ~300 | Category: marketplace) -->\n# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.claude-plugin/marketplace.json)\n\n<!-- File: .claude-plugin/plugin.json (Tokens: ~300 | Category: plugin-manifest) -->\n# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.claude-plugin/plugin.json)\n\n<!-- File: .cursor/mcp.json (Tokens: ~300 | Category: mcp-config) -->\n# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/teng-lin/notebooklm-py/HEAD/.cursor/mcp.json)\n</yakaai_skills>"}