Skip to content

Repository files navigation

outlook-cli

Cross-platform CLI for Microsoft Outlook via the Microsoft Graph API, with dual implementations in Node.js and .NET NativeAOT.

Features

  • 📧 Email — inbox, read, search, draft, reply, forward, send, move, flag, mark-read
  • 📅 Calendar — today, week, date range, view, create events, list calendars
  • 👥 Contacts — search contacts and GAL, manage aliases (fredfreddie@outlook.com)
  • 👤 Multi-account — personal + work accounts, parent chains, per-account permissions
  • 👥 Delegate access — read and send on behalf of other users (--as fred)
  • 👀 Watch mode — real-time change tracking via delta queries, rules engine for channel delivery
  • 🔐 Security — AES-256-GCM encrypted token cache, configurable permissions, forbidden scopes, send_to whitelist, defense-in-depth token validation
  • 🖥️ Cross-platform — Mac, Linux, Windows; device code flow for headless VMs
  • 📊 Multiple output formats — text, json, markdown, html
  • 🤖 AI agent integration — OpenClaw / NanoClaw dual-mode (Skill + Channel Factory)
  • 🌉 COM Bridge — For enterprise environments where Graph API is blocked, connect via Outlook Desktop COM automation on Windows

Quick Start

1. Clone and Build

git clone https://github.com/jeffstall/outlook-cli.git
cd outlook-cli
.\build.ps1 all

build.ps1 runs npm install automatically and builds both Node.js and .NET NativeAOT for your current OS/architecture. Both implementations share the same config directory (~/.outlook-cli/) and can be used interchangeably. See docs/architecture.md for details.

2. Set Up Accounts

You need an Azure App Registration (free). See docs/AZURE-SETUP.md for step-by-step instructions. Both accounts below can share the same client ID — each user authenticates independently.

# Add a read/write account
node bin/outlook-cli.js account add work --client-id YOUR_CLIENT_ID
node bin/outlook-cli.js auth login --account work
# Add a read-only account (can read mail but cannot send, draft, move, or delete)
node bin/outlook-cli.js account add monitor --client-id YOUR_CLIENT_ID --read-only
node bin/outlook-cli.js auth login --account monitor

Each auth login opens a browser to sign in with a different Microsoft account. Read-only is enforced at two layers: the token only contains read scopes, and the CLI blocks write commands before they reach the API. See docs/usage/account.md for details.

3. Read Your Inbox

# List recent messages for the read/write account
node bin/outlook-cli.js mail inbox --account work
# Read message #1 (short IDs are assigned by inbox/search commands)
node bin/outlook-cli.js mail read 1 --account work

4. Send a Message

# Compose and send a message from "work" to "monitor"
node bin/outlook-cli.js mail draft --to "monitor@example.com" --subject "Hello from CLI" --body "Testing outlook-cli!" --send --yes --account work

Replace monitor@example.com with the actual email address of the monitor account. Use --send to compose and send in one step, or omit it to create a draft you can review first.

5. Verify It Arrived

# Check the read-only account's inbox
node bin/outlook-cli.js mail inbox --account monitor

Managing Accounts

# List all accounts
node bin/outlook-cli.js account list
# Remove a single account (deletes config and cached tokens)
node bin/outlook-cli.js account remove monitor
# Reset to clean state — remove the entire config directory# (Windows)
rmdir /s /q "%USERPROFILE%\.outlook-cli"# (Mac/Linux)
rm -rf ~/.outlook-cli

See docs/usage/account.md for the full account command reference.

Documentation

DocumentDescription
docs/usage.mdComplete command-line reference with examples
docs/architecture.mdArchitecture, config formats, security model, integration
docs/src-node.mdBuilding and testing the Node.js implementation
docs/src-dotnet.mdBuilding and testing the .NET implementation
docs/src-tests.mdTest architecture and conventions
docs/AZURE-SETUP.mdAzure App Registration setup guide
docs/SECURITY.mdSecurity model and threat analysis
docs/MULTI-ACCOUNT.mdMulti-account configuration guide
docs/DELEGATE-ACCESS.mdDelegate access setup and usage
docs/WATCH-MODE.mdWatch mode and rules engine
docs/JSON-INPUT.mdJSON input file schemas for all commands
docs/DIRECTORY-STRUCTURE.mdProject directory layout
docs/self-hosting.mdSelf-hosting guide including COM Bridge deployment

Architecture Overview

