Skip to content

0.5.0

Choose a tag to compare

@github-actions github-actions released this 31 Oct 12:59
· 26 commits to main since this release
7307612

Added

  • calendars list takes a query: synced:, primary: and access_role: narrow the list, such as
    gcal personal calendars list synced:true.
  • commands info describes what each calendar command answers with, and --fields can pick from it.

Changed — may break callers

  • gcal search <words> is now gcal search events <query>, and gcal status is now gcal store status, the
    shape the other WireCat tools use (max: search messages <query>, store status). The old paths are gone, with no
    alias. Over MCP the command is search events, and its input is query (was words); a store search's next-page
    step names query too. A partial sync's hint points at store status. The permission keys move with them:
    permissions.store.status and permissions.search.events; permissions.search still covers the search. A config
    that still sets permissions.status is refused with config.invalid, which names
    gcal <profile> config unset permissions.status.
  • events list takes only the standard field query, and none of its own words. today, week, from:, to:,
    changed: and overlapping are refused. Write the window as fields: from:2026-11-02 to:2026-11-06 is
    ends_at>=2026-11-02 starts_at<=2026-11-06, and changed:2026-10-25 is changed_at>=2026-10-25; calendar: and
    person: stay. Over MCP the input is query ("ends_at>=2026-11-02"), no longer words. What callers lose:
    • today and week: write the dates. The query language has today but no word for a day ahead, so the end of a
      window is an ISO date.
    • overlapping and the overlaps field: no standard term asks for events that clash, so the list no longer finds
      them. Compare starts_at and ends_at of the listed events instead.
    • starts_at>=… is refused and names the ends_at>=… term to write instead: the store finds events by the moments
      they span, so it can bound only the latest start and the earliest end. An event that ends exactly at the
      ends_at moment is left out.
    • Without a time term the list still starts at the beginning of today.
  • Deleting a whole Google calendar and giving it to another account are deny by default, as emptying one is.
    api.calendar.calendars.delete and api.calendar.calendars.transferOwnership were ask, which over MCP runs with no
    question. Set either key to ask or allow to let it run.
  • session status and session end answer where no keyring can be reached and no sign-in file is kept. They
    failed with oauth.not-saved. Now session status says state: missing with keyring: unreachable, and
    session end says ended: false with keyring: unreachable: this run can use no sign-in, so there is nothing to
    show or end. A sign-in kept with --credential-storage file is read as before. session start and the commands that
    call Google still fail with oauth.not-saved, which troubleshooting explains. A script
    that took the failure to mean "keyring out of reach" reads keyring in the answer instead.
  • people list takes one event as event:<id>. gcal personal people list 42 is refused as a word with no
    field; write people list event:42. Over MCP the input is query ("event:42"), no longer event.
  • search --backend server answers as the shared search does. Each event's found_by is ["server"] (was
    ["google"]). The refusals have new reasons: no synced calendar is search.no-calendars (was
    calendars.none-synced), --offline is search.offline (was offline.refused), --exact, --cursor or
    --newest is search.server-options, and --backend both is search.one-backend (was search.backend-both).
  • The calendar commands' help no longer lists --json and --jsonl under each command, and their MCP tools no
    longer take json or jsonl inputs. The global --json and --jsonl work as before; an agent that sent
    jsonl: true was refused.
  • config show --bot and config set|unset --personal|--bot are hidden. gcal has no bots, so they had nothing
    behind them. They are still accepted, so a script that passes one keeps working.

Fixed

  • Calls an agent sends to gcal mcp serve at the same time each get their own answer. Two calendar reads sent
    together could answer one of them empty ({"item":{"value":null}}) or fail it with command.crashed, because the
    calls shared which command was running and the store it had opened. Each call now keeps its own
    (WC-ARCH-22).
  • An all-day event with no time zone of its own or of its calendar starts at midnight in your computer's time zone.
    gcal read it as midnight UTC: on a computer in Madrid it started an hour late, and in New York on the evening before.
    Such an event's timezone now names the zone it was read in, where it was null. An event or calendar that names
    its zone is read in that zone, as before. An event already stored keeps its old start until Google sends it again,
    after it changes
    (WC-TIME-3).