teams-cli 0.2.0__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. {teams_cli-0.2.0 → teams_cli-0.2.2}/.github/workflows/ci.yml +10 -0
  2. {teams_cli-0.2.0 → teams_cli-0.2.2}/CHANGELOG.md +45 -0
  3. {teams_cli-0.2.0 → teams_cli-0.2.2}/Cargo.lock +1 -1
  4. {teams_cli-0.2.0 → teams_cli-0.2.2}/Cargo.toml +3 -2
  5. {teams_cli-0.2.0 → teams_cli-0.2.2}/PKG-INFO +151 -20
  6. {teams_cli-0.2.0 → teams_cli-0.2.2}/README.md +150 -19
  7. {teams_cli-0.2.0 → teams_cli-0.2.2}/docs/releases.md +39 -0
  8. teams_cli-0.2.2/src/auth/pass.rs +494 -0
  9. teams_cli-0.2.2/src/auth/process.rs +81 -0
  10. teams_cli-0.2.2/src/auth/wsl.rs +152 -0
  11. teams_cli-0.2.2/src/auth/wsl_credentials.ps1 +46 -0
  12. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/auth.rs +250 -23
  13. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/backend.rs +13 -0
  14. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/cli.rs +37 -6
  15. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/config.rs +46 -0
  16. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/browser.rs +510 -57
  17. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/browser_install.rs +43 -1
  18. teams_cli-0.2.2/src/desktop/browser_setup.rs +138 -0
  19. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/connection.ps1 +34 -13
  20. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/connection.rs +60 -7
  21. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/helper.rs +3 -1
  22. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/owner.rs +98 -5
  23. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/session.rs +56 -8
  24. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/windows.rs +57 -1
  25. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop.rs +317 -19
  26. teams_cli-0.2.2/src/desktop_people.js +362 -0
  27. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/error.rs +1 -1
  28. teams_cli-0.2.2/src/graph.rs +777 -0
  29. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/lib.rs +1 -0
  30. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/main.rs +647 -128
  31. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/schema.rs +82 -10
  32. teams_cli-0.2.2/src/setup/capabilities.rs +178 -0
  33. teams_cli-0.2.2/src/setup.rs +1275 -0
  34. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/tui.rs +391 -3
  35. {teams_cli-0.2.0 → teams_cli-0.2.2}/tests/cli.rs +182 -3
  36. {teams_cli-0.2.0 → teams_cli-0.2.2}/tests/connection.test.ps1 +50 -14
  37. teams_cli-0.2.2/tests/credentials.rs +249 -0
  38. {teams_cli-0.2.0 → teams_cli-0.2.2}/tests/desktop.rs +4 -5
  39. teams_cli-0.2.2/tests/js/people.test.mjs +37 -0
  40. teams_cli-0.2.2/tests/pass_credentials.sh +24 -0
  41. teams_cli-0.2.2/tests/wsl_credentials.test.ps1 +35 -0
  42. teams_cli-0.2.0/src/graph.rs +0 -376
  43. {teams_cli-0.2.0 → teams_cli-0.2.2}/.github/workflows/dependencies.yml +0 -0
  44. {teams_cli-0.2.0 → teams_cli-0.2.2}/.github/workflows/release.yml +0 -0
  45. {teams_cli-0.2.0 → teams_cli-0.2.2}/.gitignore +0 -0
  46. {teams_cli-0.2.0 → teams_cli-0.2.2}/.mise.toml +0 -0
  47. {teams_cli-0.2.0 → teams_cli-0.2.2}/LICENSE +0 -0
  48. {teams_cli-0.2.0 → teams_cli-0.2.2}/Makefile +0 -0
  49. {teams_cli-0.2.0 → teams_cli-0.2.2}/build.rs +0 -0
  50. {teams_cli-0.2.0 → teams_cli-0.2.2}/examples/validate_schema.rs +0 -0
  51. {teams_cli-0.2.0 → teams_cli-0.2.2}/pyproject.toml +0 -0
  52. {teams_cli-0.2.0 → teams_cli-0.2.2}/scripts/smoke-release.py +0 -0
  53. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/delivery.rs +0 -0
  54. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/avatars.rs +0 -0
  55. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/browser_core.rs +0 -0
  56. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/cdp.rs +0 -0
  57. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/install.rs +0 -0
  58. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop/macos.rs +0 -0
  59. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop.js +0 -0
  60. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop_cache.js +0 -0
  61. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop_core.js +0 -0
  62. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/desktop_send.js +0 -0
  63. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/output.rs +0 -0
  64. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/render.rs +0 -0
  65. {teams_cli-0.2.0 → teams_cli-0.2.2}/src/teams_cli_alias.rs +0 -0
  66. {teams_cli-0.2.0 → teams_cli-0.2.2}/tests/connection.rs +0 -0
  67. {teams_cli-0.2.0 → teams_cli-0.2.2}/tests/desktop_scripts.rs +0 -0
  68. {teams_cli-0.2.0 → teams_cli-0.2.2}/tests/desktop_scripts.test.cjs +0 -0
  69. {teams_cli-0.2.0 → teams_cli-0.2.2}/tests/fixtures/clispec-v0.3.json +0 -0
  70. {teams_cli-0.2.0 → teams_cli-0.2.2}/tests/package_alias.rs +0 -0
  71. {teams_cli-0.2.0 → teams_cli-0.2.2}/tests/release_smoke.rs +0 -0
  72. {teams_cli-0.2.0 → teams_cli-0.2.2}/vership.toml +0 -0
