- Python 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .gitignore | ||
| README.md | ||
| teams | ||
teams
CLI for Microsoft Teams (education tenant) over the internal web-client APIs and Microsoft Graph. No app registration, no admin consent. Interactive surface is a one-time device-code approval; everything after that is pure HTTP with silently rotating refresh tokens.
Reads class teams, channel posts, files (including Class Materials), assignments and calendar.
Install
git clone <repo> ~/teams-cli
ln -sf ~/teams-cli/teams ~/.local/bin/teams
Requirements: Python 3.12+ (stdlib only). The tenant ID is hardcoded for
my university — change TENANT at the top of the script to yours.
Auth
teams auth password # username + password, zero UI
teams auth login # device code, ~15s browser approval
Password login (ROPC) works if the tenant does not force MFA on it; on
AADSTS50076 fall back to the device code, which prints a code for
https://login.microsoft.com/device. Tokens land in ~/.local/share/teams-cli/auth.json — that
file is a live credential for your account, keep it out of sync/backup.
Graph tokens are minted locally from the stored refresh token via the Microsoft Office client. ic3 (posts) and the education assignments API tokens are minted through Teams desktop cross-client redemption. Every mint returns a fresh refresh token, so the chain renews itself — no re-login until the tenant password changes, an admin revokes, or long inactivity.
teams auth import <har> is an alternative bootstrap from a devtools HAR
export of teams.cloud.microsoft (useful when device-code is disabled by
Conditional Access).
teams auth status shows what is alive.
Usage
teams teams # list class teams
teams channels <team> # channels of a team
teams posts <team> [channel] [--limit N] # read channel posts
teams files <team> [-d DRIVE] [subpath] # list files
teams files <team> -d "Class Materials" \
-g "First Midterm/xxx.pdf" -o out.pdf # download a file
teams assignments [--limit N] [--classes] # assignments (* = turned in)
teams calendar [--days N] [--past N] # calendar events
Every command accepts --json for machine-readable output.
Team/channel selection is a case-insensitive substring match, diacritics
folded (podrska matches podrška).
How it works
- Teams list/channels/files/calendar: Microsoft Graph, delegated, minted from the refresh token.
- Channel posts: internal chatsvc (
teams.cloud.microsoft/api/chatsvc) with ic3-audience tokens. - Assignments: internal education API
(
assignments.edu.cloud.microsoft/api/v1.0/edu), audience8f348934-64be-4bb2-bc16-c54c96789f43, minted via Teams desktop client cross-redemption. - Device-code bootstrap uses the first-party Microsoft Office client
d3590ed6-52b3-4102-aeff-aad2292ab01c; no app registration or admin approval is involved anywhere.
Notes
- Messaging is read-only; sending goes through the same chatsvc endpoints and can be added.
- Direct-message chat lists ride the trouter websocket, not REST — not implemented.
- Graph education permissions are admin-blocked in locked tenants; the internal EDU API sidesteps that.
- Endpoints are undocumented and can change.
- Built and tested against a Singidunum University student tenant.