* Keep every signed-in account live With the multi-account flag on, the accounts other than the active one are now restored at launch, one after the other once the active account's UI is up. They run their migrations, sync while the app is active, get a pusher (appended so accounts on the same homeserver keep each other's) and count towards the app badge, and background refresh and search backfill cover them too. Only the active account's remote settings are ever applied. Calls stay with the active account until the call service handles every account, and an auth error on another account is only logged until accounts can be signed out one at a time. With the flag off only the active account is live, as before. * Sum the app badge across every signed in account Each live account now reports its own unread count, and the app badge shows their sum. Delivered notifications are only cleared for the account whose rooms were read, so a room shared by two accounts keeps the other account's notifications. The room list observer for the badge and the notifications moves from the UserSessionFlowCoordinator to the AppCoordinator's per-account wiring. The flow keeps updating the chats tab badge. * Let the user session manager manage every session - The AppCoordinator tells the manager to pause, resume, go offline or run the search backfill, instead of looping over the sessions itself. - The manager also restores the other accounts, preparing each with the AppCoordinator's migrations and wiring, and resumes them while the services are running. With a single account nothing changes. - Wiring an account again (e.g. after clearing the cache) replaces its observers rather than adding to them. - Add addAccountFlowEnabled, a developer-only switch for the upcoming add account flow. It isn't a user preference, so testers enabling multi-account can't add a second account yet. * Apply review suggestions to keeping every account live - Move the notification changes (pushers for every account, the summed app badge and per-account clearing) to their own PR, so notifications follow the active account again for now. - Revert loading only the active account's remote settings: they load in the store again, as on develop, until the hooks are reworked. - The user session manager reports the auth errors of every live session, so the AppCoordinator subscribes once instead of keeping per-account observers. - Restoring a single account is private to the manager now. - Rename otherSessionsRestoreTask to otherSessionsRestorationTask. * Restore every signed in account through one path The user session manager now restores every account in a single pass, most recently selected first, instead of separate restores for the active account and the others. The AppCoordinator shows the first account that comes back and no longer reads the multi-account flag: without it, the manager only ever makes one account live. - Clearing the cache clears every live account, and the next pass replaces their sessions. - Each account is migrated once per launch, and an account that just signed in is never migrated. - A pass also runs after signing in, so the other accounts come live. - Remove UserSessionManagerError, restoreActiveSession and restoreOtherSessions. * Only clear the cache of the active account Clearing the cache goes back to clearing the account shown in the UI. Its session stays live until the next restore pass replaces it, and when that restore fails another live account becomes the active one. * Apply review suggestions to restoring every account - Remove the search backfill guard: with no sessions the manager starts nothing and reports that nothing is running, so the task completes. - Add a TODO to switch to the most recently used account when the active one signs out while others are signed in (element-meta#3325). - Disable SwiftLint's type_body_length on the AppCoordinator again, it's just over the limit with develop's new migrations.
Element X iOS
Element X iOS is the next-generation Matrix client provided by Element.
Compared to the previous-generation Element Classic, it is a total rewrite using the Matrix Rust SDK underneath and targeting devices running iOS 18+.
Rust SDK
Element X leverages the Matrix Rust SDK through an FFI layer exposed as a swift package that the final client can directly import and use. We're doing this as a way to share code between platforms, with Element X Android using the same SDK.
Status
This project is actively developed and supported. New users are recommended to use Element X instead of the previous-generation app.
Contributing
Please see our contribution guide.
Come chat with the community in the dedicated Matrix room.
Build instructions
Please refer to the setting up a development environment section from the contribution guide.
Support
When you are experiencing an issue on Element X iOS, please first search in GitHub issues and then in #element-x-ios:matrix.org. If after your research you still have a question, ask at #element-x-ios:matrix.org. Otherwise feel free to create a GitHub issue if you encounter a bug or a crash, by explaining clearly in detail what happened. You can also perform bug reporting (Rageshake) from the Element application by going to the application settings. This is especially recommended when you encounter a crash.
Forking
Please read our forking guide.
Copyright & License
Copyright (c) 2025 - 2026 Element Creations Ltd. Copyright (c) 2022 - 2025 New Vector Ltd.
This software is dual licensed by Element Creations Ltd (Element). It can be used either:
(1) for free under the terms of the GNU Affero General Public License (as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version); OR
(2) under the terms of a paid-for Element Commercial License agreement between you and Element (the terms of which may vary depending on what you and Element have agreed to).
Unless required by applicable law or agreed to in writing, software distributed under the Licenses is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Licenses for the specific language governing permissions and limitations under the Licenses.