A command-line tool for Microsoft Outlook (Work/School accounts). Search, read, send, and reply to emails. List, read, and create calendar events. Built with the O365 library and Typer.
- Python 3.11+
- uv package manager
- An Azure App Registration (free) with Microsoft Graph delegated permissions:
Mail.ReadWriteMail.SendCalendars.ReadWrite
- Go to Azure Portal > App registrations
- Click New registration
- Name it anything (e.g. "Outlook CLI"), set Supported account types to your preference
- Under Authentication > Advanced settings, set Allow public client flows to Yes and save
- Under API permissions, add the three Delegated permissions listed above
- If your tenant requires admin consent, have an admin grant consent for the app
- Copy the Application (client) ID — you'll need it for
outlook auth login
git clone https://github.com/mhattingpete/outlook-cli.git
cd outlook-cli
uv sync# Authenticate with your Azure app
outlook auth login --client-id YOUR_CLIENT_ID
# Follow the device code flow — open the URL and enter the code
# Check status
outlook auth statusoutlook auth login [--client-id ID] [--tenant-id ID] # Authenticate via device code flow
outlook auth logout # Remove stored token
outlook auth status # Show auth status and config# Search / list messages
outlook mail search # List recent inbox messages
outlook mail search "quarterly report" # Full-text search
outlook mail search --unread # Unread messages only
outlook mail search --from alice@company.com # Filter by sender
outlook mail search --start-date 2025-01-01 --end-date 2025-02-01
outlook mail search --important --has-attachments # Combine filters
outlook mail search --folder "Sent Items" --limit 10 # Different folder
# Read a message
outlook mail read MESSAGE_ID
# Send a message
outlook mail send --to bob@company.com --subject "Hello" --body "Hi Bob!"
outlook mail send --to bob@company.com --cc carol@company.com --subject "Update" --body "FYI"
# Reply to a message
outlook mail reply MESSAGE_ID --body "Thanks for the update!"
outlook mail reply MESSAGE_ID --body "Noted, thanks." --reply-all
# Mark as read/unread
outlook mail mark MESSAGE_ID # Mark as read (default)
outlook mail mark MESSAGE_ID --unread # Mark as unread# List events (default: next 7 days)
outlook cal list
outlook cal list --start 2025-03-01 --end 2025-03-31 # Custom date range
outlook cal list --subject "standup" # Filter by subject
outlook cal list --location "Room A" # Filter by location
outlook cal list --all-day # All-day events only
outlook cal list --recurring # Recurring events only
outlook cal list --organizer boss@company.com # Filter by organizer
# Read event details (shows attendees, recurrence, etc.)
outlook cal read EVENT_ID
# Create an event
outlook cal create --subject "Lunch" --start "2025-02-08 12:00" --end "2025-02-08 13:00"
outlook cal create --subject "Workshop" \
--start "2025-02-10 09:00" --end "2025-02-10 17:00" \
--body "Full day workshop" --location "Conference Room B"outlook-cli works with Claude Code out of the box. Here are example prompts and what Claude does with them:
# ── Email triage ──────────────────────────────────────────
# Prompt: "Show me unread emails from alice"
outlook mail search --unread --from alice@company.com
# Prompt: "Read the first message"
outlook mail read aB3x-def4-5678-gh90
# Prompt: "Reply saying I'll handle it today"
outlook mail reply aB3x-def4-5678-gh90 --body "I'll handle this today."
# Prompt: "Mark it as read"
outlook mail mark aB3x-def4-5678-gh90
# ── Calendar management ──────────────────────────────────
# Prompt: "What's on my calendar this week?"
outlook cal list
# Prompt: "Any recurring meetings?"
outlook cal list --recurring
# Prompt: "Schedule a team lunch Friday at noon"
outlook cal create --subject "Team Lunch" \
--start "2025-02-14 12:00" --end "2025-02-14 13:00" \
--location "Cafeteria"
# ── Search and respond ───────────────────────────────────
# Prompt: "Find emails about the project proposal with attachments"
outlook mail search "project proposal" --has-attachments
# Prompt: "Reply-all to the latest with my feedback"
outlook mail reply msg-id --reply-all --body "Looks good — approved."Config and tokens are stored in ~/.outlook-cli/:
~/.outlook-cli/
├── config.toml # client_id, tenant_id
└── o365_token.token # OAuth token (auto-managed)
# Install dev dependencies
uv sync
# Run tests
uv run pytest tests/ -v
# Run the CLI
uv run outlook --helpMIT