Skip to content

feat(auth): add logout command and --fresh flag for login#288

Open
MCR-GLOBAL wants to merge 1 commit intoteng-lin:mainfrom
MCR-GLOBAL:fix/auth-fresh-login-246
Open

feat(auth): add logout command and --fresh flag for login#288
MCR-GLOBAL wants to merge 1 commit intoteng-lin:mainfrom
MCR-GLOBAL:fix/auth-fresh-login-246

Conversation

@MCR-GLOBAL
Copy link
Copy Markdown

@MCR-GLOBAL MCR-GLOBAL commented Apr 15, 2026

Summary

Usage

# Switch accounts: logout then login
notebooklm auth logout
notebooklm login

# Or use --fresh to clear and login in one step
notebooklm login --fresh

Test plan

  • Lint, format, type check all pass
  • Full test suite: 2013 passed, 9 skipped
  • notebooklm login --help shows --fresh flag
  • notebooklm auth logout --help shows correct usage
  • Manual: notebooklm login --fresh allows switching to a different Google account

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added --fresh flag to login command to reset cached browser profile and authentication state before logging in
    • Added auth logout command to clear all authentication and cached browser data

Users couldn't switch Google accounts because the cached browser profile
at ~/.notebooklm/browser_profile/ retained session cookies from the
previous account.

- Add `notebooklm auth logout` command that clears both storage_state.json
  and the browser profile directory
- Add `notebooklm login --fresh` flag that clears the cached browser
  profile before opening the login browser, allowing account switching

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 15, 2026

📝 Walkthrough

Walkthrough

Extended the login CLI command with a --fresh flag that removes cached browser profile and authentication state files before initiating login. Added a new auth logout command to clear stored authentication and browser cache, addressing the inability to switch Google accounts.

Changes

Cohort / File(s) Summary
Authentication Session Management
src/notebooklm/cli/session.py
Added --fresh flag to login command that deletes browser profile directory and auth state file before login. Introduced new auth logout command that removes cached authentication state and browser profile, with conditional messaging for success or already-logged-out state.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Hops with glee, account to account,
No more sticky sessions, what a triumph!
Fresh logins and logouts, clean as morning dew,
Switch those Google accounts—finally true!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: adding a logout command and a --fresh flag to the login command for authentication management.
Linked Issues check ✅ Passed The PR implements both solutions from issue #246: adds notebooklm auth logout command to clear storage and browser profile, and adds --fresh flag to login for switching accounts.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #246: the new logout command and --fresh flag for login functionality, with no unrelated modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a --fresh flag to the login command and adds a new logout command to manage authentication state by clearing cached browser profiles and saved auth files. The review feedback suggests also clearing the local notebook context in both scenarios to prevent stale state when switching accounts or logging out, and recommends adding error handling for file operations to handle locked files gracefully.

Comment on lines +410 to +418
if fresh:
import shutil

if browser_profile.exists():
shutil.rmtree(browser_profile)
console.print("[yellow]Cleared cached browser profile.[/yellow]")
if storage_path.exists():
storage_path.unlink()
console.print("[yellow]Cleared saved auth state.[/yellow]")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

When performing a --fresh login, it is important to also clear the current notebook context. Since this flag is intended for switching accounts, any previously selected notebook ID in context.json will likely be invalid for the new account. Additionally, wrapping these file operations in a try-except block prevents the command from crashing if files are locked (e.g., by an active browser process), allowing for a more graceful warning.

Suggested change
if fresh:
import shutil
if browser_profile.exists():
shutil.rmtree(browser_profile)
console.print("[yellow]Cleared cached browser profile.[/yellow]")
if storage_path.exists():
storage_path.unlink()
console.print("[yellow]Cleared saved auth state.[/yellow]")
if fresh:
import shutil
try:
if browser_profile.exists():
shutil.rmtree(browser_profile)
console.print("[yellow]Cleared cached browser profile.[/yellow]")
if storage_path.exists():
storage_path.unlink()
console.print("[yellow]Cleared saved auth state.[/yellow]")
clear_context()
except OSError as e:
console.print(f"[yellow]Warning: Could not fully clear profile: {e}[/yellow]")

Comment on lines +983 to +991
cleared = False
if storage_path.exists():
storage_path.unlink()
console.print("[green]Removed auth state.[/green]")
cleared = True
if browser_profile.exists():
shutil.rmtree(browser_profile)
console.print("[green]Removed cached browser profile.[/green]")
cleared = True
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logout command should also clear the local notebook context (context.json) to prevent stale state issues after the user is unauthenticated. Furthermore, adding error handling for the file operations ensures the command doesn't terminate abruptly if the browser profile directory is locked by another process.

