.docname {Teams for Linux} .include {docs} Microsoft does not publish a native Teams client for Linux. [Teams for Linux][teams-for-linux] is an unofficial [Electron][electron] wrapper around the Teams web app that provides a standalone desktop client, system tray integration and native notifications. Install it with `yay -S teams-for-linux-bin`. ## Configuration The configuration is stored in `~/.config/teams-for-linux/config.json`. ```json { "notificationMethod": "web", "electronCLIFlags": [ ["enable-features", "WebRtcPipeWireCamera"] ] } ``` - `notificationMethod: web` uses the browser notification API of the embedded web app instead of the Electron notification API. - `WebRtcPipeWireCamera` enables the PipeWire camera backend, which is required for the webcam to work under Wayland. ## Opening meeting links in the app Clicking a Teams meeting link in the [Thunderbird](002-thunderbird.qd) or Outlook web interface opens the meeting in the browser instead of in Teams for Linux. Getting the handover to work requires a userscript, because the desktop integration alone is not sufficient. ### Verify the protocol handler The package registers the `msteams:` URI scheme through its desktop entry, so this part usually works out of the box: ```sh gio mime x-scheme-handler/msteams ``` The output must name `teams-for-linux.desktop` as the default application. If it does not, register it with `xdg-mime default teams-for-linux.desktop x-scheme-handler/msteams`. A deep link can be tested directly from a shell. This opens the meeting in Teams for Linux: ```sh xdg-open 'msteams:/meet/?p=' ``` ### Why the browser never asks Meeting invitations do not contain `msteams:` links. They contain plain HTTPS links in the form `https://teams.microsoft.com/meet/?p=`. An HTTPS URL belongs to the browser, so nothing is ever handed to an external application. That URL answers with a redirect to a launcher page: ```txt HTTP/2 302 location: /dl/launcher/launcher.html?url=%2F_%23%2Fmeet%2F%3Fp%3D%26anon%3Dtrue&type=meet&directDl=true&msLaunch=true ``` Because the redirect happens on the server, no document is ever created for the `/meet/` URL and a userscript cannot match on it. The launcher page is the first document that actually loads, and its `url` query parameter carries the deep link path, prefixed with `/_#`. Stripping that prefix yields exactly the path the `msteams:` scheme expects. ### Userscript Install [Tampermonkey][tampermonkey] in [Librewolf](001-librewolf.qd) and add the following userscript. ```js // ==UserScript== // @name Teams links to teams-for-linux // @match https://teams.microsoft.com/dl/launcher/launcher.html* // @match https://teams.microsoft.com/meet/* // @match https://teams.microsoft.com/l/* // @run-at document-start // @grant GM_info // ==/UserScript== (() => { let path; if (location.pathname.startsWith('/dl/launcher/')) { const u = new URLSearchParams(location.search).get('url'); if (!u) return; path = u.replace(/^\/_#/, ''); } else { path = location.pathname + location.search; } if (!/^\/(meet|l)\//.test(path)) return; window.stop(); location.href = 'msteams:' + path; setTimeout(() => { window.close(); location.replace('about:blank'); }, 1500); })(); ``` Three details in this script are not obvious and the script silently stops working without them: - `@grant GM_info` forces Tampermonkey to run the script in its sandboxed content script scope. With `@grant none` the script is injected into the page as an inline `