Guide
Manage Outlook Calendar from the CLI
Create, list, update, and delete Microsoft 365 calendar events from your terminal. No Azure AD app registration, no Graph API boilerplate. The Nylas CLI handles OAuth2 and calendar CRUD with single-line commands. Works with Gmail, Outlook, Exchange, Yahoo, iCloud, and IMAP.
Written by Caleb Geene Director, Site Reliability Engineering
Reviewed by Hazik
Most Fortune 500 companies run on Microsoft 365
According to Microsoft's Ignite 2024 announcement, nearly 70% of the Fortune 500 use Microsoft 365 Copilot alone — meaning overall Microsoft 365 adoption is even higher. That means most enterprise calendar workflows hit the Graph API sooner or later. And the Graph API isn't casual. You register an Azure AD application, configure delegated permissions like Calendars.ReadWrite, handle OAuth2 token exchange with PKCE, then call GET /me/events with a Bearer token. That's four steps before your first query.
Application permissions (the daemon/service auth flow) require a different grant type entirely, and according to Microsoft's Graph API calendar documentation, most calendar operations need delegated permissions unless you're building a background service with admin consent. The Nylas CLI collapses all of this into nylas init.
Graph API vs. Nylas CLI
| Task | Microsoft Graph API | Nylas CLI |
|---|---|---|
| Initial setup | Register Azure AD app, configure permissions, get tenant ID | brew install nylas/nylas-cli/nylas && nylas init |
| Authentication | Implement OAuth2 PKCE flow, handle token refresh | nylas auth login (browser-based OAuth2) |
| List events | GET /me/events with Bearer token and query params | nylas calendar events list |
| Create event | POST /me/events with JSON body | nylas calendar events create --title "..." |
| Book a room | POST /me/findRooms + add room as attendee | --participant room@company.com |
| Check availability | POST /me/calendar/getSchedule with JSON body | nylas calendar availability check |
| Provider lock-in | Microsoft only | Works with Google, Yahoo, iCloud, Exchange, IMAP too |
| Time to first API call | 15-30 minutes | Under 2 minutes |
1. Install and connect your Microsoft 365 account
Install via Homebrew (other methods here) and run the init wizard:
brew install nylas/nylas-cli/nylas
nylas initThe wizard creates a Nylas account and walks you through connecting Microsoft 365 via OAuth2. Unlike Graph API setup, there's no Azure AD app registration, no tenant configuration, no .env files.
2. Core Outlook calendar commands
Most Microsoft 365 automations still come down to four operations: list the right calendar, create an event in the right mailbox, update the exact occurrence you care about, and delete only when the mailbox policy allows it. The Outlook-specific wrinkle is that you often need to target a delegated calendar or shared identity rather than your own default calendar.
# List upcoming events on your default calendar
nylas calendar events list --days 14
# Create an event on a delegated executive calendar
nylas calendar events create \
--calendar-id cal_exec_assistant \
--title "Board Prep" \
--start "2026-04-10 09:00" \
--end "2026-04-10 10:00" \
--participant chief-of-staff@company.com
# Reschedule a Microsoft 365 event
nylas calendar events update event_abc123 \
--start "2026-04-10 11:00" \
--end "2026-04-10 12:00"
# Delete an event by ID
nylas calendar events delete event_abc123If the mailbox owner delegated access through Outlook but you still cannot write to the calendar, verify the exact calendar_id and mailbox policy before blaming the command. That is a Microsoft 365 permissions problem, not a CLI syntax problem.
3. Shared calendars and delegation
Microsoft 365 organizations rely heavily on shared calendars for teams, projects, and departments. According to Microsoft's Azure AD permission model documentation, accessing another user's calendar requires either delegated permissions with the user's consent or application-level permissions granted by an admin. The CLI abstracts this once your grant has the right scopes.
# See all calendars (personal + shared + delegated)
nylas calendar list
# List events on a shared team calendar
nylas calendar events list --calendar-id cal_shared_marketing
# Create an event on a delegated calendar
nylas calendar events create \
--calendar-id cal_exec_assistant \
--title "Board Prep" \
--start "2026-04-10 09:00" \
--end "2026-04-10 10:00"4. Executive assistant and delegated-calendar workflows
Outlook calendar automation is often less about room resources and more about one person acting on behalf of another. Executive assistants, chiefs of staff, recruiting coordinators, and operations leads commonly create or move meetings on delegated calendars all day. That pattern is much more Outlook-specific than the iCloud or Yahoo versions of this guide.
# Pull the exact delegated calendar IDs you can access
nylas calendar list --json | \
jq -r '.[] | "\(.name) | read_only=\(.read_only) | id=\(.id)"'
# Create a meeting on an executive's delegated calendar
nylas calendar events create \
--calendar-id cal_exec_assistant \
--title "Board Prep" \
--start "2026-04-10 09:00" \
--end "2026-04-10 10:00" \
--participant chief-of-staff@company.comIf the mailbox owner delegated access through Outlook but you still cannot write to the event, the issue is usually permission scope or mailbox policy, not the CLI command.
5. Teams meeting links
When you create an event with participants on a Microsoft 365 account, Teams meeting links can be auto-generated. The conferencing details appear in the event response. Extract them with --json and jq:
nylas calendar events create \
--title "Weekly Standup" \
--start "2026-04-07 09:00" \
--end "2026-04-07 09:30" \
--participant dev-team@company.com \
--json | jq '.conferencing'This replaces the manual Graph API flow of creating an onlineMeeting resource and attaching it to the event.
6. Outlook categories and recurring events
Outlook calendars support color-coded categories (Blue, Red, Green, or custom labels like "Client Meetings"). These categories sync across Outlook desktop, web, and mobile. When you fetch events as JSON, each event's metadata includes its category assignments:
# View event details including categories
nylas calendar events list --json | jq '.[] | {title: .title, categories: .metadata}'Recurring events
Outlook represents recurring events using RRULE (RFC 5545). A weekly standup, for instance, is a single master event with an RRULE like FREQ=WEEKLY;BYDAY=MO;COUNT=52. When you list events, the CLI returns individual occurrences, not the raw RRULE. Updating a single occurrence changes only that instance; updating the master event changes the series.
# Update a single occurrence
nylas calendar events update event_abc123_20260407 \
--title "Standup (Cancelled)" \
--start "2026-04-07 09:00" \
--end "2026-04-07 09:00"
# Delete an entire recurring series by its master ID
nylas calendar events delete event_abc123When to use the Exchange guide instead
If your main problem is room mailboxes, on-prem Exchange, hybrid coexistence, or EWS migration pressure, you are really in Exchange territory rather than pure Outlook/M365 tenant workflows. Use the Exchange calendar guide for that estate-management path.
7. Check availability and find time
Free/busy checks work across calendars without parsing iCal feeds or calling the Graph API's getSchedule endpoint:
# Your availability for the next 7 days
nylas calendar availability check
# Find a 30-minute slot with two coworkers
nylas calendar availability find \
--participants alice@company.com,bob@company.com \
--duration 30Example output
$ nylas calendar availability find --participants alice@company.com,bob@company.com --duration 30
Available slots:
1. Tue, Apr 1, 2026, 11:00 AM - 11:30 AM
All participants free
2. Tue, Apr 1, 2026, 3:00 PM - 3:30 PM
All participants free
Found 2 slot(s)8. JSON output for scripting
Outlook teams usually use JSON output for morning briefings, room audits, executive assistant workflows, and escalation tooling. The payload matters more than the rendered table when you are feeding Microsoft 365 state into another system:
# Count today's meetings
nylas calendar events list --days 1 --json | jq length
# Morning briefing script
#!/bin/bash
count=$(nylas calendar events list --days 1 --json | jq length)
echo "You have $count meetings today."
if [ "$count" -gt 6 ]; then
echo "Heavy meeting day. Block focus time."
fi9. Delegated calendars vs shared mailboxes
Microsoft 365 teams often conflate delegated calendars, shared mailboxes, resource calendars, and M365 group calendars. They are not the same thing operationally. Delegation is person-to-person access. Shared mailboxes behave like a separate identity. M365 groups are collaboration objects with their own calendar surface. That distinction barely exists in the Google or iCloud versions of this guide, but it changes how Outlook automations fail in practice.
# Check which calendars your current Outlook grant can actually see
nylas calendar list --json | \
jq -r '.[] | "\(.name) | read_only=\(.read_only) | id=\(.id)"'If a script can list a calendar but cannot create an event, the issue is usually delegated permission scope or mailbox policy, not the command itself.
10. Conditional Access and tenant controls
Outlook and Microsoft 365 also sit behind Entra ID tenant policy. Conditional Access, MFA requirements, disabled legacy auth, tenant consent, and mailbox-level policies can all block otherwise valid calendar workflows. This is why the Outlook article cannot just be a copy of the Yahoo or iCloud one. The protocol story is Microsoft Graph, but the operational story is tenant policy.
When an Outlook automation works for one user and fails for another, the root cause is often not event data. It is the tenant deciding which grant is allowed to act, whether shared mailbox access is enabled, or whether conferencing details can be provisioned.
11. M365 groups and channel scheduling
Another Outlook-specific workflow is scheduling around M365 groups, Teams channels, and room lists. Those don't map cleanly to the simpler "one account, one calendar" model used by most personal providers. If you support enterprise users, make sure your automation can distinguish between a person's mailbox calendar and a shared collaboration calendar.
# Pull calendar IDs first, then target the exact group or delegated calendar
nylas calendar list --json | \
jq '.[] | {name: .name, id: .id}'Next steps
- Manage calendar from the terminal -- full guide covering DST handling, working hours, timezone locking, and AI scheduling
- List Outlook emails from terminal -- read and search your Outlook inbox without the Graph API
- Send email from the terminal -- compose and send email from the command line
- Give AI agents calendar access via MCP -- let Claude or Cursor manage your Outlook calendar
- Full command reference -- every calendar flag and subcommand