# Setup Get PresenceJam running on your machine. ## Prerequisites - **Windows 10/11** (64-bit), **macOS** (Apple Silicon), or **Linux** (64-bit, glibc) — the full matrix, including what is *not* supported, is in [`docs/PLATFORMS.md`](./docs/PLATFORMS.md) - On **Linux**, a running Secret Service keyring daemon is required — see **Linux: System Keyring Required** below - A **Spotify Premium** account (required for the Web API) - A **Microsoft 365 Teams** account (work or school — the Graph presence APIs don't support personal Microsoft accounts) ## Step 1 — Install the App Download the latest release from the [GitHub Releases page](https://github.com/Carme99/PresenceJam-Desktop/releases/latest): | OS | File | Notes | |----|------|-------| | Windows | see [Releases page](https://github.com/Carme99/PresenceJam-Desktop/releases/latest) | Run the installer, follow the prompts | | Linux | `PresenceJam-linux-amd64.deb` / `.AppImage` | Install the `.deb` with `sudo apt install ./PresenceJam-linux-amd64.deb`, or run the `.AppImage` directly; requires a running keyring daemon (see **Linux: System Keyring Required** below) | | macOS | see [Releases page](https://github.com/Carme99/PresenceJam-Desktop/releases/latest) | Drag PresenceJam to Applications | | Windows (winget) | `winget install PresenceJam.PresenceJam` | Windows 10/11 package-manager install | | macOS (Homebrew) | `brew install carme99/tap/presence-jam` | Apple Silicon only — the formula refuses an Intel install | #### AppImage launcher entry (Linux, optional) The `.deb` gets a launcher entry and icon from the package manager; an AppImage does not, and without one a hidden window is only reachable by re-running the file from a terminal. To add the same integration: ```bash mkdir -p ~/.local/bin ~/.local/share/applications ~/.local/share/icons install -m755 PresenceJam-linux-amd64.AppImage ~/.local/bin/PresenceJam-linux-amd64.AppImage cat > ~/.local/share/applications/presencejam.desktop <<'EOF' [Desktop Entry] Type=Application Name=PresenceJam Exec=/home//.local/bin/PresenceJam-linux-amd64.AppImage Icon=presencejam Terminal=false Categories=Utility; StartupWMClass=presencejam EOF update-desktop-database ~/.local/share/applications ``` Replace `/home/` in `Exec=` with your real home path (desktop entries do not expand `~`), and point `Icon=` at artwork you installed (e.g. `~/.local/share/icons/presencejam.png`). This copies the file rather than installing a package, so the "no install required" description still holds. **Launch at Login does not need this** — the autostart plugin writes its own `~/.config/autostart/PresenceJam.desktop` pointing at the AppImage. Windows and macOS filenames carry the version (`PresenceJam-.msi`, `PresenceJam-.app.tar.gz`); the Linux artifacts do not (`PresenceJam-linux-amd64.deb` / `.AppImage`). See the [latest release](https://github.com/Carme99/PresenceJam-Desktop/releases/latest) for the current values. The installer will create: - The app in your Applications/start menu - A `%APPDATA%\PresenceJam\` (Windows), `~/Library/Application Support/PresenceJam/` (macOS) or `$XDG_CONFIG_HOME/PresenceJam/` (Linux) folder for `config.json`, and a separate bundle-id folder for `tokens.json` — see **What Gets Installed** below - A **system tray** icon — the app runs in the background > **Tip:** When the app first opens, it will show the **Onboarding Wizard** — a 3-step guide that walks you through connecting Spotify and Teams. --- ## Step 2 — Register a Spotify App PresenceJam uses Spotify's Web API to read your currently playing track. This requires a Spotify Developer app with the correct settings. ### Create the app 1. Go to the [Spotify Developer Dashboard](https://developer.spotify.com/dashboard) and log in 2. Click **Create App** 3. Fill in the details: - **App name:** PresenceJam (or anything you like) - **App description:** Syncs my Spotify playback to Teams status - Tick the **Developer Terms of Service** checkbox 4. Click **CREATE** ### Configure redirect URIs The Create dialog has no Redirect URIs field — you add those after creation: 1. On the app overview page, click **Edit Settings** 2. Under **Redirect URIs**, add: `presencejam://callback` 3. Click **SAVE** ### Copy your credentials From the app overview page, copy: - **Client ID** — you'll paste this into PresenceJam during onboarding - **Client Secret** — also pasted into PresenceJam during onboarding > **Keep your Client Secret private.** It authenticates your app to Spotify. If you accidentally expose it publicly, click **ROTATE** on the app overview page to regenerate it immediately. --- ## Step 3 — Connect to Teams Teams uses Microsoft's Device Code flow. You do not need to create or register an application: PresenceJam currently borrows the public-client identity `14d82eec-204b-4c2f-b7e8-296a70dab67e` from Microsoft's **Microsoft Graph Command Line Tools** app registration rather than using a PresenceJam-owned Microsoft Entra app registration. During onboarding, PresenceJam will: 1. Show you a short **code** and a verification URL 2. Open your browser to that URL 3. You enter the code and sign in with your Microsoft account 4. PresenceJam picks up the auth token automatically Make sure you sign in with the **same Microsoft account** you use in Teams. The requested delegated permissions are `Presence.ReadWrite Presence.Read Calendars.ReadBasic MailboxSettings.Read openid profile offline_access`. The Microsoft consent screen and any grant or revocation entry may name **Microsoft Graph Command Line Tools**, not PresenceJam, because the identity is shared. Revoking that grant, or a policy or service change to the shared registration, can also stop PresenceJam's Teams connection. PresenceJam does not receive or store a client secret for this flow. --- ## Step 4 — Configure Your Status After connecting both services, you'll land on the **Dashboard**. Before starting sync, you can adjust how your Teams status looks in **Settings**. ### Status Format Customize the text using placeholders — the full table lives in [USAGE.md — Status Format](./USAGE.md#status-format): | Placeholder | Output | |-------------|--------| | `{artist}` | Artist name — on an episode, the show name | | `{track}` | Track name — on an episode, the episode name | | `{album}` | Album name — on an episode, the publisher | | `{emoji}` | 🎵 (playing track), 🎙️ (playing episode) or ⏸️ (paused) | | `{device}` | Name of the device Spotify is playing on | | `{playlist}` / `{context}` | Where playback started from (exact aliases of each other) | | `{progress}` | Playback position (`3:07`); empty when Spotify reports none | | `{shuffle}` / `{repeat}` | 🔀 / 🔁 while on, nothing while off | | `{show}` / `{episode}` / `{publisher}` | Episode-only fields; empty on a music track | **Default:** `🎵 {artist} - {track} 🎧` **Example:** `🎵 Daft Punk - One More Time 🎧` Podcast and audiobook episodes are formatted with their own built-in `🎙️ {show} - {episode}` template — your music template above is not applied to them, and there is no setting for it yet. ### Profanity Filter If a track or artist name contains profanity, PresenceJam replaces the entire status with a safe placeholder. You can: - Toggle the filter on/off - Customize the placeholder text (supports `{emoji}`) ### Other Settings | Setting | Description | |---------|-------------| | Polling interval | How often to check Spotify when a track is playing (default 30s; default field clamped 5-300s) | | Clear on pause | Automatically clear Teams status when Spotify pauses. `config.json` only — `teams.clear_on_pause`; there is no Settings toggle for it | | Launch at login | Start PresenceJam when your OS boots | --- ## Upgrading from 2.x Upgrading to 3.0 adds new OAuth scopes on both providers, so **both** require a **one-time re-auth** after the upgrade: - **Spotify** — the `user-modify-playback-state` scope powers the tray playback controls. Until you reconnect, Settings warns that playback control needs a one-time Spotify reconnect; the banner is driven by the shared persist-warning copy. - **Teams** — the current delegated scope set is `Presence.ReadWrite Presence.Read Calendars.ReadBasic MailboxSettings.Read openid profile offline_access`. `Presence.Read` powers meeting/call-aware gating, `Calendars.ReadBasic` supports the calendar gate, `MailboxSettings.Read` supports working-hours import, and `profile` supplies the object-id claim needed by the availability sync. Until you reconnect, Settings warns that presence features need a one-time Teams reconnect; both providers now share one banner (`settings.authPersistWarning`), which names the provider rather than carrying a per-scope string. Click **Reconnect** in the banner (or Settings → reconnect the service) — you only need to do this once per provider. Your `tokens.json` migrates automatically: on first read, v3.0 detects a ≤2.x plaintext file, encrypts it with AES-256-GCM, and rewrites it. No manual step. For folder-copy backups, copy BOTH directories — they are not co-located (issue #300): `config.json` lives in `%APPDATA%\PresenceJam\` / `~/Library/Application Support/PresenceJam/` / `$XDG_CONFIG_HOME/PresenceJam/`, while `tokens.json` lives under the bundle-id folder `%APPDATA%\com.presencejam.app\PresenceJam\` / `~/Library/Application Support/com.presencejam.app/PresenceJam/` / `$XDG_CONFIG_HOME/com.presencejam.app/PresenceJam/`. --- ## What Gets Installed ``` %APPDATA%\PresenceJam\ (Windows) ~/Library/Application Support/PresenceJam/ (macOS) └── config.json # Your settings %APPDATA%\com.presencejam.app\PresenceJam\ (Windows — bundle-id folder) ~/Library/Application Support/com.presencejam.app/PresenceJam/ (macOS) └── tokens.json # Spotify + Teams tokens (AES-256-GCM ciphertext; decryption key in the OS keychain — see SECURITY.md) %LOCALAPPDATA%\com.presencejam.app\logs\ (Windows — bundle-id folder) ~/Library/Logs/com.presencejam.app/ (macOS — bundle-id folder) └── PresenceJam.log # Live log; rotated by size, with bounded archives (Settings → Logging) ``` (Linux uses `$XDG_CONFIG_HOME` instead of `%APPDATA%` / `~/Library/Application Support` for `config.json` and `tokens.json`, and `~/.local/share` in place of `%LOCALAPPDATA%` for the logs; the layout is otherwise the same.) **`config.json`, `tokens.json` and the logs live in three different folders** — Tauri's config/token path and `app_log_dir()` both append the bundle identifier `com.presencejam.app` (issue #300), so back up or delete all three. A `config.json` that no longer parses as JSON is renamed out of the way as `config.json.bak` in that same folder and the app boots on defaults, so a broken file is never silently overwritten — see [TROUBLESHOOTING.md — The app came up with default settings](./TROUBLESHOOTING.md#the-app-came-up-with-default-settings). No data is sent to any third-party server — all tokens stay on your machine. --- ## Uninstalling 1. **Quit the app** — right-click the tray icon → Quit 2. **Delete the app:** - Windows: Settings → Apps → PresenceJam → Uninstall - macOS: Drag PresenceJam from Applications to Trash - Linux (deb): `sudo apt remove presence-jam` (or `sudo dpkg -r presence-jam`) - Linux (AppImage): just delete the AppImage file (and the `~/.local/bin` copy if you followed the launcher recipe in the README) 3. **Delete user data** (optional) — `config.json`, `tokens.json` and the logs live in three different folders: ```powershell # Windows Remove-Item -Recurse -Force "$env:APPDATA\PresenceJam" Remove-Item -Recurse -Force "$env:APPDATA\com.presencejam.app\PresenceJam" Remove-Item -Recurse -Force "$env:LOCALAPPDATA\com.presencejam.app\logs" ``` ```bash # macOS rm -rf ~/Library/Application\ Support/PresenceJam rm -rf ~/Library/Application\ Support/com.presencejam.app/PresenceJam rm -rf ~/Library/Logs/com.presencejam.app ``` ```bash # Linux rm -rf "${XDG_CONFIG_HOME:-$HOME/.config}/PresenceJam" rm -rf "${XDG_CONFIG_HOME:-$HOME/.config}/com.presencejam.app/PresenceJam" rm -rf ~/.local/share/com.presencejam.app/logs ``` 4. **Remove the login entry** if **Launch at Login** was on: Windows and macOS remove it with the app; on Linux delete `~/.config/autostart/PresenceJam.desktop`. A `~/.local/share/applications/presencejam.desktop` exists only if you wrote one for an AppImage install — the app never creates it. Your Spotify app credentials (Client ID/Secret) in the Spotify Developer Dashboard are unaffected — revoke them separately if you want to fully disconnect. ## Linux: System Keyring Required PresenceJam stores your Spotify `client_secret` in the OS keychain (the same place Firefox/Chromium store website passwords). On Windows and macOS this works automatically; on Linux it requires a system keyring daemon to be installed and running. If PresenceJam fails to start with an error mentioning "OS keychain is unavailable" or "Failed to open keychain entry", your Linux setup is missing a keyring. Install one of the following: | Distro / DE | Recommended package | |---|---| | GNOME (Ubuntu, Fedora Workstation, etc.) | `gnome-keyring` (usually pre-installed on GNOME desktops) | | KDE Plasma | `kwallet5` or `kwallet6` | | Headless / no GUI | `gnome-keyring-daemon` with headless unlock (`echo \| gnome-keyring-daemon --unlock`, then verify with `secret-tool` below), or a KeePassXC Secret Service bridge | | Other | `gnome-keyring` + `libsecret-tools` | **Linux install command:** ```bash # Debian / Ubuntu sudo apt install gnome-keyring libsecret-1-0 # Fedora sudo dnf install gnome-keyring libsecret # Arch sudo pacman -S gnome-keyring libsecret ``` > **Note:** the `presencejam://` deep-link scheme registration writes > `~/.local/share/applications/.desktop` plus `xdg-mime default` on > Linux (`app.rs` `register_all`, issue #66) — that path needs > `update-desktop-database` (`desktop-file-utils`) to register launchers. After installing, **log in to a graphical session** (a headless SSH session can't reach the keyring). If you launched PresenceJam from a TTY, launch it from your desktop session instead. Then restart PresenceJam. > **If the keyring is locked rather than missing**, the app no longer mistakes it for "Spotify was never set up": Reconnect shows a **Keychain unavailable** badge (and Settings the matching wording on the credential row) telling you to unlock the keyring and retry, and it does **not** push you back through the Spotify setup wizard. Your `client_secret` is still stored — nothing needs re-entering once the keyring answers. Verify the keyring is reachable from your shell: ```bash secret-tool store --label=test service test user test secret-tool lookup service test user test # should echo "test" secret-tool clear service test user test ``` If `secret-tool` can read/write, PresenceJam's keychain path will work. If not, your distro's Secret Service D-Bus activation is broken — check `systemctl --user status gnome-keyring-daemon` (or the equivalent for `kwalletd`). There is **no plaintext-on-disk fallback** for the client secret. A working keyring is a hard requirement.