Skip to main content

outlook-cli

Microsoft Outlook from your terminal—for humans and agents.

outlook-cli is an early Rust CLI for Outlook mail and calendars through the supported Microsoft Graph API, with an optional classic Outlook desktop backend for Windows and WSL. It aims to provide calm terminal workflows for people and a deterministic, introspectable command contract for automation.

Current milestone

  • Work/school and personal Microsoft accounts through delegated OAuth
  • Tokens protected by the operating system credential store
  • Mail listing, reading, search, sending, replying, moving, deletion, and read-state updates
  • Draft lifecycle and attachment upload/download up to 150 MiB
  • Calendar agenda and event creation
  • Text output on a terminal and JSON when piped
  • Read-only profiles, bounded collections, stable errors, and CLI Spec v0.3

Build

cargo build
cargo test --locked --all-targets

Windows tests also execute the bundled PowerShell bridge against mock Outlook objects, without accessing a mailbox. On other platforms this test can be run with a portable PowerShell installation:

OUTLOOK_TEST_POWERSHELL=/path/to/pwsh cargo test --test desktop_bridge -- --ignored

Install

cargo install outlook-cli --locked
# or, using a prebuilt wheel (supported platforms below)
uv tool install outlook-cli-rs

Both packages install the outlook executable.

Starting with 0.2.3, PyPI wheels cover Windows x64, macOS Intel/Apple Silicon, and Linux x64/ARM64 (glibc 2.17+ or musl 1.2+). WSL uses the Linux wheel. These wheels contain the compiled executable, so Rust is not needed to install or run them. Other platforms require Rust and native build tools to build the source distribution. To require a prebuilt package and fail instead of compiling:

uv tool install --no-build outlook-cli-rs

See the release process for the build matrix and publication checks.

Configure

outlook-cli includes a maintained multitenant Microsoft Entra public-client registration, so the normal setup is simply:

outlook init

The registration requests delegated Microsoft Graph permissions only: User.Read, Mail.ReadWrite, Mail.Send, and Calendars.ReadWrite. A read-only profile requests Mail.Read and Calendars.Read instead.

For a staged or headless setup:

outlook init --no-login
outlook auth login

Read-only profiles also block remote writes locally:

outlook init --read-only

Organizations with restrictive consent policies can use their own public-client registration. Enable public client flows and supply its Application (client) ID:

outlook init --client-id YOUR_APPLICATION_ID

The same override is available through OUTLOOK_CLIENT_ID. Tenant policy can still require administrator approval, and the maintained registration is not yet publisher verified while the project is in its early development phase.

For short-lived automation, OUTLOOK_ACCESS_TOKEN overrides stored credentials.

Classic Outlook on Windows / WSL

Use the same executable with a desktop profile:

outlook init --profile local --backend desktop
outlook --profile local inbox --limit 10
outlook --profile local mail folders
outlook --profile local mail folders --parent inbox
outlook --profile local mail list --folder sentitems
outlook --profile local mail search 'quarterly report' --limit 20
outlook --profile local mail read MESSAGE_ID
outlook --profile local doctor

Requires classic Outlook, a configured and signed-in Windows Outlook profile, and powershell.exe on PATH. From WSL, Windows executable interop must be enabled. New Outlook does not support COM/OOM or MAPI. See Microsoft's Outlook feature comparison.

Desktop initialization checks the connection; --no-login saves a profile without launching Outlook, including when preparing configuration on another platform. Authentication is managed in Windows Outlook. No Graph OAuth registration or token is used. auth status verifies desktop access; auth status --offline only reports configuration and leaves sign-in state unknown. doctor --offline checks platform and PowerShell availability without launching Outlook.

The CLI uses Outlook's active Windows profile and default store. A CLI profile selects the backend; it does not switch the Windows Outlook profile or account. Well-known folders resolve in the default store. mail folders lists its top-level mail folders; use --parent with a returned ID to browse further. Supported names are inbox, sentitems, deleteditems, outbox, drafts, and junkemail.

Desktop supports folder and message listing, reading, search, send, reply/reply-all, move, delete, mark-read/unread, and draft list/create/update/send/delete. Attachments, calendar commands, and whoami return unsupported. Read-only profiles block writes; deleting messages or drafts requires confirmation (or --yes).

