An almost stable Matrix client. https://app.sable.moe
  • TypeScript 93.6%
  • Rust 5%
  • JavaScript 0.6%
  • Kotlin 0.2%
  • CSS 0.2%
  • Other 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Erwan Leboucher 355fce699e
fix: preserve room and sender data in push notifications (#2056)
<!-- Please read
https://github.com/SableClient/Sable/blob/dev/CONTRIBUTING.md before
submitting your pull request -->

### Description

<!-- Please include a summary of the change. Please also include
relevant motivation and context. List any dependencies that are required
for this change. -->

Fixes #

#### Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] This change requires a documentation update

### Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings

### AI disclosure:

- [ ] Partially AI assisted (clarify which code was AI assisted and
briefly explain what it does).
- [ ] Fully AI generated (explain what all the generated code does in
moderate detail).

<!-- Write any explanation required here, but do not generate the
explanation using AI!! You must prove you understand what the code in
this PR does. -->
2026-09-07 10:33:44 +02:00
.changeset fix: preserve room and sender data in push notifications 2026-09-07 00:33:11 +02:00
.github ci: publish stable releases to the AUR 2026-08-30 11:49:36 +02:00
.vscode more visual fixes 2026-07-27 06:01:32 +03:00
contrib
docs fix: prepare Flatpak metadata 2026-08-11 20:47:28 +02:00
infra okay this should workkk 2026-07-26 14:51:16 -05:00
packaging ci: publish stable releases to the AUR 2026-08-30 11:49:36 +02:00
public Merge remote-tracking branch 'origin/dev' into feat/tauri-desktop 2026-07-17 12:12:26 +02:00
scripts feat(crypto): drive matrix-js-sdk crypto from a Rust engine over IPC 2026-08-28 14:37:51 +02:00
src fix: preserve room and sender data in push notifications 2026-09-07 00:33:11 +02:00
src-tauri fix: preserve room and sender data in push notifications 2026-09-07 00:33:11 +02:00
tests/e2e fix(crypto): restore device verification from an unverified session 2026-09-01 19:00:57 +02:00
.dockerignore
.gitattributes
.gitignore feat(flatpak): publish a nightly channel 2026-08-26 10:33:10 +02:00
.npmrc chore: use devEngines for node version 2026-07-24 19:45:52 -05:00
build.config.ts
Caddyfile
CHANGELOG.md chore: prepare release 1.21.0 2026-08-17 20:52:05 +00:00
CODE_OF_CONDUCT.md formatting 2026-07-30 14:21:10 -05:00
config.json fix(gifs): send gifs through the media proxy instead of uploading them 2026-08-22 19:00:47 +02:00
CONTRIBUTING.md docs: add architecture guidance for contributors 2026-08-04 15:27:58 +02:00
Dockerfile feat: unify product name and build flavor across builds 2026-07-26 13:32:41 -05:00
flake.lock fix(flake): make flake build android/desktop/web 2026-08-13 17:00:45 +02:00
flake.nix chore(nix): auto-fix nix hashes 2026-08-28 13:15:15 +00:00
index.html fix(android): let the keyboard shrink the layout viewport 2026-08-22 20:11:26 +02:00
knip.json feat(crypto): drive matrix-js-sdk crypto from a Rust engine over IPC 2026-08-28 14:37:51 +02:00
knope.toml fix(ci): replace enrich-changelog with native knope templates 2026-07-25 13:32:40 +02:00
LICENSE
mise.tauri.toml fix: package CEF releases without goreleaser 2026-08-12 11:31:40 +02:00
mise.toml fix: make Linux distribution work via GoReleaser, drop nfpm config 2026-08-11 20:38:43 +02:00
nfpm.yaml feat(tauri): build arm64 Linux desktop bundles 2026-08-15 18:00:59 +02:00
oxfmt.config.ts chore: fmt 2026-07-19 01:06:28 +02:00
oxlint.config.ts fix(overlay): stack overlays by open order instead of fixed z-index 2026-08-08 21:48:33 -05:00
package.json feat(crypto): drive matrix-js-sdk crypto from a Rust engine over IPC 2026-08-28 14:37:51 +02:00
playwright.config.ts test(e2e): isolate accounts for parallel workers 2026-08-13 10:48:26 +02:00
pnpm-lock.yaml feat(crypto): drive matrix-js-sdk crypto from a Rust engine over IPC 2026-08-28 14:37:51 +02:00
pnpm-workspace.yaml pin crypto wasm version to prevent key spam 2026-08-26 18:39:39 -05:00
README.md feat(flatpak): publish a nightly channel 2026-08-26 10:33:10 +02:00
rust-toolchain.toml feat: add mise support 2026-07-24 19:42:44 -05:00
TRADEMARKS.md formatting 2026-05-13 12:42:00 -05:00
tsconfig.json refactor: refactor persona into the wanted architecture 2026-08-07 20:44:27 -05:00
vite.config.ts fix(build): restore static copy output paths for the bundled call app 2026-08-24 16:39:07 +02:00
vitest.config.ts chore: consume @sableclient/tauri-plugin-notifications-api from npm 2026-08-18 10:38:35 +02:00
wrangler.json chore: drop cloudflare deps 2026-07-31 21:02:03 +02:00

Sable

A Matrix client built to enhance the user experience with quality-of-life features, cosmetics, utilities, and sheer usability. See the changelog.

Soon to be replaced desktop apps can be downloaded here. They auto-update by pulling the website.

Join our matrix space here to discuss features, issues, or meowing.

Forked from Cinny.

Getting started

The stable web app is available at app.sable.moe and tracks the latest GitHub release. Nightly builds are available at dev.sable.moe and from the nightly GitHub release.

You can also download our desktop app for Windows and Linux from releases. Release artifacts include build attestations. AppImage and Windows installations update automatically; .deb, .rpm, and AUR installations update through their package manager.

Desktop (Linux / macOS / Windows)

Download   Flathub

On macOS, via our Homebrew tap:

brew install --cask SableClient/sable/sable

The fully qualified name matters: since Homebrew 6.0.0 non-official taps need explicit trust, and installing this way trusts just this one cask. brew tap followed by a short-name install now fails unless you also run brew trust.

On Linux, nightly builds have their own Flatpak remote, rebuilt from dev every night:

flatpak remote-add --if-not-exists sable-nightly https://sableclient.github.io/Sable/sable-nightly.flatpakrepo
flatpak install sable-nightly moe.sable.client.Nightly

It installs alongside the stable Flathub build under a separate application ID. Built by the build-nightly-flatpak and publish-nightly-flatpak jobs in tauri-build.yml.

Android (Obtainium)

Android APKs are published to every release, and Obtainium keeps them updated straight from GitHub. Each release also ships an obtainium.json app config. Use it for the nightly channel, where prereleases and date-based version tracking have to be enabled to follow the rolling nightly tag.

Stable

Add to Obtainium   App config   Download APK

Nightly

Add to Obtainium   App config   Download APK

Setup & install

  1. Install Obtainium.
  2. Tap Add to Obtainium above. Stable opens the Add App page prefilled with https://github.com/SableClient/Sable; nightly opens an import prompt, since it carries the prerelease and version-tracking settings the rolling nightly tag needs.
  3. Or download the obtainium.json for either channel and import it with Import/Export → Import from file.

Android builds are produced by the android job in tauri-build.yml, and the config by the obtainium job in the same workflow.

Relevant variables and switching between Nightly and Stable

Relevant variable differences between Nightly and Stable:

  • Include prereleases - true for Nightly, false for Stable
  • Fallback to older releases - false for Nightly, true for Stable
  • Use latest asset upload as release date - true for Nightly, false for Stable (this is due to Nightly builds being uploaded to one release instead of creating new ones)
  • Use release date as version string (pseudo-version) - true for Nightly, false for Stable (this is due to Nightly builds being uploaded to one release instead of creating new ones)

iOS (AltStore / SideStore)

Sable iOS builds are distributed as unsigned IPAs through AltStore and SideStore. Each release publishes both the IPA and an altstore-source.json manifest — stable builds to the latest GitHub release, nightly builds to the nightly GitHub release.

Stable Source

Add to AltStore   Add to SideStore   Direct URL

Nightly Source

Add to AltStore   Add to SideStore   Direct URL

Setup & install

  1. Set up AltStore Classic or SideStore on your device.
  2. Add the Sable source (tap a button above), or add it manually:
    • AltStore (stable): altstore://source?url=https://github.com/SableClient/Sable/releases/latest/download/altstore-source.json
    • SideStore (stable): sidestore://source?url=https://github.com/SableClient/Sable/releases/latest/download/altstore-source.json
    • AltStore (nightly): altstore://source?url=https://github.com/SableClient/Sable/releases/download/nightly/altstore-source.json
    • SideStore (nightly): sidestore://source?url=https://github.com/SableClient/Sable/releases/download/nightly/altstore-source.json
  3. Install Sable from the source. The IPA is unsigned; AltStore/SideStore re-sign it with your personal development certificate at install time, so apps refresh every 7 days (the standard free-account limitation).

iOS builds are produced by the ios job in tauri-build.yml and track the same dev/v* triggers as desktop builds.

Self-hosting

You have a few options for self hosting, you can:

  1. Run the prebuilt docker container.
  2. Deploy on a site like GitLab Pages. Jae has a guide here.
  3. Build it yourself.

Docker

Prebuilt images are published to ghcr.io/sableclient/sable.

  • latest tracks the current latest version release.
  • dev tracks the current dev branch image.
  • X.Y.Z tags are versioned releases.
  • X.Y tags float within a release line.
  • Pushes to dev also publish a short commit SHA tag.

Run the latest image with:

docker run --rm -p 8080:8080 ghcr.io/sableclient/sable:latest

Then open http://localhost:8080.

If you want to override the bundled config.json, mount your own file at /app/config.json:

services:
  sable:
    image: ghcr.io/sableclient/sable:latest
    ports:
      - '8080:8080'
    volumes:
      - ./config.json:/app/config.json:ro

Build it yourself

To build and serve Sable yourself with nginx, clone this repo and build it:

pnpm i # Installs all dependencies
pnpm run build # Compiles the app into the dist/ directory

After that, you can copy the dist/ directory to your server and serve it.

  • In the config.json, you can modify the default homeservers, feature rooms/spaces, toggle the account switcher, and toggle experimental simplified slilding sync support.

Optional default client settings

While the default settings are recommended for most users, you can optionally add a top-level "settingsDefaults" object whose keys match client settings (only fields you want to override) to override them. The default settings for any new logins will match these. Existing keys in local storage or users who chose to sync settings with their account data will still have their settings set.

For example:

{
  "settingsDefaults": {
    "hour24Clock": true,
    "pageZoom": 110,
    "messageLayout": 2,
    "rightSwipeAction": "members",
    "captionPosition": "below",
    "renderUserCards": "both",
    "jumboEmojiSize": "large"
  }
}

Invalid or unknown keys are ignored.

  • To deploy on subdirectory, you need to rebuild the app youself after updating the base path in build.config.ts.
    • For example, if you want to deploy on https://sable.moe/app, then set base: '/app'.

Local development

Tip

The easiest way to get started is with mise, it manages node, pnpm, rust, and other tooling.

mise install    # Install all required tools
mise run setup  # Install dependencies (pnpm install)
mise run dev    # Start the Vite dev server

Run mise tasks to list all available tasks (build, test, lint, etc.).

To build the app:

mise run build

Desktop & Mobile (Tauri)

Sable uses Tauri for native desktop and mobile builds.

mise run tauri:setup          # Install Rust toolchain + system packages
mise run tauri:setup:macos    # Install Xcode (macOS only)
mise run tauri:setup:windows  # Install VS Build Tools + WebView2 (Windows only)
mise run tauri wry dev        # Dev server with system webview (WebKit/WebView2)
mise run tauri cef build      # Production build with Chromium Embedded Framework
mise run tauri --help         # Any other args pass through to the Tauri CLI

When the first argument is wry or cef and the second is dev or build, the wrapper injects --features <runtime>,updater --no-default-features. Everything else is forwarded to tauri as-is.

Deployment and infrastructure

Deployment workflows and infrastructure details live in infra/README.md.