feat(note): add --json flag to note list command#259
feat(note): add --json flag to note list command#259Flosters wants to merge 1 commit intoteng-lin:mainfrom
Conversation
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.
📝 WalkthroughWalkthroughAdded a Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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.
| 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 |
There was a problem hiding this comment.
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]")
returnReferences
- 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.
There was a problem hiding this comment.
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
📒 Files selected for processing (1)
src/notebooklm/cli/note.py
| 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) | ||
| ]) |
There was a problem hiding this comment.
Type mismatch and inconsistent JSON output structure.
Two issues here:
-
Type error:
json_output_responseis typed asjson_output_response(data: dict) -> None(seehelpers.py:540), but you're passing a list. This will fail mypy type checking. -
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}).
Summary
notebooklm note listwas the only list command in the CLI without a--jsonflag, making it impossible to parse notes programmatically.This PR adds
--jsontonote list, consistent withsource list,artifact list,notebook list, and every other list command.Output format:
Changes
cli/note.py: add--json/json_outputflag tonote list[]as JSON when no notes exist[{id, title, preview}]array for each noteno_wrap=Trueon the ID column in table view (UUIDs wrap badly in narrow terminals)Test plan
notebooklm note list --jsonreturns valid JSON arraynotebooklm note list --jsonon empty notebook returns[]notebooklm note list(no flag) still renders the rich table unchangedSummary by CodeRabbit
--jsonflag to thenote listcommand for JSON-formatted output instead of table format.