feat: add Notes and Reminders CLI commands#212
Conversation
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 14 minutes and 28 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThis pull request adds comprehensive CLI support for Apple iCloud Notes and Reminders services. It introduces Typer-based command modules for Notes ( Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~65 minutes Possibly related PRs
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.
Actionable comments posted: 1
🧹 Nitpick comments (3)
pyicloud/cli/normalize.py (1)
235-237: Cap the recents search window to avoid oversized queries.
window = max(500, limit * 50)grows linearly with user input; very large--limitvalues can trigger heavy remote queries and high memory use. Add an upper bound.Proposed refactor
- window = max(500, limit * 50) + window = min(max(500, limit * 50), 5_000)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pyicloud/cli/normalize.py` around lines 235 - 237, The recents search window currently uses window = max(500, limit * 50) which can grow unbounded; change it to cap the value with an upper bound (e.g., window = min(MAX_WINDOW, max(500, limit * 50))) and define a sensible constant MAX_WINDOW (for example 5000 or 10000) near the top of the module or function; ensure notes_service.recents(limit=window) uses this capped window to prevent oversized remote queries and memory spikes.tests/test_cmdline.py (1)
286-300: Intentional duplicate for deduplication testing is clear from test usage.Line 299 includes
self.recent_rows[2](Note/MEETING) twice inall_rows. This is intentional to verify the search deduplication logic intest_notes_search_uses_recents_first_and_fallback. Consider adding a brief inline comment to make this intention explicit for future maintainers.📝 Optional: Add clarifying comment
self.all_rows = [ self.recent_rows[2], NoteSummary( id="Note/FOLLOWUP", title="Meeting Follow-up", snippet="Send recap", modified_at=datetime(2026, 3, 2, tzinfo=timezone.utc), folder_id="Folder/WORK", folder_name="Work", is_deleted=False, is_locked=False, ), self.recent_rows[1], + # Duplicate entry to verify deduplication in search_notes_by_title self.recent_rows[2], ]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_cmdline.py` around lines 286 - 300, Add a brief inline comment next to the duplicate entry in self.all_rows clarifying that the repeated self.recent_rows[2] (Note/MEETING) is intentional for deduplication testing; update the list where self.all_rows is constructed to comment on the deliberate duplicate used by test_notes_search_uses_recents_first_and_fallback so future maintainers understand the purpose.pyicloud/cli/commands/reminders.py (1)
131-139: Catch RemindersAuthError and RemindersApiError exceptions.The reminders service raises
RemindersAuthErrorandRemindersApiError(frompyicloud/services/reminders/client.py), but_reminders_callonly catchesLookupErrorandValidationError. These exceptions should be caught and converted toCLIAbortto match the wrapper's intended purpose of providing reminder-specific user-facing errors.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pyicloud/cli/commands/reminders.py` around lines 131 - 139, The _reminders_call wrapper currently only handles LookupError and ValidationError but must also catch RemindersAuthError and RemindersApiError raised by the reminders service; update the exception handling in _reminders_call (function name: _reminders_call) to import and catch RemindersAuthError and RemindersApiError (from pyicloud.services.reminders.client) and convert them to CLIAbort the same way as the other exceptions (raise CLIAbort(str(err)) from err) while preserving the existing catches.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@README.md`:
- Line 1322: Update the README line that currently reads "_List recent notes,
folders, or one folder’s notes:_" to the clearer wording "_List recent notes,
folders, or notes in one folder:_"; locate the exact string in the README (the
line starting with "List recent notes, folders, or") and replace the possessive
phrasing "one folder’s notes" with "notes in one folder" to improve readability.
---
Nitpick comments:
In `@pyicloud/cli/commands/reminders.py`:
- Around line 131-139: The _reminders_call wrapper currently only handles
LookupError and ValidationError but must also catch RemindersAuthError and
RemindersApiError raised by the reminders service; update the exception handling
in _reminders_call (function name: _reminders_call) to import and catch
RemindersAuthError and RemindersApiError (from
pyicloud.services.reminders.client) and convert them to CLIAbort the same way as
the other exceptions (raise CLIAbort(str(err)) from err) while preserving the
existing catches.
In `@pyicloud/cli/normalize.py`:
- Around line 235-237: The recents search window currently uses window =
max(500, limit * 50) which can grow unbounded; change it to cap the value with
an upper bound (e.g., window = min(MAX_WINDOW, max(500, limit * 50))) and define
a sensible constant MAX_WINDOW (for example 5000 or 10000) near the top of the
module or function; ensure notes_service.recents(limit=window) uses this capped
window to prevent oversized remote queries and memory spikes.
In `@tests/test_cmdline.py`:
- Around line 286-300: Add a brief inline comment next to the duplicate entry in
self.all_rows clarifying that the repeated self.recent_rows[2] (Note/MEETING) is
intentional for deduplication testing; update the list where self.all_rows is
constructed to comment on the deliberate duplicate used by
test_notes_search_uses_recents_first_and_fallback so future maintainers
understand the purpose.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f051ecd1-c3ff-4756-827e-ab0d6be63eba
📒 Files selected for processing (17)
README.mdpyicloud/cli/app.pypyicloud/cli/commands/notes.pypyicloud/cli/commands/reminders.pypyicloud/cli/normalize.pypyicloud/cli/output.pypyicloud/services/notes/service.pypyicloud/services/reminders/_mappers.pypyicloud/services/reminders/_protocol.pypyicloud/services/reminders/_reads.pypyicloud/services/reminders/_writes.pypyicloud/services/reminders/client.pypyicloud/services/reminders/service.pytests/services/test_reminders_cloudkit.pytests/test_cmdline.pytests/test_notes.pytests/test_output.py
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
README.md (1)
1322-1322:⚠️ Potential issue | 🟡 MinorUse clearer phrasing: “notes in one folder”.
“one folder’s notes” reads awkwardly here; “notes in one folder” is clearer.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@README.md` at line 1322, Replace the phrase "one folder’s notes" with the clearer wording "notes in one folder" in the README heading/text that currently reads "_List recent notes, folders, or one folder’s notes:_", so it becomes "_List recent notes, folders, or notes in one folder:_; update any identical occurrences of "one folder’s notes" elsewhere in the file to maintain consistent phrasing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@README.md`:
- Around line 1319-1320: The top-level subcommands list in the README is missing
the new namespaces; update that earlier "top-level subcommands" section to
include the `notes` and `reminders` entries so it matches the later
documentation (which describes `icloud notes ...`); locate the list of top-level
commands and add `notes` and `reminders` alongside the other subcommands to keep
the README consistent and avoid confusing first-time users.
---
Duplicate comments:
In `@README.md`:
- Line 1322: Replace the phrase "one folder’s notes" with the clearer wording
"notes in one folder" in the README heading/text that currently reads "_List
recent notes, folders, or one folder’s notes:_", so it becomes "_List recent
notes, folders, or notes in one folder:_; update any identical occurrences of
"one folder’s notes" elsewhere in the file to maintain consistent phrasing.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
Signed-off-by: Tim Laing <11019084+timlaing@users.noreply.github.com>
Co-authored-by: Tim Laing <11019084+timlaing@users.noreply.github.com>
* feat: handle Apple's HSA2 trusted-device prompts * Trim unrelated Notes PR scope * Address CodeRabbit review comments * Add docstrings for auth bridge PR scope * Harden bridge prover and persistence tests
…#208) Updates the requirements on [protobuf](https://github.com/protocolbuffers/protobuf) to permit the latest version. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Commits](https://github.com/protocolbuffers/protobuf/commits) --- updated-dependencies: - dependency-name: protobuf dependency-version: 7.34.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.34.1 to 4.35.1. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@3869755...c10b806) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.35.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: Tim Laing <11019084+timlaing@users.noreply.github.com>
|
@MrJarnould - thanks |
Breaking change
Proposed change
This PR adds first-class CLI support for the existing Notes and Reminders services.
For Notes, it adds commands to inspect and export data, including:
notes recentnotes foldersnotes listnotes searchnotes getnotes rendernotes exportnotes changesnotes sync-cursorFor Reminders, it adds commands for both read and write flows, including:
reminders listsreminders listreminders getreminders createreminders updatereminders set-statusreminders deletereminders snapshotreminders changesreminders sync-cursorIt also adds subcommand groups for reminder alarms, hashtags, attachments, and recurrence rules.
While smoke-testing the new CLI against a live iCloud session, I fixed a few service-level issues that affected the new commands:
notes list --all --since <current-cursor>now short-circuits instead of scanning changes when the cursor is already currentreminders sync-cursornow uses a cheap current-token path before falling back to the full changes feedCount=0This PR also adds normalization/output helpers and targeted tests for the new command groups and the service fixes they rely on.
Type of change
Example of code:
icloud notes recent --limit 5 icloud notes get NOTE_ID --format json icloud reminders lists --format json icloud reminders create --list-id LIST_ID --title "Buy milk"Additional information
pytest tests/test_cmdline.py tests/test_output.py tests/test_notes.py tests/services/test_reminders_cloudkit.py -qruff checkon the touched CLI and service files102passes,1intentional skip for image-only attachment metadata creation)Checklist
If user exposed functionality or configuration variables are added/changed: