Development Roadmap
Status: Living document. Detailed per-issue and per-PR state lives in GitHub Issues, Pull Requests, the CHANGELOG, and ADRs. This document carries themes, principles, and parked work only.
Principles
- Validate first: Run spikes before implementing complex features
- Start simple: Build MVP, add complexity only if needed
- User-driven: Implement Phase 2 features only when users request them
- Linux-first: Embrace Unix philosophy --- composable tools over monolithic features
- Measured releases: Accumulate meaningful changes rather than rapid incremental releases (#2235)
- Automate triage, not decisions: Bots surface information; maintainers decide
- Incremental configuration: New features use nested config patterns from day one; existing flat options migrate opportunistically (ADR-025)
Active Themes
Current status is tracked via the linked GitHub labels. This section serves as an orientation map, not a real-time tracker.
-
Stability and Reliability: auth recovery, network error scoping, media permission handling, drag-and-drop file uploads (restore
File.pathElectron now strips, #2679). Live: bug. -
Media and Calls: camera and mic handling, speaking indicator, call drops on multi-interface systems. Live: media, screen-sharing. Suppressing automatic audio/video device switching shipped (
media.preventDeviceSwitching, PR #2652). -
Downloads: download-feedback manager shipped --- taskbar/KDE JobView progress and completion notifications (#2512). Save options
download.saveDirectory/download.alwaysAskWhereToSave/download.openWhenDoneplus a policy-block notification for M365/SharePoint-interrupted downloads shipped (PR #2652). Context-menu attachment download ("Download Attachment & Copy to Clipboard", "Save Open Document to File") through the authenticated session was closed unmerged (PR #2654); reopen if requested. Both split out of #2645. -
Linux Desktop Integration: background portal integration for Flatpak shipped, so the sandboxed app requests background running and reports its status over
org.freedesktop.portal.Background, withSetStatusused where the portal is v2 or newer (#2815, PR #2826). Live: flatpak. -
WebAuthn and FIDO2 on Linux (ADR-021, opt-in via
auth.webauthn.enabled): USB security keys run throughfido2-tools. The Flathub build now bundles libfido2 and its tools (flathub PR #232, flathub #221), and the tester on #3008 confirmed the sandbox now detects them. Sign-in still shows no PIN prompt for that tester on both the Flatpak and the native .deb, where the key flashes for touch, and the cause is still unresolved. Next: ask on #3008 for a full debug log of the .deb session through to the PIN step and the SSO host, then check whether that host needsauth.webauthn.extraOrigins. The flathub #221 reporter has not yet said whether they use a USB key. Phone and QR passkeys stay blocked (#2714). Live: authentication. -
macOS Desktop Integration: presence-status overlay on the Dock icon (
media.showStatusOnDockIcon) and opt-out Apple-Silicon rendering/performance switches (media.macPerformanceMode, larger V8 heap gated to arm64) shipped (PR #2653). Releases now also carry a native Apple Silicon.dmgalongside the Intel one: thedmgCI job builds both architectures in a single electron-builder run (macOS update metadata is not arch-suffixed, so both must share onelatest-mac.yml) and ad-hoc signs them, which is what lets an arm64 build launch without an Apple Developer Program membership. Notarization is still out of reach, so first launch requires the Gatekeeper approval documented in troubleshooting. -
Wayland Compatibility:
--ozone-platform=x11remains the shipped default. Two removal attempts followed: PR #2506 was reverted the same day in PR #2600 after an accidental merge, and the Electron 42 retry PR #2601 was closed unmerged after a reporter-confirmed regression; the community testing tracker #2508 closed June 2026 with the same verdict. Decision and reopen triggers recorded in ADR-031. Live: wayland. -
MQTT Integration: presence, media state, screen-share topics shipped. Home Assistant auto-discovery shipped (PR #2464, PR #2571). Microphone state shipped (PR #2497). Incoming-call topic shipped (PR #2572). Camera topic shipped (PR #2582). Meeting-started detection shipped, experimental behind
mqtt.meetingStartDetection.enabled(#2587, PR #2757). Live: mqtt. -
Secondary Window for Calls (#2971, ADR-032, proposed): opt-in second
BrowserWindowon the same session partition so a call can live in one window while the other stays a full client. Meeting links route to it, a calendar-based "join upcoming" follows as phase 2, the preload receives a window role and call state becomes per window. The live call itself is never moved. Supersedes ADR-010. -
Multi-Account Profile Switcher (#2495, ADR-020): Phase 1 shipped in v2.9.0 behind the opt-in
multiAccount.enabledflag, covering WebContentsView-based profiles, the avatar pill, the Profiles menu andCtrl+Alt+1…5pinned slots. Mutually exclusive with Intune SSO. Phase 2 has started with the sender-to-profile attribution map (PR #2865), which nothing consumes yet; per-profile unread aggregation is next (PR #2916). Meeting-join andmsteams://links still route to Profile 0 (#2867). Deferred from the shared-state audit:cleanExpiredAuthCookiesruns against the root session only, the power-save blocker is not profile-scoped, and the incoming-call toast has no notion of its originating partition. -
Notifications: lifecycle stable; remaining work in notifications.
-
Performance: the ten-item audit is closed out in ADR-026. Bounded timestamp polling, a cached tray base icon and chunked
cacheManagerscans shipped in PR #2837. The four not-planned items each carry a recorded reason, with a stated magnitude where a residual cost is accepted. Where a reopen trigger exists it needs no instrumentation, so a user-supplied DevTools profile or a reproducible idle-CPU report is enough to revisit one. -
Config Schema as Single Source of Truth (#2597): phases 0-2 shipped in v2.12.0 (drift fixes, generated reference +
config-schema.jsonwith CI drift guard, docs config explorer); 3a (applyMode+ nested-field metadata, hard-failing generator lint) and 4 (warn-only startup validation) landed; 3b (in-app settings window) is the remaining phase (ADR-029). The settings window is the deliverable, and its restart-only MVP can ship on its own:- Build the restart-only settings MVP, reusing the
legacyConfigStoreoverride-on-boot layering and allowlisting writes to schema keys with type/choice plus deep prototype-pollution validation; defer the live-apply subset and the object-typed forms.
The flat-to-nested config migration is an optional, independent companion rather than a prerequisite, and can land before, alongside, or after the window. #2841 settled on yargs'
deprecatedflag plus the renames projection (ADR-025), and the user-invoked migration shipped in v2.19.0 as the Settings menu's "Show Updated Config…" entry (#2913, PR #2914, PR #2915). Migrating the remaining flat options to the nested names owned by ADR-025, tracked namespace by namespace in #2842, de-risks the writer by collapsing config to one canonical nested shape. It can also ride on the window itself: since every save writes canonical nested keys, the UI passively migrates each user with no separate phase. - Build the restart-only settings MVP, reusing the
-
Testing Infrastructure: cross-distro Docker tests passing for all 9 configurations (ADR-016); CI integration in progress.
-
Dev Experience: stale bot tuning and a project-specific code-reviewer subagent are the next quick wins. (PR template landed 2026-05-15.)
Awaiting User Feedback
Phase 2 work depending on a user trigger.
- Quick Chat Access (#2109, shipped v2.7.4): notification click-to-chat, recent contacts cache, favorites list if requested.
- Smartcard PIN Dialog (#2639, merged in #2659, opt-in via
auth.clientCertificate.pinDialog.enabled): WebAuthn PIN dialog migration onto the shared secure prompt. - SSO Web Sign-in Pre-fill (#2794, merged in #2761, opt-in via
auth.webLogin.*): account and password pre-fill on the Microsoft/federated web login form, with optional auto-advance and MFA method selection. Broader host coverage and passkey-aware flows only if requested. - Custom Stickers (#2476, shipped v2.11.0 in PR #2550, opt-in via
customStickers.enabled): local folder and HTTPS URL import with one-level subfolder scanning; Telegram pack import (#2577, PR #2578) was tried and closed in favor of GIPHY search, itself then parked as not needed (PR #2580); prompt-driven generation through a user-configured endpoint was never attempted. Any of these only if requested. - Graph API Enhanced Features (ADR-030): calendar sync, mail preview notifications. Presence endpoint returns 403 because the Teams token lacks
Presence.Readscope. Fuller backlog in app/graphApi/README.md. - MQTT call topics (#2370, incoming-call topic shipped in PR #2572): caller identity or meeting subject in the payload, separate topics per call kind, and a per-topic retain or TTL setting, only if a second user asks.
Not Planned / Not Feasible
| Feature | Issue | Reason | Notes |
|---|---|---|---|
| Screen Lock Media Privacy | #2106 | Closed --- no user interest | Reopen if requested |
| Meeting Join with ID | #2152 | Microsoft limitation | Workaround: use meeting link via clipboard |
| Custom Notifications Phase 2 | #2108 | Dropped --- didn't work for the user | MVP (v2.6.16) remains |
| GNOME Search Provider | #2075 | Latency too high (~300-1100ms) | Technically feasible but poor UX |
| External Browser Auth | #2017 | Not feasible | Teams manages OAuth internally |
| Multiple Windows (generic pop-out, moving a live call) | #1984, #2499 | Not feasible: a running call cannot leave its renderer, and Teams' own pop-out is a desktop host feature (#2983) | Quick Chat covers quick replies. The scoped, opt-in secondary window is a separate proposal, see Active Themes and ADR-032 |
| useSystemPicker | --- | Rejected (ADR-008) | Reconsider when Electron improves Linux support |
| Disable Chat Spellcheck | #2304 | Not feasible | Spellcheck is controlled by Teams/Chromium, not the wrapper |
| Formatting View on Compose | #2318 | Not feasible | Teams UI internals; no injection point |
Infrastructure
- Bot Automation: issue triage is a standalone Go service (github-issue-triage-bot, ADR-018).
- Cross-Distro Testing: 9 configurations on Docker, all passing (ADR-016).
- Release Automation: managed by release-please; merge the auto-generated Release PR to trigger a release.
- Repo Health: repo-butler generates a daily dashboard at the portfolio page.