Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Query Google NotebookLM notebooks from Claude Code for source-grounded, citation-backed answers from Gemini.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/cleanup_manager.py
1#!/usr/bin/env python32"""3Cleanup Manager for NotebookLM Skill4Manages cleanup of skill data and browser state5"""67import shutil8import argparse9from pathlib import Path10from typing import Dict, List, Any111213class CleanupManager:14"""15Manages cleanup of NotebookLM skill data1617Features:18- Preview what will be deleted19- Selective cleanup options20- Library preservation21- Safe deletion with confirmation22"""2324def __init__(self):25"""Initialize the cleanup manager"""26# Skill directory paths27self.skill_dir = Path(__file__).parent.parent28self.data_dir = self.skill_dir / "data"2930def get_cleanup_paths(self, preserve_library: bool = False) -> Dict[str, Any]:31"""32Get paths that would be cleaned up3334Args:35preserve_library: Keep library.json if True3637Returns:38Dict with paths and sizes3940Note: .venv is NEVER deleted - it's part of the skill infrastructure41"""42paths = {43'browser_state': [],44'sessions': [],45'library': [],46'auth': [],47'other': []48}4950total_size = 05152if self.data_dir.exists():53# Browser state54browser_state_dir = self.data_dir / "browser_state"55if browser_state_dir.exists():56for item in browser_state_dir.iterdir():57size = self._get_size(item)58paths['browser_state'].append({59'path': str(item),60'size': size,61'type': 'dir' if item.is_dir() else 'file'62})63total_size += size6465# Sessions66sessions_file = self.data_dir / "sessions.json"67if sessions_file.exists():68size = sessions_file.stat().st_size69paths['sessions'].append({70'path': str(sessions_file),71'size': size,72'type': 'file'73})74total_size += size7576# Library (unless preserved)77if not preserve_library:78library_file = self.data_dir / "library.json"79if library_file.exists():80size = library_file.stat().st_size81paths['library'].append({82'path': str(library_file),83'size': size,84'type': 'file'85})86total_size += size8788# Auth info89auth_info = self.data_dir / "auth_info.json"90if auth_info.exists():91size = auth_info.stat().st_size92paths['auth'].append({93'path': str(auth_info),94'size': size,95'type': 'file'96})97total_size += size9899# Other files in data dir (but NEVER .venv!)100for item in self.data_dir.iterdir():101if item.name not in ['browser_state', 'sessions.json', 'library.json', 'auth_info.json']:102size = self._get_size(item)103paths['other'].append({104'path': str(item),105'size': size,106'type': 'dir' if item.is_dir() else 'file'107})108total_size += size109110return {111'categories': paths,112'total_size': total_size,113'total_items': sum(len(items) for items in paths.values())114}115116def _get_size(self, path: Path) -> int:117"""Get size of file or directory in bytes"""118if path.is_file():119return path.stat().st_size120elif path.is_dir():121total = 0122try:123for item in path.rglob('*'):124if item.is_file():125total += item.stat().st_size126except Exception:127pass128return total129return 0130131def _format_size(self, size: int) -> str:132"""Format size in human-readable form"""133for unit in ['B', 'KB', 'MB', 'GB']:134if size < 1024:135return f"{size:.1f} {unit}"136size /= 1024137return f"{size:.1f} TB"138139def perform_cleanup(140self,141preserve_library: bool = False,142dry_run: bool = False143) -> Dict[str, Any]:144"""145Perform the actual cleanup146147Args:148preserve_library: Keep library.json if True149dry_run: Preview only, don't delete150151Returns:152Dict with cleanup results153"""154cleanup_data = self.get_cleanup_paths(preserve_library)155deleted_items = []156failed_items = []157deleted_size = 0158159if dry_run:160return {161'dry_run': True,162'would_delete': cleanup_data['total_items'],163'would_free': cleanup_data['total_size']164}165166# Perform deletion167for category, items in cleanup_data['categories'].items():168for item_info in items:169path = Path(item_info['path'])170try:171if path.exists():172if path.is_dir():173shutil.rmtree(path)174else:175path.unlink()176deleted_items.append(str(path))177deleted_size += item_info['size']178print(f" โ Deleted: {path.name}")179except Exception as e:180failed_items.append({181'path': str(path),182'error': str(e)183})184print(f" โ Failed: {path.name} ({e})")185186# Recreate browser_state dir if everything was deleted187if not preserve_library and not failed_items:188browser_state_dir = self.data_dir / "browser_state"189browser_state_dir.mkdir(parents=True, exist_ok=True)190191return {192'deleted_items': deleted_items,193'failed_items': failed_items,194'deleted_size': deleted_size,195'deleted_count': len(deleted_items),196'failed_count': len(failed_items)197}198199def print_cleanup_preview(self, preserve_library: bool = False):200"""Print a preview of what will be cleaned"""201data = self.get_cleanup_paths(preserve_library)202203print("\n๐ Cleanup Preview")204print("=" * 60)205206for category, items in data['categories'].items():207if items:208print(f"\n๐ {category.replace('_', ' ').title()}:")209for item in items:210path = Path(item['path'])211size_str = self._format_size(item['size'])212type_icon = "๐" if item['type'] == 'dir' else "๐"213print(f" {type_icon} {path.name:<30} {size_str:>10}")214215print("\n" + "=" * 60)216print(f"Total items: {data['total_items']}")217print(f"Total size: {self._format_size(data['total_size'])}")218219if preserve_library:220print("\n๐ Library will be preserved")221222print("\nThis preview shows what would be deleted.")223print("Use --confirm to actually perform the cleanup.")224225226def main():227"""Command-line interface for cleanup management"""228parser = argparse.ArgumentParser(229description='Clean up NotebookLM skill data',230formatter_class=argparse.RawDescriptionHelpFormatter,231epilog="""232Examples:233# Preview what will be deleted234python cleanup_manager.py235236# Perform cleanup (delete everything)237python cleanup_manager.py --confirm238239# Cleanup but keep library240python cleanup_manager.py --confirm --preserve-library241242# Force cleanup without preview243python cleanup_manager.py --confirm --force244"""245)246247parser.add_argument(248'--confirm',249action='store_true',250help='Actually perform the cleanup (without this, only preview)'251)252253parser.add_argument(254'--preserve-library',255action='store_true',256help='Keep the notebook library (library.json)'257)258259parser.add_argument(260'--force',261action='store_true',262help='Skip confirmation prompt'263)264265args = parser.parse_args()266267# Initialize manager268manager = CleanupManager()269270if args.confirm:271# Show preview first unless forced272if not args.force:273manager.print_cleanup_preview(args.preserve_library)274275print("\nโ ๏ธ WARNING: This will delete the files shown above!")276print(" Note: .venv is preserved (part of skill infrastructure)")277response = input("Are you sure? (yes/no): ")278279if response.lower() != 'yes':280print("Cleanup cancelled.")281return282283# Perform cleanup284print("\n๐๏ธ Performing cleanup...")285result = manager.perform_cleanup(args.preserve_library, dry_run=False)286287print(f"\nโ Cleanup complete!")288print(f" Deleted: {result['deleted_count']} items")289print(f" Freed: {manager._format_size(result['deleted_size'])}")290291if result['failed_count'] > 0:292print(f" โ ๏ธ Failed: {result['failed_count']} items")293294else:295# Just show preview296manager.print_cleanup_preview(args.preserve_library)297print("\n๐ก Note: Virtual environment (.venv) is never deleted")298print(" It's part of the skill infrastructure, not user data")299300301if __name__ == "__main__":302main()