New messages and replies use plain text and Outlook's configured sending account. A successful send means Outlook accepted the message for sending; offline Outlook may queue it. Draft updates preserve omitted fields; --clear-to, --clear-cc, and --clear-bcc remove the corresponding recipients. Draft update/send/delete reject sent messages and messages already submitted for sending. Moves return the message's new desktop ID; use that ID for subsequent commands. Delete follows Outlook's behavior, including permanent deletion from Deleted Items. If a write times out or the bridge fails, check Outlook before retrying: it may have completed. There is no automatic fallback to Graph. Existing profiles without a backend field continue to use Graph, which remains the default for init.

Desktop search is case-insensitive literal text in subject, sender name, or sender address, limited to one folder (inbox by default). KQL and regular expressions are not interpreted. Sender addresses may be Exchange legacy addresses as exposed by Outlook. Results reflect the desktop client's available/synchronized data.

Text output includes copyable message IDs and continuation tokens; JSON exposes the same values as structured fields. Desktop IDs encode both EntryID and StoreID, are unrelated to Graph IDs, and can change after moves. Pages scan at most 1,000 items or about 30 seconds before returning a continuation; a search page can be empty with more items still to scan. Pass --cursor with the same command, folder, and query to continue. Pagination uses item positions, so mailbox changes between calls can cause skipped or repeated results. Restart listing after switching the Windows Outlook profile or account.

The bundled PowerShell bridge receives input as JSON on stdin, returns JSON, and releases COM references without quitting Outlook. The CLI waits up to 45 seconds; Outlook may show Windows profile or security prompts. A timeout terminates the local bridge process, but WSL interop can leave a Windows-side process or prompt running; inspect Windows if a call times out.

Commands

outlook inbox --limit 20
outlook mail folders
outlook mail read MESSAGE_ID
outlook mail search 'subject:"quarterly report"' --limit 20
outlook mail mark-read MESSAGE_ID
printf 'All set.' | outlook mail reply MESSAGE_ID --body -
outlook mail send --to person@example.com --bcc archive@example.com \
  --subject 'Hello' --body 'Hi'
outlook mail move MESSAGE_ID --destination archive
outlook mail delete MESSAGE_ID --yes
outlook mail draft create --to person@example.com --subject 'Report' --body 'Attached.'
outlook mail attachment add DRAFT_ID ./report.pdf --content-type application/pdf
outlook mail attachment list DRAFT_ID
outlook mail attachment download MESSAGE_ID ATTACHMENT_ID ./report.pdf
outlook mail draft send DRAFT_ID
outlook calendar agenda --start 2026-09-03T00:00:00Z --end 2026-09-10T00:00:00Z
outlook calendar create --subject 'Project sync' \
  --start 2026-09-04T09:00:00 --end 2026-09-04T09:30:00 \
  --timezone Europe/Amsterdam --attendee person@example.com
outlook auth status                 # verify the selected credential
outlook auth status --offline       # inspect local credential state only
outlook profile list
outlook profile use work
outlook profile remove old --yes
outlook config show
outlook config path
outlook doctor --offline
outlook schema --command 'mail send'

Graph message and event requests opt into immutable Outlook IDs. Remote writes are blocked when the active profile is read-only. Destructive commands confirm on a terminal and require --yes in automation. Attachment downloads never overwrite unless --force is supplied; uploads switch automatically to Microsoft's resumable upload sessions at 3 MiB. Stdout contains data; diagnostics and sign-in instructions go to stderr.

Terminal experience

Run outlook in a terminal for a quick-start guide. Mail lists show full subjects, sender details, unread and attachment indicators, and copyable IDs. Message reading includes recipients and preserves body paragraphs. Folders show total and unread counts; attachments show readable sizes; agendas include timezone and location when supplied by the backend. Paginated text output includes the next cursor, including when a desktop search returns an empty page with more items to scan.

Headings use a restrained cyan accent on terminals. Set NO_COLOR=1 or pass --no-color to disable colors. Redirected text has no color escapes. Mail views remove terminal control sequences from remote content before displaying it.

outlook inbox --output text          # Readable output even when redirected
outlook inbox --output json          # Structured records for scripts
outlook --no-color mail read MESSAGE_ID

Status

The command surface is under active development. A keyboard-first TUI, rich HTML composition, inline attachments, meeting responses, contacts, and delta synchronization are planned after the core Graph and authentication contracts settle.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

