Skip to content

Commit db9aa51

Browse files
authored
Merge pull request teng-lin#206 from mike-golant/feat/codex-agent-support
docs(agent): add Codex repository guidance
2 parents c47f01f + 18eaf6d commit db9aa51

File tree

11 files changed

+266
-12
lines changed

11 files changed

+266
-12
lines changed

AGENTS.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Repository Guidelines
2+
3+
**Status:** Active
4+
**Last Updated:** 2026-03-13
5+
6+
## Project Structure & Module Organization
7+
8+
`src/notebooklm/` contains the async client and typed APIs. Internal feature modules use `_` prefixes such as `_sources.py` and `_artifacts.py`; `src/notebooklm/cli/` holds Click commands, and `src/notebooklm/rpc/` handles protocol encoding and decoding. Tests are split by scope: `tests/unit/`, `tests/integration/`, and `tests/e2e/`. Recorded HTTP fixtures live in `tests/cassettes/`. Examples are in `docs/examples/`, and diagnostics live in `scripts/`.
9+
10+
## Build, Test, and Development Commands
11+
12+
Use `uv` for local work:
13+
14+
```bash
15+
uv sync --extra dev --extra browser
16+
uv run pytest
17+
uv run ruff check src/ tests/
18+
uv run ruff format src/ tests/
19+
uv run mypy src/notebooklm
20+
uv run pre-commit run --all-files
21+
```
22+
23+
Run `uv run pytest tests/e2e -m readonly` only after `notebooklm login` and setting test notebook env vars.
24+
25+
## Coding Style & Naming Conventions
26+
27+
Target Python 3.10+, 4-space indentation, and double quotes. Ruff enforces formatting and import order with a 100-character line length. Keep module and test file names in `snake_case`; prefer descriptive Click command names that match existing groups such as `source`, `artifact`, and `research`. Preserve the internal/public split: `_*.py` for implementation, exported types in `src/notebooklm/__init__.py`.
28+
29+
## Testing Guidelines
30+
31+
Put pure logic in `tests/unit/`, VCR-backed flows in `tests/integration/`, and authenticated NotebookLM coverage in `tests/e2e/`. Name tests `test_<behavior>.py` and record cassettes with `NOTEBOOKLM_VCR_RECORD=1 uv run pytest tests/integration/test_vcr_*.py -v`. Coverage is expected to stay at or above the configured 90% threshold.
32+
33+
## Commit, PR, and Agent Notes
34+
35+
Follow the existing commit style: `feat(cli): ...`, `fix(cli): ...`, `refactor(test): ...`, `style: ...`. PRs should include a short summary, linked issue when relevant, and the commands run locally. For Codex or other parallel agents, prefer `--json`, pass explicit notebook IDs instead of relying on `notebooklm use`, and isolate runs with `NOTEBOOKLM_HOME=/tmp/<agent-id>` when multiple agents share one machine.

README.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
2828
## What You Can Build
2929