┌──────────────────────────────────────────────────────┐
│ outlook-cli │
├──────────────────────┬───────────────────────────────┤
│ Node.js (ESM) │ .NET 8 (NativeAOT) │
│ Commander.js CLI │ System.CommandLine CLI │
│ @azure/msal-node │ MSAL.NET │
│ Direct HTTP Graph │ Direct HTTP Graph │
├──────────────────────┴───────────────────────────────┤
│ Shared Configuration │
│ ~/.outlook-cli/accounts.json │
│ ~/.outlook-cli/aliases.json │
│ ~/.outlook-cli/cache-*.enc (AES-256-GCM) │
│ ~/.outlook-cli/delta-*.json │
└──────────────┬───────────────────────────────────────┘
│ (provider = "bridge" in accounts.json)
┌──────────────▼───────────────────────────────────────┐
│ COM Bridge (optional) │
│ src/bridge/ — Windows-only ASP.NET Core server │
│ COM automation → Outlook Desktop → Exchange │
│ HMAC-SHA256 authenticated HTTP API │
└──────────────────────────────────────────────────────┘

Both implementations produce identical CLI behavior and share all configuration files. You can switch between them freely.

Azure App Registration

You need a free App Registration in Microsoft Entra ID. See docs/AZURE-SETUP.md for step-by-step instructions.

Required permissions:

PermissionPurpose
User.ReadRead user profile
Mail.ReadRead email messages
Mail.ReadWriteCreate drafts, move, flag, mark-read
Calendars.ReadRead calendar events
Calendars.ReadWriteCreate calendar events
offline_accessRefresh tokens for persistent sessions

Optional permissions:

PermissionPurpose
Mail.SendSend email from own account
Mail.Send.SharedSend on behalf of delegate mailbox owner
Mail.Read.SharedRead delegate mailbox
Mail.ReadWrite.SharedWrite to delegate mailbox
Calendars.Read.SharedRead delegate calendar

Security note: Permissions are configurable per account via accounts.json. The security model supports forbidden scopes and send_to recipient whitelists. See docs/SECURITY.md.

Security Model

  • Read-only accounts — Restrict accounts to read-only operations with --read-only (setup guide)
  • Configurable permissions — Each account defines allowed/forbidden scopes in accounts.json
  • Forbidden scopes — Block specific permissions (e.g., Mail.Send) at the config level
  • send_to whitelist — Restrict which recipients can receive mail from a given account
  • Defense-in-depth token validation — Tokens are inspected at runtime to enforce permission policy
  • Encrypted token cache — AES-256-GCM encryption, PBKDF2 SHA-512 with 310,000 iterations
  • Confirmation prompts — Write operations require confirmation (bypass with --yes for scripting)

See docs/SECURITY.md for the full threat model.

AI Agent Integration (OpenClaw / NanoClaw)

outlook-cli operates in two modes for AI agent integration:

  • Skill mode — Agents invoke CLI commands and parse JSON output
  • Channel Factory mode — Watch rules engine normalizes incoming emails to channel messages, delivered via stdout / webhook / exec / file
# OpenClaw — symlink as a skill
ln -s /path/to/outlook-cli/skill ~/.openclaw/skills/outlook
# NanoClaw — install in container
git clone https://github.com/jeffstall/outlook-cli.git /opt/outlook-cli
cd /opt/outlook-cli && npm install && npm link

See skill/SKILL.md and skill/NANOCLAW.md.

Configuration

Environment Variables

VariableDescriptionDefault
OUTLOOK_CLI_CLIENT_IDAzure app client ID(none)
OUTLOOK_CLI_TENANT_IDAzure AD tenant IDcommon
OUTLOOK_CLI_PASSPHRASEToken cache encryption passphraseMachine-derived
OUTLOOK_CLI_LOG_LEVELLogging levelwarn

Config Directory

All configuration is stored in ~/.outlook-cli/:

FilePurpose
accounts.jsonAccount definitions, permissions, defaults
aliases.jsonContact aliases
cache-*.encEncrypted MSAL token cache
delta-*.jsonWatch mode delta tokens
config.jsonOptional global configuration

Development

# Node.js
npm install
npm test# 160+ tests via vitest
node bin/outlook-cli.js --help
# .NET
dotnet build src/dotnet/OutlookCli.csproj
dotnet run --project src/dotnet -- --help
# Both (unified build script)
.\build.ps1 all

See docs/src-node.md, docs/src-dotnet.md, and docs/src-tests.md.

License

MIT — see LICENSE

About

Outlook CLI took for Claw environments

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages