- config.py: add _sanitize_agent_id() to strip path traversal chars and limit length; use it in get_agent_config_dir() - account_manager.py: set_agent_active_account() validates account exists before saving, raises ValueError if not found - account_manager.py: switch_account() also persists to agent-specific file when running under an agent ID - auth_manager.py: status() shows 'Active Account (agent-specific):', 'Active Account (global):', or 'Active Account:' based on context - SKILL.md: add 'accounts remove <id>' to commands table Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
24 KiB
Executable File
name, description
| name | description |
|---|---|
| nblm | Use this skill to query your Google NotebookLM notebooks directly from Claude Code for source-grounded, citation-backed answers from Gemini. Browser automation, library management, persistent auth. Drastically reduced hallucinations through document-only responses. |
NotebookLM Quick Commands
Query Google NotebookLM for source-grounded, citation-backed answers.
Environment
All dependencies and authentication are handled automatically by run.py:
- First run creates
.venvand installs Python/Node.js dependencies - If Google auth is missing or expired, a browser window opens automatically
- No manual pre-flight steps required
Usage
/nblm <command> [args]
Commands
Notebook Management
| Command | Description |
|---|---|
login |
Authenticate with Google |
status |
Show auth and library status |
accounts |
List all Google accounts |
accounts add |
Add a new Google account |
accounts switch <id> |
Switch active account (by index or email) |
accounts remove <id> |
Remove a Google account |
accounts use <id> |
Set agent-specific active account (OpenClaw isolation) |
accounts clear |
Clear agent-specific account override |
local |
List notebooks in local library |
remote |
List all notebooks from NotebookLM API |
create <name> |
Create a new notebook |
delete [--id ID] |
Delete a notebook |
rename <name> [--id ID] |
Rename a notebook |
summary [--id ID] |
Get AI-generated summary |
describe [--id ID] |
Get description and suggested topics |
add <url-or-id> |
Add notebook to local library (auto-detects URL vs notebook ID) |
activate <id> |
Set active notebook |
Source Management
| Command | Description |
|---|---|
sources [--id ID] |
List sources in notebook |
upload <file> |
Upload a single file |
upload <folder> |
Sync a folder of files to NotebookLM |
upload-zlib <url> |
Download from Z-Library and upload |
upload-url <url> |
Add URL as source |
upload-youtube <url> |
Add YouTube video as source |
upload-text <title> [--content TEXT] |
Add text as source |
source-text <source-id> |
Get full indexed text |
source-guide <source-id> |
Get AI summary and keywords |
source-rename <source-id> <name> |
Rename a source |
source-refresh <source-id> |
Re-fetch URL content |
source-delete <source-id> |
Delete a source |
Upload options:
--use-active- Upload to the currently active notebook--create-new- Create a new notebook named after the file/folder--notebook-id <id>- Upload to a specific notebook--dry-run- Show sync plan without executing (folder sync)--rebuild- Force rebuild tracking file (folder sync)
Important: When user runs upload without specifying a target, ASK them first:
"Would you like to upload to the active notebook, or create a new notebook?" Then pass the appropriate flag (
--use-activeor--create-new).
Chat & Audio/Media
| Command | Description |
|---|---|
ask <question> |
Query NotebookLM |
podcast [--instructions TEXT] |
Generate audio podcast |
podcast-status <task-id> |
Check podcast generation status |
podcast-download [output-path] |
Download latest podcast |
briefing [--instructions TEXT] |
Generate brief audio summary |
debate [--instructions TEXT] |
Generate debate-style audio |
slides [--instructions TEXT] |
Generate slide deck |
slides-download [output-path] |
Download slide deck as PDF |
infographic [--instructions TEXT] |
Generate infographic |
infographic-download [output-path] |
Download infographic |
media-list [--type TYPE] |
List generated media (audio/video/slides/infographic) |
media-delete <id> |
Delete a generated media item |
Command Routing
Based on $ARGUMENTS, execute the appropriate command:
$IF($ARGUMENTS, Parse the command from: "$ARGUMENTS"
login → python scripts/run.py auth_manager.py setup --service google
accounts → python scripts/run.py auth_manager.py accounts list
accounts add → python scripts/run.py auth_manager.py accounts add
accounts switch → python scripts/run.py auth_manager.py accounts switch "<id>"
accounts remove → python scripts/run.py auth_manager.py accounts remove "<id>"
accounts use → python scripts/run.py auth_manager.py accounts use "<id>"
accounts clear → python scripts/run.py auth_manager.py accounts clear
status → Run both:
python scripts/run.py auth_manager.py statuspython scripts/run.py notebook_manager.py list
local → python scripts/run.py notebook_manager.py list
remote → python scripts/run.py nblm_cli.py notebooks
create → python scripts/run.py nblm_cli.py create "<name>"
delete [--id ID] → python scripts/run.py nblm_cli.py delete <args>
rename [--id ID] → python scripts/run.py nblm_cli.py rename "<name>" <args>
summary [--id ID] → python scripts/run.py nblm_cli.py summary <args>
describe [--id ID] → python scripts/run.py nblm_cli.py describe <args>
add → Smart add workflow (auto-detects URL vs notebook ID)
activate → python scripts/run.py notebook_manager.py activate --id "<id>"
sources [--id ID] → python scripts/run.py nblm_cli.py sources <args>
upload → First ASK user: "Upload to active notebook or create new?" Then:
- Active: python scripts/run.py source_manager.py add --file "<file>" --use-active
- New: python scripts/run.py source_manager.py add --file "<file>" --create-new
upload → Sync a folder:
- First ASK user: "Sync to active notebook, create new, or specify notebook?"
- Active: python scripts/run.py source_manager.py sync "<folder>" --use-active
- New: python scripts/run.py source_manager.py sync "<folder>" --create-new
- Specific: python scripts/run.py source_manager.py sync "<folder>" --notebook-id ID
- Dry-run: python scripts/run.py source_manager.py sync "<folder>" --dry-run
- Rebuild: python scripts/run.py source_manager.py sync "<folder>" --rebuild
upload-zlib → First ASK user: "Upload to active notebook or create new?" Then:
- Active: python scripts/run.py source_manager.py add --url "<url>" --use-active
- New: python scripts/run.py source_manager.py add --url "<url>" --create-new
upload-url → python scripts/run.py nblm_cli.py upload-url "<url>"
upload-youtube → python scripts/run.py nblm_cli.py upload-youtube "<url>"
upload-text