@@ -24,6 +24,16 @@ jobs:
24
24
  components: rustfmt, clippy
25
25
  - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
26
26
  - run: cargo test --locked --all-targets
27
+ - name: Verify pass and GPG credential encryption
28
+ if: runner.os == 'Linux'
29
+ run: |
30
+ sudo apt-get update -qq
31
+ sudo apt-get install -y --no-install-recommends pass
32
+ bash tests/pass_credentials.sh
33
+ - name: Verify WSL credential encryption
34
+ if: runner.os == 'Windows'
35
+ shell: powershell
36
+ run: ./tests/wsl_credentials.test.ps1
27
37
 
28
38
  quality:
29
39
  name: Formatting and lints
@@ -7,6 +7,51 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.2](https://github.com/rvben/teams-cli/compare/v0.2.1...v0.2.2) - 2026-10-15
11
+
12
+ ### Added
13
+
14
+ - Guided `teams init` asks for Work/school or Personal, chooses a separate browser port, offers explicit send permission, and opens the inbox after verified sign-in.
15
+ - Browser setup can opt in to reopening its saved session with `teams`; existing profiles, native Teams and scripted reads keep their connection behaviour. Explicit setup supports `--auto-start`.
16
+ - Offer initialized `pass` stores during new Graph setup on Linux, WSL and macOS, with explicit `--credential-store pass` and `--pass-store-dir` options. Save the backend and absolute directory per profile, verify GPG encryption/decryption before sign-in, and preserve encrypted credentials on failed updates.
17
+
18
+ ### Fixed
19
+
20
+ - Report credential-helper failures distinctly from missing sign-ins; bound helper operations and preserve the chosen backend across sign-in, refresh and logout.
21
+ - Store WSL Graph credentials with Windows DPAPI through PowerShell, so callback and device-code sign-in, token refresh, and logout do not require D-Bus or Secret Service.
22
+
23
+ ### Changed
24
+
25
+ - Guided setup offers separate accounts or explicit connection updates, preserves Graph registration and channel-history access, resumes interrupted browser sign-in on the original port, and verifies fresh Graph credentials before saving them with rollback on config failure.
26
+ - Cold work-browser inbox startup checks sign-in renewal in the background; failures pause sending and offer sign-in while preserving drafts. First-run `teams tui` uses guided setup, including headless Graph recovery and environment-override checks.
27
+ - Guided setup checks local browser/display support, Teams installation and Windows interop, and matching lightweight browser downloads before allowing a connection choice. Unavailable options explain their requirements; supported alternatives are selected automatically.
28
+ - Guided Graph setup verifies chat access before saving connection settings. Desktop/browser sending opt-in now requires a send-interface probe; guided setup offers an explicit read-only alternative if it fails, without sending a test message.
29
+ - Reject personal-only lightweight browser/work-school combinations before saving even with `--no-login`.
30
+
31
+ ## [0.2.1](https://github.com/rvben/teams-cli/compare/v0.2.0...v0.2.1) - 2026-10-15
32
+
33
+ ### Added
34
+
35
+ - **desktop**: add `teams desktop clear-flags` and a confirmed TUI cleanup that remove remote-debugging flags from the user-wide WebView2 setting while keeping its other arguments.
36
+ - Search people by name or email and create or reuse a one-to-one conversation with `people search` and `chats create --recipient ID --yes`. Opening a conversation never sends a message.
37
+ - Support these operations through the selected personal or work/school desktop account and through Microsoft Graph. Graph search requires a new sign-in to consent to `User.ReadBasic.All`.
38
+
39
+ ### Changed
40
+
41
+ - Windows desktop helpers use protocol 4. WSL requires the helper from the same CLI release.
42
+ - Ambiguous conversation-creation outcomes remain unconfirmed and are never automatically retried.
43
+ - Personal-account searches put verified live matches first and filter unrelated recent-contact suggestions before applying the result limit.
44
+
45
+ ### Fixed
46
+
47
+ - **desktop**: pass the debugging flags only to the Teams launch on Windows and WSL, so other WebView2 apps such as Outlook no longer open the debugging port.
48
+ - **desktop**: name the application that holds a refused port and report a user-wide debugging setting as the cause.
49
+ - **desktop**: recognise the dedicated browser on Linux and WSL when Chrome rewrites its process title, so setup no longer stops with "did not open its debugging endpoint"; recovery hints now name the browser mode and port in use.
50
+ - **desktop**: keep the work/school browser visible when the organisation's sign-in (such as AD FS with Windows sign-in) does not let Teams stay signed in headless, instead of reporting success and then losing the session; reads now say when Teams was sent back to sign-in, and setup reports whether the browser runs headless or visible.
51
+ - **desktop**: stop a verified dedicated browser that hangs after closing its debugging port, so disconnect and recover no longer leave it running.
52
+ - **desktop**: refuse sign-in success when the browser closes or loses verified ownership during the sign-in check, and verify reads again after observing work-account sign-in.
53
+ - **desktop**: separate email lookup from name search ([b0647f1](https://github.com/rvben/teams-cli/commit/b0647f177c3f4cb5f73e74f42aed11078832e632))
54
+
10
55
  ## [0.2.0](https://github.com/rvben/teams-cli/compare/v0.1.13...v0.2.0) - 2026-10-14
11
56
 
12
57
  ### Added
@@ -3187,7 +3187,7 @@ dependencies = [
3187
3187
 
3188
3188
  [[package]]
3189
3189
  name = "teams-cli"
3190
- version = "0.2.0"
3190
+ version = "0.2.2"
3191
3191
  dependencies = [
3192
3192
  "assert_cmd",
3193
3193
  "base64 0.23.1",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "teams-cli"
3
- version = "0.2.0"
3
+ version = "0.2.2"
4
4
  edition = "2024"
5
5
  rust-version = "1.90"
6
6
  description = "A Microsoft Teams CLI and TUI designed equally for humans and agents"
@@ -56,10 +56,11 @@ windows-sys = { version = "0.61", features = [
56
56
  "Win32_Security",
57
57
  "Win32_Storage_Packaging_Appx",
58
58
  "Win32_System_Diagnostics_ToolHelp",
59
+ "Win32_System_Registry",
59
60
  "Win32_System_Threading",
60
61
  ] }
61
62
 
62
- [target.'cfg(target_os = "macos")'.dependencies]
63
+ [target.'cfg(unix)'.dependencies]
63
64
  libc = "0.2"
64
65
 
65
66
  [dev-dependencies]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: teams-cli
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  License-File: LICENSE
@@ -62,27 +62,80 @@ Run `teams` in a terminal on first use, or start explicitly:
62
62
  teams init
63
63
  ```
64
64
 
65
- `teams-cli` includes a maintained multitenant Microsoft Entra public-client registration, so normal setup does not require creating an app or copying a client ID:
65
+ Choose **Work or school** or **Personal**, choose whether to enable sending, and
66
+ follow sign-in. Setup checks this machine first and gives unavailable connections
67
+ no selectable number, with an explanation of what they need. It chooses a separate
68
+ browser port and opens your inbox once chats are readable. After that, just run:
66
69
 
67
70
  ```console
68
- teams init
71
+ teams
69
72
  ```
70
73
 
71
- For a personal Microsoft account with the lightweight hidden browser:
74
+ On macOS, Linux and WSL2, work/school setup prefers a dedicated browser; personal
75
+ setup prefers the lightweight browser. Missing display support, missing executables,
76
+ invalid browser overrides and unavailable matching downloads are checked before
77
+ selection. Personal can use a full browser or Teams Desktop when lightweight mode
78
+ is unavailable. Work/school can use Teams Desktop or Microsoft Graph when needed.
79
+ When no lightweight runtime is installed, these checks query public Chrome for
80
+ Testing version metadata at `googlechromelabs.github.io`; no browser download or
81
+ Teams sign-in happens before consent.
82
+ On a Linux terminal without a display, Graph uses device-code sign-in on another device.
83
+ You explicitly approve reopening a dedicated browser
84
+ when you start the inbox. The saved sign-in is reused, and expired work/school
85
+ sign-in offers to reopen the sign-in window. Some organisations require keeping
86
+ the browser visible; minimise it instead of closing it. WSL2 needs WSLg for sign-in.
87
+ On native Windows, browser options are unavailable; use Teams Desktop or run inside
88
+ WSL2 for browser mode.
89
+
90
+ Guided setup saves connection settings only after a successful chat read, including
91
+ Graph profiles. If sending was requested, desktop/browser setup also probes the
92
+ send interface without sending a message. If that fails, you can explicitly continue
93
+ read-only; setup never silently downgrades your choice. A successful probe establishes
94
+ that the interface is available, while delivery and organisation policies are checked
95
+ when you actually send. Teams build compatibility and sign-in still need live validation.
96
+
97
+ Running setup again asks whether to connect another account or update an existing
98
+ connection. Updates preserve Graph application/tenant settings and previously granted
99
+ channel-history access. Failed Graph verification preserves the previous credential;
100
+ if saving settings fails, the credential change is rolled back. Browser setup can resume
101
+ an unfinished sign-in on the same port, or start a separate account without touching it.
102
+ Recovery errors include the exact command to close that browser.
103
+ You can forget an unfinished setup after confirmation; its browser data and saved
104
+ sign-in remain on disk, and the old browser's close command is shown. Reusing that
105
+ forgotten browser data requires explicit setup with its original `--desktop-port`.
106
+ Setup offers unfinished connections under other names when you connect another account.
107
+
108
+ Cold work-browser startup opens the inbox once chats are readable and checks sign-in
109
+ renewal in the background. A sign-out pauses sending and offers sign-in in the inbox.
110
+ Other startup-check failures keep chats readable and pause sending until you reopen
111
+ the inbox to check again. Drafts stay in memory through the sign-in detour.
112
+ Guided Graph setup disables conflicting token or permission environment overrides;
113
+ explicit flags keep their automation behavior.
114
+
115
+ **Other connection options** keeps Microsoft Graph and the running Teams Desktop
116
+ available. Microsoft Graph includes a maintained Entra public-client registration,
117
+ so normal API setup needs no app registration or copied client ID.
118
+
119
+ Scripts and explicit connection flags keep their existing behaviour. For example:
72
120
 
73
121
  ```console
74
- teams init --profile personal --backend desktop --desktop-client browser-core
122
+ teams init --backend graph
123
+ # Or configure an automatically reopened work browser explicitly:
124
+ teams init --profile work --backend desktop --desktop-client browser \
125
+ --desktop-account work-school --desktop-port 9224 --auto-start
75
126
  ```
76
127
 
77
- This downloads its browsers automatically, opens visible sign-in once, and then
78
- runs hidden. See [lightweight browser setup](#low-memory-browser-client-experimental)
79
- for sending, reconnecting, and experimental compatibility limits.
128
+ Browser profiles default to read-only; add `--allow-send` to enable sending.
129
+ Existing profiles retain their connection behaviour unless you opt in with setup
130
+ or `--auto-start`. CLI reads, JSON output, demo mode and snapshots never start a
131
+ browser automatically. See [lightweight browser setup](#low-memory-browser-client-experimental)
132
+ for personal-account compatibility limits.
80
133
 
81
- Browser PKCE is the human-friendly default. The browser talks directly to Microsoft, and the CLI never receives or stores your password. Normal sign-in requests these delegated scopes:
134
+ For Microsoft Graph profiles, browser PKCE is the default when a local browser is available. The browser talks directly to Microsoft, and the CLI never receives or stores your password. Normal Graph sign-in requests these delegated scopes:
82
135
 
83
136
  ```text
84
- openid profile offline_access User.Read Team.ReadBasic.All
85
- Channel.ReadBasic.All Chat.Read Chat.Create ChatMessage.Send
137
+ openid profile offline_access User.Read User.ReadBasic.All
138
+ Team.ReadBasic.All Channel.ReadBasic.All Chat.Read Chat.Create ChatMessage.Send
86
139
  ChannelMessage.Send
87
140
  ```
88
141
 
@@ -157,12 +210,59 @@ The custom app must be a public client with `http://localhost` registered for br
157
210
 
158
211
  For short-lived automation, `TEAMS_ACCESS_TOKEN` overrides the stored credential. Refresh credentials are never written to the config file.
159
212
 
213
+ Under WSL, Graph credentials use Windows DPAPI encryption for the current Windows
214
+ user through `powershell.exe`; no D-Bus or Linux Secret Service is required. Windows
215
+ executable interop must be enabled. Encrypted files live under
216
+ `%LOCALAPPDATA%\teams-cli\credentials` and are shared by WSL distributions using
217
+ the same Windows account and profile name. Existing WSL Secret Service sign-ins
218
+ require `teams auth login` again after upgrading; their old entries are not migrated
219
+ or removed. Native Linux uses Secret Service by default.
220
+
221
+ ### Using pass for Graph credentials
222
+
223
+ On Linux, WSL and macOS, interactive Graph setup offers `pass` when it is installed
224
+ and the selected password store has a readable `.gpg-id`. The OS store is recommended
225
+ when available; if it is unavailable, setup recommends the configured pass store.
226
+ Existing profiles keep their saved credential store without prompting again.
227
+
228
+ To select it explicitly, initialize your GPG password store first, then run:
229
+
230
+ ```console
231
+ pass init GPG_KEY_ID
232
+ teams --profile work-pass init --credential-store pass --device-code
233
+ # To use a different existing store:
234
+ teams --profile other-work init --credential-store pass --pass-store-dir /path/to/password-store --device-code
235
+ ```
236
+
237
+ Before opening Microsoft sign-in for a new pass credential, the CLI checks encryption
238
+ and decryption using synthetic data in a private temporary store. The check leaves
239
+ no probe entries or Git commits in your password store. GPG may ask you to unlock
240
+ your key; configure `gpg-agent` and a suitable pinentry for your terminal or desktop.
241
+ Terminal pinentry may need `export GPG_TTY="$(tty)"`. Helper operations time out after
242
+ 60 seconds if unlocking or another operation stalls.
243
+
244
+ Tokens are passed to `pass` through stdin, and stored under
245
+ `teams-cli/<SHA-256 of profile name>`. The CLI saves `credential_store = "pass"` and
246
+ the absolute `pass_store_dir` in the profile. Changing `PASSWORD_STORE_DIR` later
247
+ will not redirect that profile's credentials. Sign-in, refresh, status and logout
248
+ use the same saved store; failures report the store or GPG problem without falling
249
+ back to another backend. Failed replacements restore the previous encrypted file.
250
+ As usual, pass manages its own local Git history if enabled; logout removes the
251
+ current entry, while older encrypted versions may remain in that history.
252
+
253
+ Use a new profile name to change credential stores or pass directories. After
254
+ verifying the new connection, sign out the old profile if you no longer need it.
255
+ `--no-login` validates the pass installation and recipient configuration without
256
+ unlocking a key or running the encryption/decryption check.
257
+
160
258
  ## Everyday commands
161
259
 
162
260
  ```console
163
261
  teams list
164
262
  teams channels list TEAM_ID
165
263
  teams chats list --limit 25
264
+ teams people search "Alex" --limit 20
265
+ teams chats create --recipient PERSON_ID --yes # no message is sent
166
266
  teams messages list --chat CHAT_ID
167
267
  teams auth login --channel-history # once, with administrator approval
168
268
  teams messages list --team TEAM_ID --channel CHANNEL_ID
@@ -178,7 +278,21 @@ teams config path
178
278
  teams doctor --offline
179
279
  ```
180
280
 
181
- Collection commands expose `--limit` and `--fields`; Graph-native collections use `--cursor`, while joined teams and channels use `--offset` because those endpoints do not accept `$top`. With a terminal they render concise text; when stdout is piped they emit JSON envelopes with continuation metadata and `truncated`.
281
+ Chat, message, team and channel collections expose `--limit` and `--fields`; Graph-native collections use `--cursor`, while joined teams and channels use `--offset` because those endpoints do not accept `$top`. With a terminal they render concise text; when stdout is piped they emit JSON envelopes with continuation metadata and `truncated`.
282
+
283
+ To message someone for the first time, use `people search` to find their verified
284
+ identity in the active profile. Search accepts a name or email prefix of 2–256
285
+ characters and returns at most 50 people; refine the query if `truncated` is true.
286
+ Pass the exact returned ID to `chats create`, then pass the resulting chat ID to
287
+ `messages send`. Creating a conversation reuses an existing one-to-one chat when
288
+ available and sends no message. It requires a writable profile and confirmation
289
+ (`--yes` for automation). Recipient IDs belong to their selected account/backend.
290
+ If creation is unconfirmed, inspect your chats before trying again.
291
+
292
+ Graph recipient search needs delegated `User.ReadBasic.All` consent. Existing
293
+ sign-ins can keep reading chats; run `teams auth login` again to enable directory
294
+ search. Your organization may restrict consent, directory guest access, external
295
+ recipients or chat creation. Personal accounts use the desktop backend.
182
296
 
183
297
  Profiles can block every remote write while keeping reads, sign-in, diagnostics, and the TUI available:
184
298
 
@@ -273,7 +387,9 @@ paste; `r` checks delivery, `s` offers an explicit second-copy confirmation, and
273
387
  `esc` keeps the draft and uncertainty together in memory. Reopening it does not
274
388
  unlock ordinary sending. Queued results are labelled queued rather than sent.
275
389
 
276
- Desktop cannot create new chats. Teams, channels, identity commands, subscriptions,
390
+ Desktop supports people search and one-to-one chat creation through the selected
391
+ Teams client's own session. Creation requires a profile with `--allow-send` and
392
+ sends no message. Teams, channels, identity commands, subscriptions,
277
393
  replies, mentions, attachments and edits return `unsupported` on desktop. The TUI
278
394
  reads chats from the same cache and sends through the same path as `messages send`.
279
395
  Existing profiles without a backend field
@@ -295,15 +411,22 @@ Added auxiliary processes are left alone. If Teams was
295
411
  restarted independently, quit and relaunch it normally, then disconnect again to
296
412
  clear the old record. No command automatically restarts Teams on exit.
297
413
 
298
- On macOS, flags apply only to the managed launch. On Windows/WSL, setup saves the
299
- previous user environment value, applies flags temporarily while Teams starts, then
300
- restores that value. Unrelated changes to the value are preserved and reported.
414
+ Debugging flags apply only to the managed Teams launch; other apps and the user
415
+ environment are left unchanged. On Windows/WSL, Teams starts through its
416
+ `ms-teams.exe` app execution alias, which must be enabled (Settings > Apps >
417
+ Advanced app settings > App execution aliases). Connect refuses a user-wide
418
+ `WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS` that already has debugging flags: such a
419
+ setting opens the port in every WebView2 app, for example Outlook, and the
420
+ listener is then refused because Teams does not own it. Errors name those apps.
421
+ `teams desktop clear-flags` removes only the debugging flags from that setting
422
+ after confirmation (`--yes` when scripted); quit and reopen the named apps
423
+ afterwards. The TUI offers the same cleanup.
301
424
  Windows and WSL share a recovery record and lock. WSL finds PowerShell in its normal
302
425
  Windows system directory even when Windows PATH entries are disabled; Windows
303
426
  executable interop must still be enabled.
304
427
 
305
- If setup is interrupted, run `teams --profile local desktop recover`. It restores
306
- pending settings without restarting Teams or requiring the Windows helper; it does
428
+ If setup is interrupted, run `teams --profile local desktop recover`. It clears the
429
+ interrupted record (and restores settings left by older versions) without restarting Teams or requiring the Windows helper; it does
307
430
  not claim ownership of an unrecorded Teams process. Use `desktop status` to inspect
308
431
  the endpoint and saved session. Recovery cannot close an already-running debugging
309
432
  endpoint: quit Teams and relaunch it normally if its ownership was not recorded.
@@ -389,7 +512,7 @@ helper route remains the default for native desktop profiles.
389
512
  Create a separate read-only profile and sign in in the window that opens:
390
513
 
391
514
  ```console
392
- teams init --profile browser --backend desktop --desktop-client browser --desktop-account work-school --yes
515
+ teams init --profile browser --backend desktop --desktop-client browser --desktop-account work-school --auto-start --yes
393
516
  # The window closes automatically after a successful chat read.
394
517
  # Teams then runs headless with the same saved sign-in:
395
518
  teams --profile browser
@@ -403,6 +526,13 @@ A sign-in timeout leaves the visible window open; finish signing in and retry
403
526
  `desktop login`. Interrupting login preserves the browser and its saved profile.
404
527
  On WSL2, the visible step needs WSLg or another graphical display.
405
528
 
529
+ Some organisations sign in through their own identity provider (for example AD FS
530
+ with Windows sign-in) and do not let Teams renew its sign-in in a headless browser.
531
+ For work/school accounts, login therefore watches the headless browser for up to a
532
+ minute; when Teams is sent back to sign-in, the visible browser is reopened and stays
533
+ open instead. Minimise that window, but keep it open. When a headless session is sent
534
+ back to sign-in later, reads report it; run `desktop login` again.
535
+
406
536
  Use `--desktop-account personal` for a personal Microsoft account. Sending still
407
537
  requires an explicit `init --allow-send` and the existing send confirmation.
408
538
  `init --no-login` only saves configuration. `desktop connect --visible` remains
@@ -413,7 +543,8 @@ The browser uses its own profile under the local data directory at
413
543
  profile. Different ports use different browser profiles. Disconnect closes this
414
544
  browser and keeps its sign-in data. To switch between visible and headless operation,
415
545
  disconnect first. `desktop recover` closes a verified managed browser or clears a
416
- stale record when no listener remains. Unverifiable processes are left untouched.
546
+ stale record when no listener remains. A verified browser that does not exit after
547
+ closing its debugging port is stopped; unverifiable processes are left untouched.
417
548
 
418
549
  The CLI checks that every listener is loopback-only and belongs to the recorded
419
550
  browser process, running as you with the expected executable, debugging port and
@@ -46,27 +46,80 @@ Run `teams` in a terminal on first use, or start explicitly:
46
46
  teams init
47
47
  ```
48
48
 
49
- `teams-cli` includes a maintained multitenant Microsoft Entra public-client registration, so normal setup does not require creating an app or copying a client ID:
49
+ Choose **Work or school** or **Personal**, choose whether to enable sending, and
50
+ follow sign-in. Setup checks this machine first and gives unavailable connections
51
+ no selectable number, with an explanation of what they need. It chooses a separate
52
+ browser port and opens your inbox once chats are readable. After that, just run:
50
53
 
51
54
  ```console
52
- teams init
55
+ teams
53
56
  ```
54
57
 
55
- For a personal Microsoft account with the lightweight hidden browser:
58
+ On macOS, Linux and WSL2, work/school setup prefers a dedicated browser; personal
59
+ setup prefers the lightweight browser. Missing display support, missing executables,
60
+ invalid browser overrides and unavailable matching downloads are checked before
61
+ selection. Personal can use a full browser or Teams Desktop when lightweight mode
62
+ is unavailable. Work/school can use Teams Desktop or Microsoft Graph when needed.
63
+ When no lightweight runtime is installed, these checks query public Chrome for
64
+ Testing version metadata at `googlechromelabs.github.io`; no browser download or
65
+ Teams sign-in happens before consent.
66
+ On a Linux terminal without a display, Graph uses device-code sign-in on another device.
67
+ You explicitly approve reopening a dedicated browser
68
+ when you start the inbox. The saved sign-in is reused, and expired work/school
69
+ sign-in offers to reopen the sign-in window. Some organisations require keeping
70
+ the browser visible; minimise it instead of closing it. WSL2 needs WSLg for sign-in.
71
+ On native Windows, browser options are unavailable; use Teams Desktop or run inside
72
+ WSL2 for browser mode.
73
+
74
+ Guided setup saves connection settings only after a successful chat read, including
75
+ Graph profiles. If sending was requested, desktop/browser setup also probes the
76
+ send interface without sending a message. If that fails, you can explicitly continue
77
+ read-only; setup never silently downgrades your choice. A successful probe establishes
78
+ that the interface is available, while delivery and organisation policies are checked
79
+ when you actually send. Teams build compatibility and sign-in still need live validation.
80
+
81
+ Running setup again asks whether to connect another account or update an existing
82
+ connection. Updates preserve Graph application/tenant settings and previously granted
83
+ channel-history access. Failed Graph verification preserves the previous credential;
84
+ if saving settings fails, the credential change is rolled back. Browser setup can resume
85
+ an unfinished sign-in on the same port, or start a separate account without touching it.
86
+ Recovery errors include the exact command to close that browser.
87
+ You can forget an unfinished setup after confirmation; its browser data and saved
88
+ sign-in remain on disk, and the old browser's close command is shown. Reusing that
89
+ forgotten browser data requires explicit setup with its original `--desktop-port`.
90
+ Setup offers unfinished connections under other names when you connect another account.
91
+
92
+ Cold work-browser startup opens the inbox once chats are readable and checks sign-in
93
+ renewal in the background. A sign-out pauses sending and offers sign-in in the inbox.
94
+ Other startup-check failures keep chats readable and pause sending until you reopen
95
+ the inbox to check again. Drafts stay in memory through the sign-in detour.
96
+ Guided Graph setup disables conflicting token or permission environment overrides;
97
+ explicit flags keep their automation behavior.
98
+
99
+ **Other connection options** keeps Microsoft Graph and the running Teams Desktop
100
+ available. Microsoft Graph includes a maintained Entra public-client registration,
101
+ so normal API setup needs no app registration or copied client ID.
102
+
103
+ Scripts and explicit connection flags keep their existing behaviour. For example:
56
104
 
57
105
  ```console
58
- teams init --profile personal --backend desktop --desktop-client browser-core
106
+ teams init --backend graph
107
+ # Or configure an automatically reopened work browser explicitly:
108
+ teams init --profile work --backend desktop --desktop-client browser \
109
+ --desktop-account work-school --desktop-port 9224 --auto-start
59
110
  ```
60
111
 
61
- This downloads its browsers automatically, opens visible sign-in once, and then
62
- runs hidden. See [lightweight browser setup](#low-memory-browser-client-experimental)
63
- for sending, reconnecting, and experimental compatibility limits.
112
+ Browser profiles default to read-only; add `--allow-send` to enable sending.
113
+ Existing profiles retain their connection behaviour unless you opt in with setup
114
+ or `--auto-start`. CLI reads, JSON output, demo mode and snapshots never start a
115
+ browser automatically. See [lightweight browser setup](#low-memory-browser-client-experimental)
116
+ for personal-account compatibility limits.
64
117
 
65
- Browser PKCE is the human-friendly default. The browser talks directly to Microsoft, and the CLI never receives or stores your password. Normal sign-in requests these delegated scopes:
118
+ For Microsoft Graph profiles, browser PKCE is the default when a local browser is available. The browser talks directly to Microsoft, and the CLI never receives or stores your password. Normal Graph sign-in requests these delegated scopes:
66
119
 
67
120
  ```text
68
- openid profile offline_access User.Read Team.ReadBasic.All
69
- Channel.ReadBasic.All Chat.Read Chat.Create ChatMessage.Send
121
+ openid profile offline_access User.Read User.ReadBasic.All
122
+ Team.ReadBasic.All Channel.ReadBasic.All Chat.Read Chat.Create ChatMessage.Send
70
123
  ChannelMessage.Send
71
124
  ```
72
125
 
@@ -141,12 +194,59 @@ The custom app must be a public client with `http://localhost` registered for br
141
194
 
142
195
  For short-lived automation, `TEAMS_ACCESS_TOKEN` overrides the stored credential. Refresh credentials are never written to the config file.
143
196
 
197
+ Under WSL, Graph credentials use Windows DPAPI encryption for the current Windows
198
+ user through `powershell.exe`; no D-Bus or Linux Secret Service is required. Windows
199
+ executable interop must be enabled. Encrypted files live under
200
+ `%LOCALAPPDATA%\teams-cli\credentials` and are shared by WSL distributions using
201
+ the same Windows account and profile name. Existing WSL Secret Service sign-ins
202
+ require `teams auth login` again after upgrading; their old entries are not migrated
203
+ or removed. Native Linux uses Secret Service by default.
204
+
205
+ ### Using pass for Graph credentials
206
+
207
+ On Linux, WSL and macOS, interactive Graph setup offers `pass` when it is installed
208
+ and the selected password store has a readable `.gpg-id`. The OS store is recommended
209
+ when available; if it is unavailable, setup recommends the configured pass store.
210
+ Existing profiles keep their saved credential store without prompting again.
211
+
212
+ To select it explicitly, initialize your GPG password store first, then run:
213
+
214
+ ```console
215
+ pass init GPG_KEY_ID
216
+ teams --profile work-pass init --credential-store pass --device-code
217
+ # To use a different existing store:
218
+ teams --profile other-work init --credential-store pass --pass-store-dir /path/to/password-store --device-code
219
+ ```
220
+
221
+ Before opening Microsoft sign-in for a new pass credential, the CLI checks encryption
222
+ and decryption using synthetic data in a private temporary store. The check leaves
223
+ no probe entries or Git commits in your password store. GPG may ask you to unlock
224
+ your key; configure `gpg-agent` and a suitable pinentry for your terminal or desktop.
225
+ Terminal pinentry may need `export GPG_TTY="$(tty)"`. Helper operations time out after
226
+ 60 seconds if unlocking or another operation stalls.
227
+
228
+ Tokens are passed to `pass` through stdin, and stored under
229
+ `teams-cli/<SHA-256 of profile name>`. The CLI saves `credential_store = "pass"` and
230
+ the absolute `pass_store_dir` in the profile. Changing `PASSWORD_STORE_DIR` later
231
+ will not redirect that profile's credentials. Sign-in, refresh, status and logout
232
+ use the same saved store; failures report the store or GPG problem without falling
233
+ back to another backend. Failed replacements restore the previous encrypted file.
234
+ As usual, pass manages its own local Git history if enabled; logout removes the
235
+ current entry, while older encrypted versions may remain in that history.
236
+
237
+ Use a new profile name to change credential stores or pass directories. After
238
+ verifying the new connection, sign out the old profile if you no longer need it.
239
+ `--no-login` validates the pass installation and recipient configuration without
240
+ unlocking a key or running the encryption/decryption check.
241
+
144
242
  ## Everyday commands
145
243
 
146
244
  ```console
147
245
  teams list
148
246
  teams channels list TEAM_ID
149
247
  teams chats list --limit 25
248
+ teams people search "Alex" --limit 20
249
+ teams chats create --recipient PERSON_ID --yes # no message is sent
150
250
  teams messages list --chat CHAT_ID
151
251
  teams auth login --channel-history # once, with administrator approval
152
252
  teams messages list --team TEAM_ID --channel CHANNEL_ID
@@ -162,7 +262,21 @@ teams config path
162
262
  teams doctor --offline
163
263
  ```
164
264
 
165
- Collection commands expose `--limit` and `--fields`; Graph-native collections use `--cursor`, while joined teams and channels use `--offset` because those endpoints do not accept `$top`. With a terminal they render concise text; when stdout is piped they emit JSON envelopes with continuation metadata and `truncated`.
265
+ Chat, message, team and channel collections expose `--limit` and `--fields`; Graph-native collections use `--cursor`, while joined teams and channels use `--offset` because those endpoints do not accept `$top`. With a terminal they render concise text; when stdout is piped they emit JSON envelopes with continuation metadata and `truncated`.
266
+
267
+ To message someone for the first time, use `people search` to find their verified
268
+ identity in the active profile. Search accepts a name or email prefix of 2–256
269
+ characters and returns at most 50 people; refine the query if `truncated` is true.
270
+ Pass the exact returned ID to `chats create`, then pass the resulting chat ID to
271
+ `messages send`. Creating a conversation reuses an existing one-to-one chat when
272
+ available and sends no message. It requires a writable profile and confirmation
273
+ (`--yes` for automation). Recipient IDs belong to their selected account/backend.
274
+ If creation is unconfirmed, inspect your chats before trying again.
275
+
276
+ Graph recipient search needs delegated `User.ReadBasic.All` consent. Existing
277
+ sign-ins can keep reading chats; run `teams auth login` again to enable directory
278
+ search. Your organization may restrict consent, directory guest access, external
279
+ recipients or chat creation. Personal accounts use the desktop backend.
166
280
 
167
281
  Profiles can block every remote write while keeping reads, sign-in, diagnostics, and the TUI available:
168
282
 
@@ -257,7 +371,9 @@ paste; `r` checks delivery, `s` offers an explicit second-copy confirmation, and
257
371
  `esc` keeps the draft and uncertainty together in memory. Reopening it does not
258
372
  unlock ordinary sending. Queued results are labelled queued rather than sent.
259
373
 
260
- Desktop cannot create new chats. Teams, channels, identity commands, subscriptions,
374
+ Desktop supports people search and one-to-one chat creation through the selected
375
+ Teams client's own session. Creation requires a profile with `--allow-send` and
376
+ sends no message. Teams, channels, identity commands, subscriptions,
261
377
  replies, mentions, attachments and edits return `unsupported` on desktop. The TUI
262
378
  reads chats from the same cache and sends through the same path as `messages send`.
263
379
  Existing profiles without a backend field
@@ -279,15 +395,22 @@ Added auxiliary processes are left alone. If Teams was
279
395
  restarted independently, quit and relaunch it normally, then disconnect again to
280
396
  clear the old record. No command automatically restarts Teams on exit.
281
397
 
282
- On macOS, flags apply only to the managed launch. On Windows/WSL, setup saves the
283
- previous user environment value, applies flags temporarily while Teams starts, then
284
- restores that value. Unrelated changes to the value are preserved and reported.
398
+ Debugging flags apply only to the managed Teams launch; other apps and the user
399
+ environment are left unchanged. On Windows/WSL, Teams starts through its
400
+ `ms-teams.exe` app execution alias, which must be enabled (Settings > Apps >
401
+ Advanced app settings > App execution aliases). Connect refuses a user-wide
402
+ `WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS` that already has debugging flags: such a
403
+ setting opens the port in every WebView2 app, for example Outlook, and the
404
+ listener is then refused because Teams does not own it. Errors name those apps.
405
+ `teams desktop clear-flags` removes only the debugging flags from that setting
406
+ after confirmation (`--yes` when scripted); quit and reopen the named apps
407
+ afterwards. The TUI offers the same cleanup.
285
408
  Windows and WSL share a recovery record and lock. WSL finds PowerShell in its normal
286
409
  Windows system directory even when Windows PATH entries are disabled; Windows
287
410
  executable interop must still be enabled.
288
411
 
289
- If setup is interrupted, run `teams --profile local desktop recover`. It restores
290
- pending settings without restarting Teams or requiring the Windows helper; it does
412
+ If setup is interrupted, run `teams --profile local desktop recover`. It clears the
413
+ interrupted record (and restores settings left by older versions) without restarting Teams or requiring the Windows helper; it does
291
414
  not claim ownership of an unrecorded Teams process. Use `desktop status` to inspect
292
415
  the endpoint and saved session. Recovery cannot close an already-running debugging
293
416
  endpoint: quit Teams and relaunch it normally if its ownership was not recorded.
@@ -373,7 +496,7 @@ helper route remains the default for native desktop profiles.
373
496
  Create a separate read-only profile and sign in in the window that opens:
374
497
 
375
498
  ```console
376
- teams init --profile browser --backend desktop --desktop-client browser --desktop-account work-school --yes
499
+ teams init --profile browser --backend desktop --desktop-client browser --desktop-account work-school --auto-start --yes
377
500
  # The window closes automatically after a successful chat read.
378
501
  # Teams then runs headless with the same saved sign-in:
379
502
  teams --profile browser
@@ -387,6 +510,13 @@ A sign-in timeout leaves the visible window open; finish signing in and retry
387
510
  `desktop login`. Interrupting login preserves the browser and its saved profile.
388
511
  On WSL2, the visible step needs WSLg or another graphical display.
389
512
 
513
+ Some organisations sign in through their own identity provider (for example AD FS
514
+ with Windows sign-in) and do not let Teams renew its sign-in in a headless browser.
515
+ For work/school accounts, login therefore watches the headless browser for up to a
516
+ minute; when Teams is sent back to sign-in, the visible browser is reopened and stays
517
+ open instead. Minimise that window, but keep it open. When a headless session is sent
518
+ back to sign-in later, reads report it; run `desktop login` again.
519
+
390
520
  Use `--desktop-account personal` for a personal Microsoft account. Sending still
391
521
  requires an explicit `init --allow-send` and the existing send confirmation.
392
522
  `init --no-login` only saves configuration. `desktop connect --visible` remains
@@ -397,7 +527,8 @@ The browser uses its own profile under the local data directory at
397
527
  profile. Different ports use different browser profiles. Disconnect closes this
398
528
  browser and keeps its sign-in data. To switch between visible and headless operation,
399
529
  disconnect first. `desktop recover` closes a verified managed browser or clears a
400
- stale record when no listener remains. Unverifiable processes are left untouched.
530
+ stale record when no listener remains. A verified browser that does not exit after
531
+ closing its debugging port is stopped; unverifiable processes are left untouched.
401
532
 
402
533
  The CLI checks that every listener is loopback-only and belongs to the recorded
403
534
  browser process, running as you with the expected executable, debugging port and