Install
openclaw skills install microsoft-calendarSecure Outlook Calendar / Microsoft 365 calendar API CLI. Use when the user wants to list, search, or read Outlook / Microsoft 365 calendar events; creating, updating, deleting, or responding to events require explicit user confirmation - Also Exchange support.
openclaw skills install microsoft-calendarUse porteden calendar to list, search, and read Outlook / Microsoft 365 calendar events in the active account. Use -jc flags for AI-optimized output.
If porteden is not installed: brew install porteden/tap/porteden (or go install github.com/porteden/cli/cmd/porteden@latest).
porteden auth login — opens browser, sign in with the Microsoft account (personal, work, or school), credentials stored in system keyringporteden auth login --token <key> — stored in system keyringporteden auth statusPE_API_KEY is set in the environment, the CLI uses it automatically (no login needed).create, update, delete, and respond change shared state and often send notifications to attendees. Before running any of them, echo back the target profile/account, the calendar ID and event ID (or summary + time for create), the attendee list if it's changing, and the intended change, then wait for the user to confirm. By default update --notify is true (notifications are sent); pass --notify=false to suppress. delete notifies attendees by default; pass --no-notify to skip the cancellation message.--profile (or PE_PROFILE) to isolate Outlook calendar accounts so a task touches only the calendar it needs. Prefer the narrowest Microsoft Graph scope at login. When a task is done — especially on a shared machine — run porteden auth logout to clear the keyring entry, and revoke access from the Microsoft account's security page (account.microsoft.com → Privacy → Apps and services with access to your data; for work/school accounts, myaccount.microsoft.com → Apps you've allowed) if a token may have been exposed.porteden calendar calendars -jc--tomorrow, --week, --days N): porteden calendar events --today -jcporteden calendar events --from 2026-02-01 --to 2026-02-07 -jcporteden calendar events --week --all -jcporteden calendar events --week --include-cancelled -jcporteden calendar events -q "meeting" --today -jcporteden calendar events --week --attendees "alice@example.com,bob@example.com" -jcporteden calendar by-contact "user@example.com" -jc (or --name "John")porteden calendar event <eventId> -jcporteden calendar freebusy --week -jc (or --calendars 123,456 for specific calendars)porteden calendar create --calendar <id> --summary "Meeting" --from "..." --to "..." --location "Room A" --attendees "a@b.com,c@d.com"porteden calendar create --calendar <id> --summary "Standup" --from "..." --to "..." --recurrence "RRULE:FREQ=WEEKLY;COUNT=10"porteden calendar create --calendar <id> --summary "Holiday" --from "2026-07-04T00:00:00Z" --to "2026-07-05T00:00:00Z" --all-dayporteden calendar update <eventId> --summary "New Title" (also: --from, --to, --location)porteden calendar update <eventId> --add-attendees "new@example.com" (or --remove-attendees; default sends notifications, use --notify=false to suppress)porteden calendar delete <eventId> (add --no-notify to skip attendee cancellation emails)porteden calendar respond <eventId> accepted (or: declined, tentative)Two distinct fields are returned on events — don't conflate them.
Event-level status (returned in event.status):
confirmed — normal/scheduled eventtentative — provider-side tentative eventcancelled — event was cancelled or deleted (only shown with --include-cancelled)Attendee-level response (returned in event.attendees[].response):
needs_action — invitee has not yet respondedaccepted — RSVP'd yestentative — RSVP'd maybedeclined — RSVP'd norespond returns 409 CANNOT_RSVP_AS_ORGANIZER when the active user is the organizer (organizers don't RSVP to their own events) and 409 NOT_AN_ATTENDEE when the active user isn't in the attendee list. Both are non-retryable preconditions — surface the message to the user instead of looping.
2026-02-01T10:00:00Z--all-day flag — the API returns allDay: true and durationMinutes: 1440startUtc, endUtc, durationMinutes, status, allDay, organizer, attendees[], joinUrl, and metaPE_PROFILE=work to avoid repeating --profile.-jc is shorthand for --json --compact: filters noise, truncates descriptions, limits attendees, reduces tokens.--all to auto-fetch all pages. The response meta block carries count, totalCount, hasMore, limit, offset, from, to on both /events and /events/by-contact. Manual: --limit 100 --offset 0, then --offset 100, etc.AAMkAGI2...AAA=) are returned in the externalId field. Get IDs via porteden calendar calendars -jc.My Calendars, Other Calendars, Shared Calendars, Birthdays, country-specific holiday calendars). The CLI exposes them as separate calendars in the list output.by-contact matches the positional email arg as a partial substring (so "@acme.com" matches anyone at that domain). --name matches against the attendee's display name when present, otherwise falls back to the local-part of the email (so --name alice matches alice@example.com, but --name acme does not match alice@acme.com).porteden calendar calendars -jc.QUOTA_EXCEEDED (monthly cap) and 429 RATE_LIMITED (transient) are differentiated by the code field in the body; the response also carries x-monthly-limit/x-monthly-used/x-monthly-remaining headers. Quota-blocked requests do not consume quota.PE_API_KEY, PE_PROFILE, PE_TIMEZONE, PE_FORMAT, PE_COLOR, PE_VERBOSE.