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.

Interactive inbox

outlook tui                         # Browse the active profile's inbox
outlook tui --folder sentitems       # Open another folder
outlook --profile local tui          # Classic Outlook on Windows/WSL
outlook tui --demo                   # Try sample mail without signing in
outlook tui --demo --snapshot        # Print an offline sample screen

The browser is read-only: previewing a message does not mark it as read. Wide terminals show a message list and a reading pane; below 100 columns, Enter or Tab switches between them. The minimum usable size is 36 × 12. Colors follow your terminal palette and respect --no-color and NO_COLOR.

Key Action
↑ / ↓ or j / k Select a message, or scroll the focused preview
Enter / Tab Switch between list and preview
Page Up / Page Down Scroll the message by ten lines
Home / End Jump to the beginning or end of the focused preview
/ Search the current folder; Enter applies, Esc cancels
Esc in the list Clear the search, or quit if no search is active
f Browse folders; Enter opens a folder's mail
→ / ← in folders Browse children / return to the parent
n Load the next page when available
r Refresh the focused pane, or retry a failed request
? Open the keyboard guide
q / Ctrl+C Quit

Graph searches use Outlook syntax; desktop searches use literal subject/sender text. Folder browsing includes child folders and pagination. An empty desktop search page can still have more matches to scan; press n when offered. Reads run asynchronously, with a timeout and cancellable previews. On WSL, the desktop bridge's existing Windows-process cleanup limitations still apply. Sign in with outlook init or outlook auth login before opening a live inbox. Interactive mode requires terminal input and output; use the regular commands and JSON for scripts. --snapshot always prints plain sample text and supports --width (36–240) and --height (12–100).

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. Rich HTML composition, inline attachments, meeting responses, contacts, and delta synchronization are planned after the core Graph and authentication contracts settle.

Metadata

Release files for outlook-cli-rs 0.2.5

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

Source distribution (sdist)

Source distribution for outlook-cli-rs 0.2.5
File Size Uploaded Provenance Actions
outlook_cli_rs-0.2.5.tar.gz 106.9 kB Without provenance Details for outlook_cli_rs-0.2.5.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for outlook-cli-rs 0.2.5
File Actions
outlook_cli_rs-0.2.5-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details for outlook_cli_rs-0.2.5-py3-none-win_amd64.whl
outlook_cli_rs-0.2.5-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details for outlook_cli_rs-0.2.5-py3-none-musllinux_1_2_x86_64.whl
outlook_cli_rs-0.2.5-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details for outlook_cli_rs-0.2.5-py3-none-musllinux_1_2_aarch64.whl
outlook_cli_rs-0.2.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details for outlook_cli_rs-0.2.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
outlook_cli_rs-0.2.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details for outlook_cli_rs-0.2.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
outlook_cli_rs-0.2.5-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details for outlook_cli_rs-0.2.5-py3-none-macosx_11_0_arm64.whl
outlook_cli_rs-0.2.5-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details for outlook_cli_rs-0.2.5-py3-none-macosx_10_12_x86_64.whl

Total release size: 27.5 MB

Release files / outlook_cli_rs-0.2.5.tar.gz

Download URL outlook_cli_rs-0.2.5.tar.gz
Size 106.9 kB
Tags Source
SHA-256 checksum
How to use checksums
7d3ed72b2ca82d57316e56e911179e7aa88640cb975d469271a1721019206d9c
BLAKE2b-256 checksum
How to use checksums
f9d366c5117edfaf2a6052ba4ed2782d4ca05fb11460489e72317f0bbadfb9fd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / outlook_cli_rs-0.2.5-py3-none-win_amd64.whl

Download URL outlook_cli_rs-0.2.5-py3-none-win_amd64.whl
Size 3.5 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
7ed478cd36ebec63e3332d2e70ab964bcd5b2d153091a4291750876d8f623673
BLAKE2b-256 checksum
How to use checksums
ef9ced447440a244cfdcbc0346051278dbcb90dc65e60ebb68cc8b37c6193d2a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / outlook_cli_rs-0.2.5-py3-none-musllinux_1_2_x86_64.whl

Download URL outlook_cli_rs-0.2.5-py3-none-musllinux_1_2_x86_64.whl
Size 4.3 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
a28b7e5b346e72bb1ceb4a44e8fd44134b1ed9794cfe8624a17122ba76fdeb4f
BLAKE2b-256 checksum
How to use checksums
c6362990632aced087992cbe51ea07910f07d5c3b91789501128124bd7fd4e3f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / outlook_cli_rs-0.2.5-py3-none-musllinux_1_2_aarch64.whl

Download URL outlook_cli_rs-0.2.5-py3-none-musllinux_1_2_aarch64.whl
Size 4.0 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
ac6a7726948fe56466966d34163265c7c5c883381865f222f87e774f7ba78e32
BLAKE2b-256 checksum
How to use checksums
6e9157e82c52ee178664e5351c7b8f393a524c2b0caf9a9278ef4508a4f40ef5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / outlook_cli_rs-0.2.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL outlook_cli_rs-0.2.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 4.2 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
c6c84afc98f5296c4b279d9011305333da398474fbf288d78da17fccccce482d
BLAKE2b-256 checksum
How to use checksums
c487c32db748d4e52dad4f16e07fb4da2011ec63f2352cc89736badf8b907416
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / outlook_cli_rs-0.2.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL outlook_cli_rs-0.2.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 3.9 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
900913fda7ceb51f58350d08fe97430b0341c8a1c6f56d9e877cae946b6dff96
BLAKE2b-256 checksum
How to use checksums
e9ab0f19818ddcab17219fbe30af7a1c84529e44f194acf27fb5e4af5a61cb5e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / outlook_cli_rs-0.2.5-py3-none-macosx_11_0_arm64.whl

Download URL outlook_cli_rs-0.2.5-py3-none-macosx_11_0_arm64.whl
Size 3.6 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
87ff4d3ecceeb1a10c70a5f3d6090372fe4369faf07be3620a5d83086255fdf7
BLAKE2b-256 checksum
How to use checksums
98c74fd1152fad6ca9c23f1f09186a206b4932544a341814c37760a7b8a7ff38
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / outlook_cli_rs-0.2.5-py3-none-macosx_10_12_x86_64.whl

Download URL outlook_cli_rs-0.2.5-py3-none-macosx_10_12_x86_64.whl
Size 3.8 MB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
c0223f0cb80f48e634d1840384d2530e9504ae5c149f95d367e8410a41e65924
BLAKE2b-256 checksum
How to use checksums
de184515ed9a8c78504bc9f6a8639af2080381aa04aa2c4ff384f32ea38bbbd7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Security for outlook-cli-rs 0.2.5

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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