Suggested change
cleared = False
if storage_path.exists():
storage_path.unlink()
console.print("[green]Removed auth state.[/green]")
cleared = True
if browser_profile.exists():
shutil.rmtree(browser_profile)
console.print("[green]Removed cached browser profile.[/green]")
cleared = True
cleared = False
try:
if storage_path.exists():
storage_path.unlink()
console.print("[green]Removed auth state.[/green]")
cleared = True
if browser_profile.exists():
shutil.rmtree(browser_profile)
console.print("[green]Removed cached browser profile.[/green]")
cleared = True
if get_context_path().exists():
clear_context()
cleared = True
except OSError as e:
console.print(f"[red]Error during logout:[/red] {e}")
raise SystemExit(1)

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/notebooklm/cli/session.py`:
- Around line 409-418: The current fresh-login branch deletes the existing
storage_state.json before the new login is confirmed; keep clearing the
browser_profile to force account selection but do NOT unlink storage_path (the
current auth file) here. Instead, remove the storage_path.unlink() call from the
fresh block and move the deletion/write responsibility to the successful
login/Playwright startup path (the code that creates/writes storage_state.json)
so that storage_path is only replaced after Playwright/Chromium launches and
login succeeds. Identify the variables browser_profile, storage_path and the
fresh branch to make this change.
- Around line 970-997: The auth_logout command (function auth_logout) can
misleadingly report success when NOTEBOOKLM_AUTH_JSON is set because subsequent
commands will still use the env-provided auth; update auth_logout to detect
os.environ.get("NOTEBOOKLM_AUTH_JSON") (or equivalent env access) before
removing storage_state.json (via get_storage_path()) and browser profile (via
get_browser_profile_dir()) and if the env var is set, refuse to proceed (exit
the command) or print an explicit, prominent message telling the user to unset
NOTEBOOKLM_AUTH_JSON first (and how to do so) instead of reporting logout
success; ensure the branch that checks the env var runs before any filesystem
removal and that the console message clearly instructs to unset the variable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 745363fe-9252-4410-b2ef-38fd7b80fc3f

📥 Commits

Reviewing files that changed from the base of the PR and between a997718 and d4d5ced.

📒 Files selected for processing (1)
  • src/notebooklm/cli/session.py

Comment on lines +409 to +418
# Clear cached browser profile to allow switching Google accounts
if fresh:
import shutil

if browser_profile.exists():
shutil.rmtree(browser_profile)
console.print("[yellow]Cleared cached browser profile.[/yellow]")
if storage_path.exists():
storage_path.unlink()
console.print("[yellow]Cleared saved auth state.[/yellow]")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don't delete the current auth file before a replacement exists.

Line 416 logs the user out before the fresh login flow has even verified that Playwright/Chromium can start. If import, install, or browser launch fails, notebooklm login --fresh leaves a previously working session unusable. Clearing the cached browser profile is enough to force account selection; let the new storage_state.json be written only after login succeeds.

Suggested fix
         # Clear cached browser profile to allow switching Google accounts
         if fresh:
             import shutil

             if browser_profile.exists():
                 shutil.rmtree(browser_profile)
                 console.print("[yellow]Cleared cached browser profile.[/yellow]")
-            if storage_path.exists():
-                storage_path.unlink()
-                console.print("[yellow]Cleared saved auth state.[/yellow]")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/notebooklm/cli/session.py` around lines 409 - 418, The current
fresh-login branch deletes the existing storage_state.json before the new login
is confirmed; keep clearing the browser_profile to force account selection but
do NOT unlink storage_path (the current auth file) here. Instead, remove the
storage_path.unlink() call from the fresh block and move the deletion/write
responsibility to the successful login/Playwright startup path (the code that
creates/writes storage_state.json) so that storage_path is only replaced after
Playwright/Chromium launches and login succeeds. Identify the variables
browser_profile, storage_path and the fresh branch to make this change.

Comment on lines +970 to +997
@auth_group.command("logout")
def auth_logout():
"""Log out by clearing saved auth state and browser profile.

Removes the storage_state.json and the cached browser profile
for the current profile. After logout, run 'notebooklm login'
to authenticate with a different account.
"""
import shutil

storage_path = get_storage_path()
browser_profile = get_browser_profile_dir()

cleared = False
if storage_path.exists():
storage_path.unlink()
console.print("[green]Removed auth state.[/green]")
cleared = True
if browser_profile.exists():
shutil.rmtree(browser_profile)
console.print("[green]Removed cached browser profile.[/green]")
cleared = True

if cleared:
console.print("\n[green]Logged out successfully.[/green]")
console.print("[dim]Run 'notebooklm login' to sign in again.[/dim]")
else:
console.print("[yellow]No auth state found — already logged out.[/yellow]")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

auth logout is misleading when NOTEBOOKLM_AUTH_JSON is set.

This file already treats NOTEBOOKLM_AUTH_JSON as an active auth source, so this command can report success while later commands still authenticate via the environment variable. Refuse the command or emit an explicit instruction to unset the env var first.

Suggested fix
     `@auth_group.command`("logout")
     def auth_logout():
         """Log out by clearing saved auth state and browser profile.
@@
         to authenticate with a different account.
         """
         import shutil
+
+        if os.environ.get("NOTEBOOKLM_AUTH_JSON"):
+            console.print(
+                "[red]Error: Cannot log out while NOTEBOOKLM_AUTH_JSON is set.[/red]\n"
+                "Unset NOTEBOOKLM_AUTH_JSON to remove inline authentication."
+            )
+            raise SystemExit(1)

         storage_path = get_storage_path()
         browser_profile = get_browser_profile_dir()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/notebooklm/cli/session.py` around lines 970 - 997, The auth_logout
command (function auth_logout) can misleadingly report success when
NOTEBOOKLM_AUTH_JSON is set because subsequent commands will still use the
env-provided auth; update auth_logout to detect
os.environ.get("NOTEBOOKLM_AUTH_JSON") (or equivalent env access) before
removing storage_state.json (via get_storage_path()) and browser profile (via
get_browser_profile_dir()) and if the env var is set, refuse to proceed (exit
the command) or print an explicit, prominent message telling the user to unset
NOTEBOOKLM_AUTH_JSON first (and how to do so) instead of reporting logout
success; ensure the branch that checks the env var runs before any filesystem
removal and that the console message clearly instructs to unset the variable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cannot switch Google accounts: login reuses cached browser profile + crashes on new account

1 participant