You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Added
gcal models list and gcal models download <model> fetch the model that search by meaning uses. The search's
hint named gcal models download e5-small, which did not exist. The model goes into the folder every WireCat tool
shares, so one already downloaded by another WireCat tool is used as it is.
events move <event> --to-calendar <id> moves an event, with its id, to another calendar of the same account.
It refuses a calendar you cannot write to, the same calendar, an event Google does not move (focus time, out of
office, working location, birthdays) and an occurrence without --series. Over MCP it is the events move command.
events update --following and events delete --following change or delete "this and all following"
occurrences. An update ends the series just before the occurrence and starts a new series there with the change,
keeping the attendees; a delete only ends the series. A series that ends after a number of times needs --repeat
for the new part.
events list changed:<date> lists what changed since a date, from the store: each event says change (new, moved or cancelled) and changed_at, and a moved one where it was.
events list overlapping lists the meetings that clash, each with overlaps, the other events. Only events that
take your time count: not cancelled, not all-day, not declined or marked free.
Changed — may break callers
Creating, changing, moving and answering events go ahead without a question by default.events.create, events.update, events.respond and the new events.move are allow (were ask); a script no longer needs --yes
for them. events.delete stays ask, --following included. To be asked again, set a key to ask, such as gcal personal config set permissions.events.create ask. The api.calendar.events.* keys stop the event writes
once you set them; their built-in ask holds for the api commands only.
A series update whose new rule ends it sooner also needs events.delete.series, which is deny by default. A
new COUNT, an earlier UNTIL, or a bound on a series that had none removed the later occurrences under events.update alone.
A sync where a calendar fails prints nothing on stdout and fails with sync.partial. Its message names each
failed calendar and its error, details.calendars holds every calendar's result (error on the failed ones), and
the error says a retry is safe. The calendars that synced are saved. A sync stopped by its time or request budget
still answers state: "partial" and succeeds.
search answers a list: the events under items, with page in cursor mode, as every other list does. It
answered one item holding hits, has_more and untrusted (WC-OUT-4). A script reads items in place of item.hits, and page.next_cursor is the value for --cursor. Each event names its own untrusted fields, and why
meaning was not searched is under missing. query and by are gone; each event still says found_by.
links review answers its reviews under items, without accounts: "all". It answered one item holding the
list. Link choices are still kept per store, so every account's reviews are listed.
search --backend server refuses --newest. Google returns its matches in no stated order and gcal reads only
the first page of each calendar, so the newest event could be missing from a "newest first" answer. Its matches
are listed earliest first, and each event's found_by is ["google"], as a store search writes it.
Fixed
gcal --help no longer offers a --read-only option, which does not exist.GCAL_READ_ONLY=1 is how a run
refuses every change.
events delete of an event already deleted at Google succeeds and removes the stored copy. Google answers such a
delete with 410, and 404 once it no longer shows the event; gcal failed on both and kept the event in the store
until the next sync.
The daily full sync no longer marks events outside its window as deleted. Older and later single events, moved
occurrences and ended series were marked deleted and their events cancelled. A store this damaged heals on its next
sync.
A repeating event moved to another time no longer keeps its occurrences at the old time after an incremental
sync.
A sync --rescan stopped by its budget no longer leaves the calendars it did not reach on incremental rounds.
A create Google made but the store failed to save names the event's id, so a repeat with --id finds it.
sync writes to the store in far fewer transactions, and the daily full round asks only changed series for their
occurrences.events list by time and people list read the store faster.
A refusal from Google for a missing or forbidden item names a reason: google.not-found or google.denied,
so a script can branch on it instead of the message.
A sign-in cut short by a timeout or Ctrl-C still closes the store it opened.
gcal api call --help no longer shows Default: [object Object] for --params. Left out, it still sends no
parameters.
gcal starts in about half the time (gcal --help: 0.40 s before, 0.19 s now, on a laptop with Node 24). The
package ships one bundled program instead of hundreds of modules. A sync also maps each event faster.
Security
search --backend server marks the right fields as written by others. Its untrusted list named title and location, while the answer held them under hits, so an agent that follows the list did not treat them as data.
Each event now names title and location itself.
gcal api refuses an empty, . or .. id in a request's address (api.bad-path-id). Such an id made the
address point at another Google endpoint, calendars/primary/events/.. at the calendar itself; nothing is sent now.
session end in a run with moved folders keeps the owner's sign-in in the system keyring, and says so. A run
with GCAL_CONFIG_DIR, GCAL_STATE_DIR or a moved HOME uses the keyring entry every run of gcal shares; ending
the session there would have signed the owner out everywhere. It now answers kept: "keyring" and says the run is
still signed in; ended is true only when the run had a sign-in of its own to remove. A run in the normal folders
ends the sign-in as before.
A sign-in in a run with moved folders no longer replaces the owner's sign-in in the system keyring. It goes to
the run's own entry, gcal-cli:<config folder>, which the run reads first and its session end removes; the run
otherwise reads the owner's entry and never changes it. So a test sign-in with another Google account can no longer
switch the owner's profile.