Skip to main content

m365-owa-cli

m365-owa-cli is a personal, agent-first Python CLI for Microsoft 365 Outlook workflows through Outlook on the web / OWA internal service endpoints.

The current command surface is calendar-focused, but the package name leaves room for mail and tasks if the same OWA-authenticated endpoint strategy proves useful there. Microsoft Graph is intentionally out of scope.

Examples

m365-owa-cli capabilities
m365-owa-cli schema event
m365-owa-cli auth set-token --connection work
m365-owa-cli auth bookmarklet --connection work --raw
m365-owa-cli auth extract-token --connection work --devtools-url http://127.0.0.1:9222 --reload
m365-owa-cli auth list-connections
m365-owa-cli categories list --connection work
m365-owa-cli categories upsert --connection work --name "Deep Work"
m365-owa-cli events list --connection work --day 2026-04-24
m365-owa-cli events delete --connection work --id AAMk... --confirm-event-id AAMk...

Commands emit JSON by default. Use --pretty where supported for local human-readable output. See docs/schema.md for the stable event and category JSON contracts.

Configuration

Tokens are stored as plaintext files under:

~/.config/m365-owa-cli/connections/<connection>.token

Tests and automation can override the config root with M365_OWA_CONFIG_DIR.

Connection names are the explicit account, tenant, or environment selector. Examples:

m365-owa-cli auth list-connections
m365-owa-cli events list --connection tenant-a --day 2026-04-24
m365-owa-cli events list --connection tenant-b --day 2026-04-24
m365-owa-cli events list --connection tenant-c --day 2026-04-24
m365-owa-cli events list --connection prod --day 2026-04-24

Browser Token Capture

Preferred method: watch a DevTools-enabled Edge or Chrome tab and store OWA auth material from browser traffic. Open Outlook on the web in that browser first. On macOS, use a reusable debug profile so Chrome first-run and search-engine-choice prompts do not come back every session:

open -na "Google Chrome" --args --remote-debugging-port=9222 --user-data-dir="$HOME/.config/m365-owa-cli/chrome-devtools-profile" --no-first-run --no-default-browser-check --disable-search-engine-choice-screen https://outlook.office.com/calendar/

Capture per connection:

m365-owa-cli auth extract-token --connection tenant-a --browser chrome --devtools-url http://127.0.0.1:9222 --reload
m365-owa-cli auth extract-token --connection tenant-b --browser chrome --devtools-url http://127.0.0.1:9222 --reload
m365-owa-cli auth extract-token --connection tenant-c --browser chrome --devtools-url http://127.0.0.1:9222 --reload

Each command stores separate local auth state:

~/.config/m365-owa-cli/connections/tenant-a.token
~/.config/m365-owa-cli/connections/tenant-b.token
~/.config/m365-owa-cli/connections/tenant-c.token
~/.config/m365-owa-cli/connections/tenant-a.credential.json

The command only accepts bearer headers from known Outlook hosts on /owa/service.svc and Microsoft identity token responses from login.microsoftonline.com; it stores secrets locally and emits metadata only. If the capture times out, interact with the open Calendar tab and retry without --reload.

Manual Token Capture Fallback

Use the bookmarklet helper only when DevTools capture is unavailable:

m365-owa-cli auth bookmarklet --connection tenant-a --raw

Create a browser bookmark with the generated value as the URL, open Outlook on the web, click the bookmarklet, then refresh or open Calendar. If OWA sends an Authorization: Bearer ... header to /owa/service.svc, the helper displays it for copying into auth set-token.

Opsec

  • Do not print, paste, commit, screenshot, or document bearer token values.
  • Do not copy ~/.config/m365-owa-cli/connections/*.token or *.credential.json into this repository.
  • Use --connection names like tenant-a, tenant-b, prod, dev, or another explicit tenant/environment name so agents never depend on hidden account state.
  • Keep remote debugging bound to the local machine, for example http://127.0.0.1:9222.
  • Prefer JSON command output and rely on built-in redaction for errors; do not add ad hoc debug logging around auth headers.

Releases

New versions are published to PyPI from GitHub Actions when a v* tag is pushed. The workflow uses PyPI trusted publishing against the pypi environment in this repository, so no long-lived PyPI API token is stored in GitHub.

Before the first release, configure a pending trusted publisher on PyPI:

  • PyPI project name: m365-owa-cli
  • Owner: okms
  • Repository: m365-owa-cli
  • Workflow: publish.yml
  • Environment: pypi

Release flow:

# bump version in pyproject.toml, commit
git tag vX.Y.Z
git push origin main --tags

The .github/workflows/publish.yml workflow runs tests, builds the source and wheel distributions, checks them with Twine, and publishes them to PyPI. Tag-less runs can also be triggered manually from the Actions tab.

Metadata

Release files for m365-owa-cli 0.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for m365-owa-cli 0.1.4
File Size Uploaded
m365_owa_cli-0.1.4.tar.gz 85.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for m365-owa-cli 0.1.4
File Interpreter ABI Platform
m365_owa_cli-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 130.2 kB

Release files / m365_owa_cli-0.1.4.tar.gz

Download URL m365_owa_cli-0.1.4.tar.gz
Size 85.3 kB
Tags Source
SHA-256 checksum
How to use checksums
7278bd5f1b3c3a43b84c0d6c0ee0254b4aec0103eea1c5fc4ebd7b63cf441e46
BLAKE2b-256 checksum
How to use checksums
ef17ac88fab89c3be305f84bb384a3eaee3cb4f47254858259e4ceab49d3d8bd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 26, 2026.

Transparency log

Release files / m365_owa_cli-0.1.4-py3-none-any.whl

Download URL m365_owa_cli-0.1.4-py3-none-any.whl
Size 44.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f3387220b1297465b8f5a1e956157fbbd4b18e3323dce060058a1ce059d5e246
BLAKE2b-256 checksum
How to use checksums
926f0d1b730c0512cda6305ed82cd26afb66e7c3d3dd18b4b02d985c6891f15b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 26, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page