30-
🤖 **AI Agent Tools** - Integrate NotebookLM into Claude Code or other LLM agents. Ships with [Claude Code skills](#agent-skills-claude-code) for natural language automation (`notebooklm skill install`), or build your own integrations with the async Python API.
30+
🤖 **AI Agent Tools** - Integrate NotebookLM into Claude Code, Codex, and other LLM agents. Ships with a [Claude Code skill](#agent-setup) (`notebooklm skill install`) and repo-level Codex instructions in [`AGENTS.md`](AGENTS.md), or build your own integrations with the async Python API.
3131

3232
📚 **Research Automation** - Bulk-import sources (URLs, PDFs, YouTube, Google Drive), run web/Drive research queries with auto-import, and extract insights programmatically. Build repeatable research pipelines.
3333

@@ -41,7 +41,7 @@
4141
|--------|----------|
4242
| **Python API** | Application integration, async workflows, custom pipelines |
4343
| **CLI** | Shell scripts, quick tasks, CI/CD automation |
44-
| **Agent Skills** | Claude Code, LLM agents, natural language automation |
44+
| **Agent Integration** | Claude Code, Codex, LLM agents, natural language automation |
4545

4646
## Features
4747

@@ -95,6 +95,8 @@ pip install "notebooklm-py[browser]"
9595
playwright install chromium
9696
```
9797

98+
If `playwright install chromium` fails with `TypeError: onExit is not a function`, see the Linux workaround in [Troubleshooting](docs/troubleshooting.md#linux).
99+
98100
### Development Installation
99101

100102
For contributors or testing unreleased features:
@@ -157,6 +159,8 @@ Other useful CLI commands:
157159

158160
```bash
159161
notebooklm auth check --test # Diagnose auth/cookie issues
162+
notebooklm agent show codex # Print bundled Codex instructions
163+
notebooklm agent show claude # Print bundled Claude Code skill template
160164
notebooklm language list # List supported output languages
161165
notebooklm metadata --json # Export notebook metadata and sources
162166
notebooklm share status # Inspect sharing state
@@ -197,18 +201,34 @@ async def main():
197201
asyncio.run(main())
198202
```
199203

200-
### Agent Skills (Claude Code)
204+
### Agent Setup
205+
206+
#### Claude Code
201207

202208
```bash
203209
# Install via CLI or ask Claude Code to do it
204210
notebooklm skill install
211+
notebooklm agent show claude
205212

206213
# Then use natural language:
207214
# "Create a podcast about quantum computing"
208215
# "Download the quiz as markdown"
209216
# "/notebooklm generate video"
210217
```
211218

219+
#### Codex
220+
221+
Codex reads repo-level instructions from [`AGENTS.md`](AGENTS.md), so there is no separate install command. After installing dependencies and authenticating, ask Codex to use the `notebooklm` CLI or Python API directly.
222+
223+
```bash
224+
uv sync --extra dev --extra browser
225+
notebooklm agent show codex
226+
notebooklm login
227+
notebooklm list --json
228+
```
229+
230+
For automation, prefer `--json`, pass explicit notebook IDs instead of relying on `notebooklm use`, and set `NOTEBOOKLM_HOME=/tmp/codex-$RUN_ID` when multiple agents may run in parallel.
231+
212232
## Documentation
213233

214234
- **[CLI Reference](docs/cli-reference.md)** - Complete command documentation

docs/cli-reference.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# CLI Reference
22

33
**Status:** Active
4-
**Last Updated:** 2026-03-12
4+
**Last Updated:** 2026-03-13
55

66
Complete command reference for the `notebooklm` CLI—providing full programmatic access to all NotebookLM features, including capabilities not exposed in the web UI.
77

@@ -27,7 +27,7 @@ See [Configuration](configuration.md) for details on environment variables and C
2727
- **Session commands** - Authentication and context management
2828
- **Notebook commands** - CRUD operations on notebooks
2929
- **Chat commands** - Querying and conversation management
30-
- **Grouped commands** - `source`, `artifact`, `generate`, `download`, `note`, `share`, `research`, `language`, `skill`, `auth`
30+
- **Grouped commands** - `source`, `artifact`, `agent`, `generate`, `download`, `note`, `share`, `research`, `language`, `skill`, `auth`
3131
- **Utility commands** - `metadata`
3232

3333
---
@@ -206,6 +206,19 @@ Manage Claude Code skill integration.
206206

207207
After installation, Claude Code recognizes NotebookLM commands via `/notebooklm` or natural language like "create a podcast about X".
208208

209+
Codex does not use the `skill` subcommand. In this repository it reads the root [`AGENTS.md`](../AGENTS.md) file and invokes the `notebooklm` CLI or Python API directly.
210+
211+
### Agent Commands (`notebooklm agent <cmd>`)
212+
213+
Show bundled instructions for supported agent environments.
214+
215+
| Command | Description | Example |
216+
|---------|-------------|---------|
217+
| `show codex` | Print the Codex repository guidance | `agent show codex` |
218+
| `show claude` | Print the bundled Claude Code skill template | `agent show claude` |
219+
220+
`agent show codex` prefers the root [`AGENTS.md`](../AGENTS.md) file when running from a source checkout, so the CLI mirrors the same instructions Codex sees in the repository.
221+
209222
### Features Beyond the Web UI
210223

211224
These CLI capabilities are not available in NotebookLM's web interface:

docs/troubleshooting.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Troubleshooting
22

33
**Status:** Active
4-
**Last Updated:** 2026-01-20
4+
**Last Updated:** 2026-03-13
55

66
Common issues, known limitations, and workarounds for `notebooklm-py`.
77

@@ -307,6 +307,30 @@ audio = next(a for a in artifacts if a.kind == "audio")
307307
playwright install-deps chromium
308308
```
309309

310+
**`playwright install chromium` fails with `TypeError: onExit is not a function`:**
311+
312+
This is an environment-specific Playwright install failure that has been observed with some newer Playwright builds on Linux. `notebooklm-py` only needs a working browser install for `notebooklm login`; the workaround is to install a known-good Playwright version in a clean virtual environment.
313+
314+
**Workaround:**
315+
```bash
316+
python -m venv .venv
317+
source .venv/bin/activate
318+
pip install -U pip
319+
pip install "playwright==1.57.0"
320+
python -m playwright install chromium
321+
pip install -e ".[all]"
322+
```
323+
324+
**Why this order matters:**
325+
- `python -m playwright ...` ensures you use the Playwright module from the active virtual environment
326+
- installing the browser before `pip install -e ".[all]"` avoids picking up an older broken global `playwright` executable
327+
- if you already have another `playwright` on your system, verify with `which playwright` after activation
328+
329+
If you need a non-editable install from Git instead of a local checkout, replace the last step with:
330+
```bash
331+
pip install "git+https://github.com/<your-user>/notebooklm-py@<branch>"
332+
```
333+
310334
**No display available (headless server):**
311335
- Browser login requires a display
312336
- Authenticate on a machine with GUI, then copy `storage_state.json`

src/notebooklm/cli/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
Command groups are organized into separate modules:
66
- source.py: Source management commands (includes add-research)
77
- artifact.py: Artifact management commands
8+
- agent.py: Agent integration helpers
89
- generate.py: Content generation commands
910
- download.py: Download commands
1011
- note.py: Note management commands
@@ -16,6 +17,7 @@
1617
"""
1718

1819
# Command groups (subcommand style)
20+
from .agent import agent
1921
from .artifact import artifact
2022
from .chat import register_chat_commands
2123
from .download import download
@@ -80,6 +82,7 @@
8082
# Command groups (subcommand style)
8183
"source",
8284
"artifact",
85+
"agent",
8386
"generate",
8487
"download",
8588
"note",

src/notebooklm/cli/agent.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""Agent integration commands."""
2+
3+
import click
4+
5+
from .agent_templates import get_agent_source_content
6+
from .helpers import console
7+
8+
9+
@click.group()
10+
def agent():
11+
"""Show bundled instructions for supported agent environments."""
12+
pass
13+
14+
15+
@agent.command("show")
16+
@click.argument("target", type=click.Choice(["codex", "claude"], case_sensitive=False))
17+
def show_agent(target: str):
18+
"""Display instructions for Codex or Claude Code."""
19+
content = get_agent_source_content(target)
20+
if content is None:
21+
console.print(f"[red]Error:[/red] {target} instructions not found in package data.")
22+
raise SystemExit(1)
23+
24+
console.print(content)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""Shared agent instruction loading helpers."""
2+
3+
from importlib import resources
4+
from pathlib import Path
5+
6+
AGENT_TEMPLATE_FILES = {
7+
"claude": "SKILL.md",
8+
"codex": "CODEX.md",
9+
}
10+
11+
REPO_ROOT_AGENTS = Path(__file__).resolve().parents[3] / "AGENTS.md"
12+
13+
14+
def _read_package_data(filename: str) -> str | None:
15+
"""Read a packaged agent template file."""
16+
try:
17+
return (resources.files("notebooklm") / "data" / filename).read_text(encoding="utf-8")
18+
except (FileNotFoundError, TypeError):
19+
return None
20+
21+
22+
def get_agent_source_content(target: str) -> str | None:
23+
"""Return bundled instructions for a supported agent target."""
24+
normalized = target.lower()
25+
26+
# Prefer the repo-level Codex guide when running from a source checkout so
27+
# the CLI mirrors the instructions Codex actually sees in this repository.
28+
if normalized == "codex" and REPO_ROOT_AGENTS.exists():
29+
return REPO_ROOT_AGENTS.read_text(encoding="utf-8")
30+
31+
filename = AGENT_TEMPLATE_FILES.get(normalized)
32+
if filename is None:
33+
return None
34+
35+
return _read_package_data(filename)

src/notebooklm/cli/skill.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55

66
import contextlib
77
import re
8-
from importlib import resources
98
from pathlib import Path
109

1110
import click
1211

12+
from .agent_templates import get_agent_source_content
1313
from .helpers import console
1414

1515
# Skill paths
@@ -19,11 +19,7 @@
1919

2020
def get_skill_source_content() -> str | None:
2121
"""Read the skill source file from package data."""
22-
try:
23-
# Python 3.9+ way to read package data (use / operator for path traversal)
24-
return (resources.files("notebooklm") / "data" / "SKILL.md").read_text(encoding="utf-8")
25-
except (FileNotFoundError, TypeError):
26-
return None
22+
return get_agent_source_content("claude")
2723

2824

2925
def get_package_version() -> str:

src/notebooklm/data/CODEX.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Repository Guidelines
2+
3+
**Status:** Active
4+
**Last Updated:** 2026-03-13
5+
6+
## Project Structure & Module Organization
7+
8+
`src/notebooklm/` contains the async client and typed APIs. Internal feature modules use `_` prefixes such as `_sources.py` and `_artifacts.py`; `src/notebooklm/cli/` holds Click commands, and `src/notebooklm/rpc/` handles protocol encoding and decoding. Tests are split by scope: `tests/unit/`, `tests/integration/`, and `tests/e2e/`. Recorded HTTP fixtures live in `tests/cassettes/`. Examples are in `docs/examples/`, and diagnostics live in `scripts/`.
9+
10+
## Build, Test, and Development Commands
11+
12+
Use `uv` for local work:
13+
14+
```bash
15+
uv sync --extra dev --extra browser
16+
uv run pytest
17+
uv run ruff check src/ tests/
18+
uv run ruff format src/ tests/
19+
uv run mypy src/notebooklm
20+
uv run pre-commit run --all-files
21+
```
22+
23+
Run `uv run pytest tests/e2e -m readonly` only after `notebooklm login` and setting test notebook env vars.
24+
25+
## Coding Style & Naming Conventions
26+
27+
Target Python 3.10+, 4-space indentation, and double quotes. Ruff enforces formatting and import order with a 100-character line length. Keep module and test file names in `snake_case`; prefer descriptive Click command names that match existing groups such as `source`, `artifact`, and `research`. Preserve the internal/public split: `_*.py` for implementation, exported types in `src/notebooklm/__init__.py`.
28+
29+
## Testing Guidelines
30+
31+
Put pure logic in `tests/unit/`, VCR-backed flows in `tests/integration/`, and authenticated NotebookLM coverage in `tests/e2e/`. Name tests `test_<behavior>.py` and record cassettes with `NOTEBOOKLM_VCR_RECORD=1 uv run pytest tests/integration/test_vcr_*.py -v`. Coverage is expected to stay at or above the configured 90% threshold.
32+
33+
## Commit, PR, and Agent Notes
34+
35+
Follow the existing commit style: `feat(cli): ...`, `fix(cli): ...`, `refactor(test): ...`, `style: ...`. PRs should include a short summary, linked issue when relevant, and the commands run locally. For Codex or other parallel agents, prefer `--json`, pass explicit notebook IDs instead of relying on `notebooklm use`, and isolate runs with `NOTEBOOKLM_HOME=/tmp/<agent-id>` when multiple agents share one machine.

src/notebooklm/notebooklm_cli.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161

6262
# Import command groups from cli package
6363
from .cli import (
64+
agent,
6465
artifact,
6566
download,
6667
generate,
@@ -135,6 +136,7 @@ def cli(ctx, storage, verbose):
135136
# Register command groups (subcommand style)
136137
cli.add_command(source)
137138
cli.add_command(artifact)
139+
cli.add_command(agent)
138140
cli.add_command(generate)
139141
cli.add_command(download)
140142
cli.add_command(note)

0 commit comments

Comments
 (0)