Skip to content

feat(note): add --json flag to note list command#259

Open
Flosters wants to merge 1 commit intoteng-lin:mainfrom
Flosters:feat/note-list-json
Open

feat(note): add --json flag to note list command#259
Flosters wants to merge 1 commit intoteng-lin:mainfrom
Flosters:feat/note-list-json

Conversation

@Flosters
Copy link
Copy Markdown

@Flosters Flosters commented Apr 9, 2026

Summary

notebooklm note list was the only list command in the CLI without a --json flag, making it impossible to parse notes programmatically.

This PR adds --json to note list, consistent with source list, artifact list, notebook list, and every other list command.

Output format:

$ notebooklm note list --json
[{"id": "...", "title": "...", "preview": "first 100 chars of content"}]

Changes

  • cli/note.py: add --json / json_output flag to note list
    • Returns [] as JSON when no notes exist
    • Returns [{id, title, preview}] array for each note
    • Sets no_wrap=True on the ID column in table view (UUIDs wrap badly in narrow terminals)

Test plan

  • notebooklm note list --json returns valid JSON array
  • notebooklm note list --json on empty notebook returns []
  • notebooklm note list (no flag) still renders the rich table unchanged
  • ID column no longer wraps in narrow terminals

Summary by CodeRabbit

  • New Features
    • Added --json flag to the note list command for JSON-formatted output instead of table format.
    • When using the flag and no notes are found, an empty JSON list is returned.
    • Improved readability of the ID column in the default table output.

Adds machine-readable JSON output to `notebooklm note list`, consistent
with every other list command in the CLI (source list, artifact list,
notebook list, etc.).

Output format:
  [{"id": "...", "title": "...", "preview": "first 100 chars..."}]

Also sets no_wrap=True on the ID column in the table view so UUIDs
do not wrap in narrow terminals.

Closes the only list command missing --json support.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

📝 Walkthrough

Walkthrough

Added a --json flag to the note list command that conditionally outputs JSON instead of a Rich table. The note_list function now accepts a json_output parameter to control output format, with empty list emission when no notes exist. The "ID" column in the table renderer was set to no_wrap=True.

Changes

Cohort / File(s) Summary
JSON Output Flag for Note List
src/notebooklm/cli/note.py
Added --json CLI option and json_output parameter to note_list function. Implemented conditional output: JSON response when flag is set, Rich table when unset. Updated table rendering with no_wrap=True for ID column.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A flag named JSON hops into view,
Tables transform to data true,
No notes? Just brackets, empty and neat,
Command-line magic, crisp and sweet! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and clearly describes the main change: adding a --json flag to the note list command, which is the primary focus of the changeset.

✏️ 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 --json flag to the note_list command, enabling JSON-formatted output for notes, and updates the table display to prevent ID wrapping. The review feedback recommends simplifying the JSON output logic to eliminate redundant checks and local imports, while also suggesting a more consistent relative import path.

Comment on lines 65 to 80
if not notes:
console.print("[yellow]No notes found[/yellow]")
if json_output:
from ..cli.helpers import json_output_response
json_output_response([])
else:
console.print("[yellow]No notes found[/yellow]")
return

if json_output:
from ..cli.helpers import json_output_response
json_output_response([
{"id": n.id, "title": n.title or "", "preview": (n.content or "")[:100]}
for n in notes
if isinstance(n, Note)
])
return
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 JSON output logic can be simplified by merging the empty check and the main output block. Since the list comprehension naturally results in an empty list if notes is empty, both cases can be handled in a single block. This avoids redundant checks and repeated local imports. Additionally, using the relative import .helpers is more consistent with the existing imports in this file than ..cli.helpers. When outputting JSON for human consumption, ensure the implementation uses ensure_ascii=False to maintain readability of UTF-8 characters.

            if json_output:
                from .helpers import json_output_response
                json_output_response([
                    {"id": n.id, "title": n.title or "", "preview": (n.content or "")[:100]}
                    for n in notes
                    if isinstance(n, Note)
                ])
                return

            if not notes:
                console.print("[yellow]No notes found[/yellow]")
                return
References
  1. When writing JSON files that may be human-read, use json.dumps(..., ensure_ascii=False) to improve readability by writing UTF-8 characters directly instead of as escape sequences.

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: 1

🤖 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/note.py`:
- Around line 66-79: The JSON output branch must return a dict (not a raw list)
to match other list commands and the json_output_response signature: move the
import of json_output_response to the module top-level imports, then change both
places that call json_output_response to pass a dict like {"notes": [...],
"count": len(notes)} where the list is built from the notes iterable (keeping
the existing comprehension that filters by isinstance(n, Note) and maps to
{"id": n.id, "title": n.title or "", "preview": (n.content or "")[:100]}), and
when there are no notes call json_output_response({"notes": [], "count": 0}).
🪄 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: 0f2124b8-525f-4f82-8ecc-e6ced5f954e1

📥 Commits

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

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

Comment on lines +66 to +79
if json_output:
from ..cli.helpers import json_output_response
json_output_response([])
else:
console.print("[yellow]No notes found[/yellow]")
return

if json_output:
from ..cli.helpers import json_output_response
json_output_response([
{"id": n.id, "title": n.title or "", "preview": (n.content or "")[:100]}
for n in notes
if isinstance(n, Note)
])
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

Type mismatch and inconsistent JSON output structure.

Two issues here:

  1. Type error: json_output_response is typed as json_output_response(data: dict) -> None (see helpers.py:540), but you're passing a list. This will fail mypy type checking.

  2. Inconsistent output format: Other list commands (notebook list, source list) wrap their output in a dict structure like {"notes": [...], "count": N}. This command returns a raw list, which is inconsistent with the established pattern.

Additionally, the import should be at the top of the file with other helpers rather than duplicated inside the function.

Proposed fix to match sibling list commands

First, add json_output_response to the imports at the top of the file:

 from .helpers import (
     console,
+    json_output_response,
     require_notebook,
     resolve_note_id,
     resolve_notebook_id,
     with_client,
 )

Then update the JSON output logic:

             if not notes:
                 if json_output:
-                    from ..cli.helpers import json_output_response
-                    json_output_response([])
+                    json_output_response({"notes": [], "count": 0})
                 else:
                     console.print("[yellow]No notes found[/yellow]")
                 return

             if json_output:
-                from ..cli.helpers import json_output_response
-                json_output_response([
-                    {"id": n.id, "title": n.title or "", "preview": (n.content or "")[:100]}
-                    for n in notes
-                    if isinstance(n, Note)
-                ])
+                data = {
+                    "notebook_id": nb_id_resolved,
+                    "notes": [
+                        {"id": n.id, "title": n.title or "", "preview": (n.content or "")[:100]}
+                        for n in notes
+                        if isinstance(n, Note)
+                    ],
+                    "count": len([n for n in notes if isinstance(n, Note)]),
+                }
+                json_output_response(data)
                 return
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/notebooklm/cli/note.py` around lines 66 - 79, The JSON output branch must
return a dict (not a raw list) to match other list commands and the
json_output_response signature: move the import of json_output_response to the
module top-level imports, then change both places that call json_output_response
to pass a dict like {"notes": [...], "count": len(notes)} where the list is
built from the notes iterable (keeping the existing comprehension that filters
by isinstance(n, Note) and maps to {"id": n.id, "title": n.title or "",
"preview": (n.content or "")[:100]}), and when there are no notes call
json_output_response({"notes": [], "count": 0}).

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.

1 participant