outlook_cli_rs-0.2.3.tar.gz (89.1 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

outlook_cli_rs-0.2.3-py3-none-win_amd64.whl (3.2 MB view details)

Uploaded Python 3Windows x86-64

outlook_cli_rs-0.2.3-py3-none-musllinux_1_2_x86_64.whl (4.0 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

outlook_cli_rs-0.2.3-py3-none-musllinux_1_2_aarch64.whl (3.6 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

outlook_cli_rs-0.2.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.9 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

outlook_cli_rs-0.2.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

outlook_cli_rs-0.2.3-py3-none-macosx_11_0_arm64.whl (3.3 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

outlook_cli_rs-0.2.3-py3-none-macosx_10_12_x86_64.whl (3.5 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file outlook_cli_rs-0.2.3.tar.gz.

File metadata

  • Download URL: outlook_cli_rs-0.2.3.tar.gz
  • Upload date:
  • Size: 89.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.5

File hashes

Hashes for outlook_cli_rs-0.2.3.tar.gz
Algorithm Hash digest
SHA256 0f0d3a6e871a1da7709442e711e74e02cb4f7025b6e2f9d114a304faf6c02d50
MD5 1821de43f4ab00ff0e16d8b74a581685
BLAKE2b-256 549ad9a006c8cd761787982fb17c61dcbd4c223089e018a5bbdeb6b0c90ff868

See more details on using hashes here.

File details

Details for the file outlook_cli_rs-0.2.3-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for outlook_cli_rs-0.2.3-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 1cf7f2782b5f79046448b267692cc5dc69b1af1b4d271eb4d8549dff9dd1c884
MD5 11311168430a1618d63303321b10e240
BLAKE2b-256 374010567c6fe37b07c66b8047f86541fcde732c77032d58c24a3e7ce25a90e3

See more details on using hashes here.

File details

Details for the file outlook_cli_rs-0.2.3-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for outlook_cli_rs-0.2.3-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 fc725b89203b63873ea9093ba5d4caef77b4242ab6bf8dfedb12b328d7396779
MD5 69b9c93685a86d5104f1b1f6eceb490d
BLAKE2b-256 1242d822cf0c0c74249708027acd5a70549cd0b6fb2c18f78d178325dd6cfef4

See more details on using hashes here.

File details

Details for the file outlook_cli_rs-0.2.3-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for outlook_cli_rs-0.2.3-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 a923b4af9729fac28bafae8512152ca027b100bd5cadc5afe2ec6cc5d402ea71
MD5 3955a69a80025bc3e2db43d47296266d
BLAKE2b-256 d398a8e159c205118a919cfd5d61af39868b8863e53366d879dd784745f1ef1e

See more details on using hashes here.

File details

Details for the file outlook_cli_rs-0.2.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for outlook_cli_rs-0.2.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6db7221c8f0b2b3133012c30d091a719a1d173c4d6aed6c7900680db4557e804
MD5 a346672975736b5f109a147af21333f4
BLAKE2b-256 1774b8fea57eaf8b734088e408dc0a50c9dbb32155cd0069df77592b48f6b5be

See more details on using hashes here.

File details

Details for the file outlook_cli_rs-0.2.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for outlook_cli_rs-0.2.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 54d8647f14eba9810ff819fb97f39ed68db4aa015ea4f41dd4066eed9c4b6c47
MD5 0b3a40e8d977355b6c48dd98b441a629
BLAKE2b-256 b6cb040f3fc1c86c716bafe0e376f9299b7a0117df46f33445743b30110b0e7a

See more details on using hashes here.

File details

Details for the file outlook_cli_rs-0.2.3-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for outlook_cli_rs-0.2.3-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7c132b2808a8c40aabec0921a1c140000194a8e0d8d9b61ecc1e9b0d6ed5fcb8
MD5 0eacc935f5396af719a6f1eeb1572c80
BLAKE2b-256 d348df13f759c4efd9eb39329d7f563a731cd983343fa400b77693980500b69c

See more details on using hashes here.

File details

Details for the file outlook_cli_rs-0.2.3-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for outlook_cli_rs-0.2.3-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 49ea5553a00171e69638501b46586b187eadeea1ae86c98de091c655de533e0c
MD5 56bd2602fa1ab9b42396c35ff9787b04
BLAKE2b-256 69003140daf1c47804d83e24e8d844aceb2e3323d7af6a293ef097023382c5cb

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.4

8 files

This release

0.2.3 This release

8 files

0.2.2

2 files

0.2.1

2 files

0.1.0

2 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