Files
spotifast/README.md
T
Carmine Paolino 8f5045549f Show what is playing through fastframe-now-playing
The desktop's media controls (MPRIS on Linux, the media overlay on
Windows, Now Playing on macOS) now come from fastframe-now-playing in
place of Spotifast's own three modules. The crate keeps what they did:
a volume request answered with the new level, the position sent at most
once a second, the cover handed to Windows and macOS as a file, the
remembered track claiming the media keys on macOS, the hidden window on
Windows, and the Flatpak desktop entry from FLATPAK_ID, which Flatpak
always sets. Loading reads as paused, and the track's id is its Spotify
URI, so a request to move within a track that has since changed is
ignored as before.

Every fastframe crate moves to fastframe's main at c62c229, the commit
that adds the crate. souvlaki and mpris-server leave the direct
dependencies with the modules. The window's app id keeps matching the
desktop entry. The link test gives the running copy's slot a runtime
directory of its own. The Nix vendor hash follows the lockfile.
2026-10-03 14:18:39 +02:00

670 lines
36 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Spotifast
**Spotify, native and fast.** Spotifast is a Spotify client written in
Rust with [egui](https://github.com/emilk/egui). It plays music through
[librespot](https://github.com/librespot-org/librespot). It typically uses
100–250 MB of RAM, while Spotify's desktop app often uses 600 MB to over 1 GB.
It runs on Linux, macOS, and Windows, starts in well under a second, and has no
browser engine.
**Want WhatsApp just as fast and native?** [ZapFast](https://zapfast.rocks) is
Spotifast's sibling: the same native interface, for WhatsApp. Both are built on [fastframe](https://github.com/crmne/fastframe), the shared
foundation for native Rust apps built with egui.
**Playback needs Spotify Premium.** Free accounts can browse and search, but
cannot play music through Spotifast on this computer or another device.
https://github.com/user-attachments/assets/a5f669ce-b3b7-4f8e-9933-976a78876c7e
See [spotifast.rocks](https://spotifast.rocks/) for installation, setup,
everyday use, and connection details.
![Spotifast Home with the playlist library, recommendations, queue, and player visible](docs/screenshot.png)
## What it does
- **Plays music on this computer.** Spotifast appears as a Spotify Connect
device. Select it from your phone or play music in the app. Playback is
gapless and supports up to 320 kbps, with
optional volume normalisation and an on-disk audio cache.
Stalled Spotify connections time out after five seconds per attempt so
playback can try another endpoint.
Since 0.8.0, a confirmed local seek discards audio queued from
the old position. Decoder, download, and device-buffer delays can still apply.
Starting a sorted playlist or Liked Songs view shows the requested song
immediately while playback connects, using its loaded metadata (available since 0.8.0). Sorted views start at their first playable row. Filtering a
playlist or Liked Songs keeps playback within the shown songs and preserves
repeated songs; Play is unavailable when no shown song can play.
- **Controls other devices.** Move playback to a speaker, a phone, or
another computer from the device picker, and keep controlling it: play,
pause, skip, seek, shuffle, repeat, volume. The picker expands upward to
show several devices at once, fitting the window; longer lists scroll.
Since 0.9.0, switching back to this computer transfers the active
Connect session with its song, position, queue, and paused or playing state.
- **Finds speakers on your network.** Spotifast finds librespot, spotifyd,
and supported hardware receivers over mDNS. Once connected, they appear as
Spotify Connect devices. The picker uses responding receivers' names and
combines entries with the same device ID.
- **Library.** Browse playlists, Liked Songs, saved albums, followed artists,
podcasts, and saved episodes. Filter, pin, and reorder sidebar items.
Since 0.10.0, the Library header switches between a list and a
responsive cover grid.
Since 0.10.0, with local playback enabled, audiobooks saved in
Spotify stay out of Podcasts, since they can't be played here.
Since 0.8.0, double-click a playlist row in Library to start playback;
a single click opens it. In the grid, a card's corner button plays it.
Settings offers a compact track list with one line per song and spaced
separators between its name, artists and added date.
Since 0.8.0, choose name, recent plays, or saved-date order where
available. Follow Spotify’s playlist order or keep a separate local arrangement.
Spotify doesn't let apps change its order, so since 0.10.0,
dragging a playlist while following it switches to the local arrangement
and says so.
Move Liked Songs among your pins or unpin it and choose its local position;
the placement survives restarts.
With local playback enabled, releases that the Web API groups as singles
are labelled EP when librespot confirms that type.
Liked Songs reopens from an account-specific metadata cache. Older rows
refresh in the background while Like and Unlike take effect immediately.
Right-click album, artist, and podcast cards for their actions (available since 0.8.0).
- **Search** across songs, artists, albums, playlists, podcasts, and episodes,
with a top result and per-type views. Right-click results and cards for their actions.
When Spotify provides an artist profile, its name on a song opens that page,
including from the top result.
Text fields offer Cut, Copy, Paste and Select all from their right-click menu.
Since 0.8.0, a personal app searches the catalogue while shared
access finds playlists. Each part appears independently, even if the other fails.
Since 0.8.0, the search field stays clear of the device and update
badges in narrow windows; hover their icons to read the labels. In a
narrow window, Library, Queue and Lyrics give up width before the top
bar's controls run together, and get it back when the window widens.
- **Home** with Made for you, Recently played, your top artists and songs, and
recommendations. Right-click playlist shortcuts and shelf cards for their actions.
Since 0.10.0, **Your podcasts** lists episodes of your saved
podcasts that you have started, then new ones you have not.
Playing an episode you have started, from Home, a podcast page, your saved
episodes or search, continues where you left it.
- **Artist pages** with popular songs, a filterable discography, and related
artists. **Album**, **playlist**, and **podcast** pages support playback
from any row. Since 0.8.0, album and playlist scrollbars represent the full track count;
dragging to an unloaded section fetches that section directly.
Discography and related-artist cards also have right-click menus (available since 0.8.0).
Artist names in the player bar open their pages, including during local
playback before Web API metadata arrives (available since 0.8.0).
Since 0.9.0, an album, single, or EP's **Add to queue** adds all
its playable songs in album order, on this computer or another device.
- **Radio.** Since 0.10.0, **Go to song radio** in a song's menu, and
**Go to playlist radio**, **Go to album radio**, or **Go to artist radio** in
their **…** menus, open a page of 50 songs Spotify picks to go with them.
**Play** plays exactly those songs, **Refresh** in **…** asks for a new mix,
and **Save as playlist** keeps the mix as a private playlist. Radio needs
playback on this computer to be set up.
- **Edit your playlists.** Create, rename, describe, reorder, and delete them.
Since 0.8.0, hold a dragged song near the playlist's top or bottom
edge to scroll to rows beyond the screen. The Library sidebar scrolls while
dragging toward offscreen playlists too.
Since 0.9.0, upload a JPEG or PNG cover from
**Edit details → Change cover**.
Add songs from a row menu, or drag a row or the currently playing song to a
playlist in the sidebar. Since 0.8.0, dragging a selected row
copies the whole selection in displayed order; the preview shows its count.
Drop the selection on Liked Songs to save every selected song. Selection
uses a translucent neutral highlight, without a row outline.
Drop a song from the player
bar, queue, or another list between rows of an open editable playlist to
insert it there. This adds a copy and leaves playback and the queue unchanged.
Clear the playlist’s filter and sort to choose an insertion position.
Drop it on an empty playlist to add its first song.
A playlist a friend shared with you takes songs too,
as Spotify's own apps allow. Filter the **Add to playlist** menu by name to
find the destination quickly: `Enter` adds to the first match, and the
arrow keys choose another. Since 0.9.0, playlist folders and
invitation permissions also load when the library finishes before local
playback connects.
Spotify's own mixes carry no added dates, so they show no Date added column.
- **Opens Spotify links.** Spotifast registers for `spotify:` links, so a
song, album, artist, playlist, or podcast shared from another app opens
in it, whether it is running or not. `open.spotify.com` addresses go
through the browser, which hands them to the same handler.
- **Queue** as a side panel or a page; it names what is playing from, and
anything can be added to it from a row menu. **Add to queue** places songs
after those already queued and before the context continues.
On other devices, rate-limited additions retry automatically after Spotify's
requested wait, preserving album and song order and their known details.
A permanent failure removes the rejected additions and reports the error.
Starting an album or playlist keeps those additions under **Playing next**,
even when it starts a song you also queued. **Clear queue** removes the
additions and keeps the playing collection's remaining songs.
Dropping a dragged song, or selection, on the player bar's Queue button
queues it the same way. While this computer is playing locally, dropping
a song at a position within the open queue's *Playing next* inserts it
there instead of always at the end, and dragging a queued row elsewhere in
that section reorders it; with a remote Spotify Connect device, every drop
still just adds to the end, since neither Spotify nor librespot can
reorder or insert into a live remote queue.
Selecting repeated playlist rows queues every occurrence in the selected
order. A repeated click counts once, and the notification counts actual additions.
Since 0.8.0, Recent keeps repeated short-song plays separate,
including consecutive local repeats of the same song.
Each Recent row starts the song it names and shows it in the player bar
immediately while playback starts.
- Since 0.8.0, a playlist's **Play** button explicitly starts at
its first available song when Shuffle is off and the original order is
selected. Double-click a row to start there; use the player bar to resume.
Cached playlists must match Spotify's revision and song count before their
rows can determine playback order. Pending playlist edits stay visible; a
cache checkpoint includes them only after all writes succeed.
Refresh waits for pending edits and their Spotify revision to be confirmed;
a failed refresh keeps the current rows and offers a retry.
Choose **Refresh** in a playlist's **…** menu to pick up changes made in
another Spotify client.
Large playlists save loaded rows in incremental checkpoints, so reopening can
resume without fetching earlier pages. Older cache files still load. Cache
writes run in the background with one pending snapshot to limit memory use.
- Since 0.10.0, the **Shuffle** button beside a collection's **Play**
button sets the global mode without starting that collection. Choose it before
a playback device is active; the next **Play** uses that selection. While
another collection plays, it changes that playback's mode without switching
to the viewed collection.
- **Lyrics.** Follow synced lyrics in a side panel or full-screen view, or read
unsynced lyrics when timestamps are unavailable. Full-screen lyrics scroll
smoothly and highlight the playing line automatically, beside the song's
cover; a song without words shows just its cover.
- **Resumes the last session.** On startup, the last song is paused where it
stopped. Play resumes it, and the other playback controls work before it
starts.
- **Album-art colour.** Pages and the player bar take a tint from the cover
of what you are looking at or listening to. The bar fades from one song's
colour to the next rather than switching in a single frame. Turn it off in
Settings.
- **Light and dark**, or follow the system.
- **Repeat stays selected.** Since 0.9.0, starting another song
locally preserves Repeat, with Shuffle on or off.
- **Song changes keep the selected song.** Since 0.10.0, the default
audio output keeps discarded audio paced while a replacement loads, preventing
the old cached song from racing to its end and causing an extra skip.
- **Reconnects keep the queue.** Since 0.9.0, recovering an
interrupted local playback session restores its playlist position,
queued songs, shuffle order, and Repeat mode, and comes back at the
volume being heard.
- **Light and dark**, or follow the system.
- **Native window behaviour.** On macOS, double-click the top bar to use the
Fill, Zoom, Minimise or Do Nothing action selected in Desktop & Dock.
Since 0.10.0, buttons, rows and cards keep the ordinary arrow
pointer; only links, such as artist names, show the hand.
- **Winamp mini player.** `Ctrl+M` opens a small player for classic `.wsz`
skins, drawn at 1x to 4x scale. It includes a spectrum analyser, playlist,
and equalizer. It keeps its shade mode and, where the desktop permits,
its own position when switching views. Drop a skin from the
[Winamp Skin Museum](https://skins.webamp.org) on either window to add it.
Since 0.9.0, switching to the mini player preserves the main
window's size even if its native close takes another frame.
On Windows, since 0.10.0, the main window uses the standard
Windows title bar. **Settings → Appearance → Custom title bar** switches to
Spotifast's own title bar and window buttons.
On Windows, since 0.8.0, a mini player saved on a disconnected monitor
starts at a default position on the current desktop.
Clicking or double-clicking the Windows tray icon brings the window forward;
the tray menu still offers Show or hide.
On Windows, since 0.8.0, and in Linux X11 sessions, hide its taskbar button
from Settings or the mini player's options menu while keeping the window
and tray controls available.
On Wayland, use the desktop's Keep Above shortcut or rule; the app's
Always on top controls are unavailable there.
![The mini player wearing the built-in skin](docs/assets/images/winamp.png)
- **Equalizer.** Winamp's ten bands and presets over the music played on
this computer, in Settings and in the skin.
- **A player bar that moves.** Since 0.11.0, **Player bar visualizer** in
Settings > Appearance draws a spectrum or the waveform of the playing song
behind the player bar, in the cover's colour. It is off by default;
click the bar's empty space to switch between spectrum, waveform and off.
- **MilkDrop.** The visualiser, powered by
[projectM](https://github.com/projectM-visualizer/projectm), runs in its own
window and process. It supports fullscreen and automatically downloads more
than 10,000 `.milk` presets on first use (about 26 MB).
https://github.com/user-attachments/assets/12b31312-0e0c-4b34-9383-e8c66aabc58d
- **Keyboard-first.** Every common action has a shortcut (`Ctrl+/` or `?` lists
them).
- **Keeps playing when you close the window.** Spotifast stays in the system
tray. Use the tray icon or media controls to reopen it, and quit from the
tray menu or with `Ctrl+Q`. You can make the close button quit in Settings.
On macOS, the Dock icon also reopens the window.
- **Visible network activity.** Pages show a spinner while loading. The top
bar also shows slow or rate-limited Spotify requests.
- **One instance.** Launching it again brings the existing window forward
instead of starting a second copy, on every platform.
- **Desktop integration.** MPRIS on Linux, so media keys, the shell, and
`playerctl` see Spotifast like any other player. On macOS and Windows,
`spotifast next` and its siblings drive the running app from a terminal,
a launcher, or a hotkey. On Windows, since 0.8.0, hover the taskbar button
for Previous, Play/Pause, and Next under the window preview. On macOS,
right-click the Dock icon for Play/Pause, Next, and Previous.
## Install
On Arch Linux, Spotifast is in the AUR:
```bash
yay -S spotifast-bin # the released build, ready made
yay -S spotifast # the release, built from source
yay -S spotifast-git # built from the latest commit
```
On macOS, with [Homebrew](https://brew.sh):
```sh
brew install --cask crmne/tap/spotifast
```
Or [download the Mac app](https://spotifast.rocks/download/#macos), open the
downloaded file, and drag **Spotifast** to **Applications**. Starting with 0.8.0,
the Mac download passes Apple's security checks. Open it from Applications
and confirm the normal downloaded-app prompt. No Terminal commands or changes
to security settings are needed.
Elsewhere, build the single binary with Rust 1.98 or newer:
```bash
cargo install --path . --locked
```
MilkDrop uses libprojectM, which is built from source. This needs CMake, a C++
compiler, and libclang. To build without MilkDrop or those tools, run
`cargo install --path . --locked --no-default-features`. On Linux, you also need the
development packages for ALSA, PulseAudio or PipeWire, and the windowing
libraries. On Arch:
```bash
sudo pacman -S --needed alsa-lib libpulse libxkbcommon wayland cmake clang
```
and on Debian or Ubuntu:
```bash
sudo apt install libasound2-dev libpulse-dev libxkbcommon-dev libwayland-dev \
cmake clang libclang-dev
```
and on Fedora:
```bash
sudo dnf install alsa-lib-devel pulseaudio-libs-devel libxkbcommon-devel \
wayland-devel cmake clang clang-devel
```
On Windows, libprojectM is built with Visual Studio 2022, CMake, LLVM, and
vcpkg (`vcpkg install glew:x64-windows-static`, with
`VCPKG_INSTALLATION_ROOT` pointing at the vcpkg folder).
With [Nix](https://nixos.org), `nix develop` provides all of it, along with
the exact toolchain `rust-toolchain.toml` pins.
An official public binary cache is not active yet. CI can publish its Linux
Nix builds once a maintainer configures Cachix; see
[Nix binary cache setup](docs/_reference/nix-cache.md).
On macOS, `packages.<system>.spotifast` contains the native binary and an
ad-hoc signed `Spotifast.app` bundle for the Dock, Launch Services, and
`spotify:` links. With nix-darwin, add `spotifast` to
`environment.systemPackages` and link `"/Applications"` through
`environment.pathsToLink`; with Home Manager, `home.packages` is enough, as
its darwin support links the bundle into `~/Applications`.
Since 0.8.0, system fallback fonts align with Latin text, including
Japanese titles drawn with Hiragino Sans on macOS. Yi characters used in
stylized artist names also use an installed fallback font instead of empty boxes.
Spotifast uses system fonts for scripts not covered by its interface font,
including Chinese, Japanese, Korean, Arabic, Hebrew, Thai, and Indic scripts.
On macOS it draws each of them with the face the system itself uses, in the
language order set in System Settings, so Chinese titles follow the
Traditional or Simplified preference set there. Windows includes common
fonts. On Linux, install `noto-fonts` and `noto-fonts-cjk` (Arch) or
`fonts-noto` and `fonts-noto-cjk` (Debian or Ubuntu) if titles appear as
empty boxes. Since 0.10.0, Spotifast also looks in every font
directory named in fontconfig's configuration, so fonts installed through
NixOS's `fonts.packages` are found too. Since 0.10.2, Arabic drawn with
a small system face is enlarged to read as large as the Latin text around
it, and Javanese, styled mathematical and circled letters, and ♡ in names
find an installed face as well.
On `main`, emoji are drawn in colour everywhere the interface shows
text (names, lyrics, menus, tooltips and text fields), in the system's own
style: Apple Color Emoji on macOS, Segoe UI Emoji on Windows, and the
desktop's colour emoji font on Linux (`noto-fonts-emoji` on Arch, `fonts-noto-color-emoji` on Debian or
Ubuntu). Without one, emoji are drawn in a single colour as before. The
Winamp mini player and MilkDrop's titles keep the single-colour emoji.
Since 0.8.0, long right-to-left titles in song rows and the player
bar end with an ellipsis inside their text area, including joined Arabic letters.
Since 0.10.0, the Linux launcher is
`packaging/applications/spotifast.desktop`. Its icon and window identity also
use Spotifast, while existing settings and window positions are preserved.
After installing it, `xdg-mime default spotifast.desktop x-scheme-handler/spotify`
chooses Spotifast for `spotify:` links.
Spotifast draws its window with OpenGL 2.0 or newer, which the graphics
driver of any current PC or Mac provides. A virtual machine or remote session
without a graphics driver, such as Windows on the Microsoft Basic Display
Adapter, may not offer it, and Spotifast then exits at startup. There is no
separate software-rendering mode. MilkDrop needs OpenGL 3.3.
## Sign in
Press **Sign in with Spotify**. Your browser opens Spotify's consent page
(Authorization Code with PKCE), so Spotifast never sees your password. The
app keeps its grants in the system credential store: Secret Service on Linux,
Keychain on macOS, and Credential Manager on Windows. You usually sign in once
per machine. If the store is unavailable or locked, a new sign-in works for
this session and Spotifast explains that it could not save it.
[Privacy](https://spotifast.rocks/privacy/) lists everything the app stores
and sends.
Playing music **on this computer** needs a second, one-time browser approval.
Spotify handles streaming separately from library access. Start it from the
device menu (**Set up playback here**) or Settings. It needs Spotify
Premium. Its reusable credential uses the same protected storage, independently
of the two Web API grants.
Since 0.8.0, local playback tries the other available server
addresses when one cannot connect, including a prompt IPv4/IPv6 fallback.
Socket and proxy tunnel setup have a five-second limit. See
[how it connects](docs/_reference/how-it-connects.md#the-engine).
Since 0.10.0, the whole engine connection can take up to 75 seconds,
including server resolution and authentication. A stalled setup may therefore
remain **Connecting** longer than one five-second attempt; the outer deadline
does not guarantee that every fallback will be tried.
Existing token files migrate after the protected write has been read back
successfully. A failed migration keeps the original for recovery and reports
an error. Sign-out removes shared, personal, and playback grants, including
legacy files and pending writes. Non-secret revocation markers prevent a
failed keychain deletion from silently restoring a signed-out session.
See [credential storage and file locations](docs/_reference/settings-and-files.md).
Since 0.8.0, Flatpak also preserves its fallback state directory
across full quits, including on older Flatpak versions.
The Flatpak application ID is `rocks.spotifast.Spotifast`.
Playback approval requests Spotify's streaming permission separately. A
verified personal app can complete sign-in while the shared app is busy.
The Web API uses a shared app by default. You can add a personal Spotify
Development Mode app in Settings → Account for a separate quota. Spotifast
still uses the shared app for requests that personal apps do not support.
Since 0.8.0, Premium listeners using shared access see a one-time
prompt explaining the personal app option, with a button that opens setup.
Dismissal is remembered across restarts.
Playlists the shared app would serve are read over the local playback session
instead when it is signed in. If Spotify stays busy and no personal app is
configured, Spotifast points you to that setting at most once a day.
## Account safety
We are not aware of a Spotify account being suspended for using Spotifast
or another librespot player with Premium. Sign-in happens on Spotify's own
pages, audio uses the quality included with Premium, DRM stays intact, and
Spotifast does not rip tracks or block ads.
Reported suspensions usually involve modded apps that remove ads from free
accounts, track ripping, or stream manipulation. Spotifast does none of
those things, and [CONTRIBUTING.md](CONTRIBUTING.md) prohibits them.
## Keyboard shortcuts
Since 0.8.0, text fields keep their usual Ctrl, Cmd and Alt arrow
keys for moving the caret while you type.
Hold `Shift` while turning the mouse wheel to scroll horizontal shelves,
including Made for you and Recently played on Home.
The main window exposes named playback controls, library and song rows,
menus, sliders, and settings switches to screen readers. Use `Tab` and
`Shift+Tab` to move focus, then `Enter` to activate a control or
play a focused song. Since 0.9.0, `Space` always plays or pauses
the current song unless a text field has focus. In a playlist, album or Liked
Songs, up and down arrows move focus between whole song rows in the displayed order and scroll them
into view. Tab still reaches the artist links, Like and More controls.
Arrow navigation selects only the destination song; hold `Shift` with up or
down to extend or shrink the selection. `Delete` removes the selected songs
from a playlist you can edit, just like **Remove from this playlist**.
Since 0.10.0, `Ctrl+A` selects every song the list shows,
`Ctrl+C` copies the selected songs' links one per line, and `Ctrl+V` adds
the song links on the clipboard to the end of a playlist you can edit.
`Ctrl+X` in a playlist you can edit copies the selected songs' links and
removes the songs from it. A focused text field keeps these keys for its own text.
Left and right arrows adjust a focused volume or seek
slider. Windows testing with NVDA and accessibility for Winamp skins are
still in progress.
| Shortcut | What it does |
| --- | --- |
| `Space` | Play or pause |
| `Ctrl+←` / `Ctrl+→` | Previous or next |
| `Shift+←` / `Shift+→` | Seek 10 seconds |
| `Ctrl+↑` / `Ctrl+↓` | Volume |
| `M` | Mute |
| `B` | Like or unlike the playing song |
| `S` / `R` | Shuffle / cycle repeat |
| `Q` | Queue panel |
| `Ctrl+F` or `/` | Search |
| `Ctrl+B` | Show or hide the sidebar |
| `Alt+←` / `Alt+→` | Back or forward |
| `Ctrl+H` / `Ctrl+L` | Home / Liked Songs |
| `Ctrl+Shift+A` / `Ctrl+Shift+B` | Playing artist / album |
| `Ctrl+A` | Select every song in a playlist, album or Liked Songs |
| `Ctrl+C` / `Ctrl+V` | Copy the selected songs' links / add copied song links to your playlist |
| `Ctrl+X` | Copy the selected songs' links and remove the songs from your playlist |
| `Ctrl+M` | Winamp mini player |
| `Ctrl+Shift+K` | MilkDrop |
| `Ctrl+,` | Settings |
| `Ctrl+/` or `?` | All shortcuts |
| `Ctrl+Q` | Quit |
On macOS, `Cmd` replaces `Ctrl`.
On Windows, since 0.8.0, middle-click a scrolling list and move the pointer to
autoscroll. Click, press Esc, use the wheel or switch windows to stop.
It works automatically on Windows. On Linux, turn on **Middle-click
autoscroll** under **Settings > Appearance**; it is off by default because a
middle click usually pastes there. See [autoscroll](docs/_guide/using-spotifast.md#middle-click-autoscroll).
## Controlling it from outside
The `spotifast` command controls the copy already running, on every
platform. Each verb prints nothing on success:
```
spotifast play-pause spotifast volume 40
spotifast play spotifast volume-up [percent]
spotifast pause spotifast volume-down [percent]
spotifast next spotifast mute
spotifast previous spotifast shuffle [on|off]
spotifast seek 15 spotifast repeat [off|context|track]
spotifast seek -- -15 spotifast like
spotifast seek-to 90 spotifast play-uri spotify:playlist:37i9…
spotifast show spotifast transfer <device-id>
spotifast now-playing [--raw] spotifast devices [--raw]
```
`shuffle` and `repeat` toggle when used without an argument. Pass a state to
set it directly. `like` adds or removes the playing track from your library.
`now-playing` prints one readable line. `--raw` prints tab-separated fields:
state, title, artists, album, position_ms, duration_ms, volume, shuffle,
repeat, art_url, saved, and device. `saved` is `yes`, `no`, or `unknown` while
loading. New fields are appended to keep older scripts working.
`devices` lists Spotify Connect devices with the ID first and the active one
marked with `*`. `--raw` prints JSON. The command refreshes the device list,
so the first call after startup may be empty. Run it again if needed.
A verb exits non-zero when Spotifast is not running.
On every platform, `spotifast <link>` opens a Spotify link, a `spotify:`
URI or an `open.spotify.com` address, in the running app, or starts the
app on it. This is what the desktop runs when a link is clicked.
Since 0.9.0, search links open Search with the query filled in,
without starting playback. They work on a fresh launch or an existing window;
if signed out, the search waits for sign-in. For example:
```sh
spotifast 'https://open.spotify.com/search/here%20comes%20the%20sun'
# Linux, with Spotifast already running:
playerctl --player=spotifast open 'https://open.spotify.com/search/here%20comes%20the%20sun'
```
Use `spotify:search:here%20comes%20the%20sun` for the equivalent Spotify URI,
or `https://open.spotify.com/search` to open an empty search box. Encode spaces
as `%20`; a `+` in the path remains a literal plus. Ordinary MPRIS playback
URIs still start playback.
On Linux, Spotifast is also an MPRIS player, so `playerctl
--player=spotifast play-pause` and media keys work too.
Launchers such as Raycast or Alfred, and the Stream Deck plugin, can use
these commands. Since the next release, they reach Spotifast through a
private channel only your user can open (on Windows, a loopback port that
answers only requests carrying a random token), instead of a fixed port
any program could reach. Use the command rather than the channel itself.
## Settings
Settings live in one readable JSON file (`~/.config/spotifast/settings.json`
on Linux). They include the Connect device name, bitrate, normalisation,
autoplay, gapless playback, the audio backend (PulseAudio/PipeWire or ALSA on
Linux), audio cache size, theme, sidebar state, whether pages take colour
from artwork, and the mini player's skin and size.
Since 0.8.0, you can hide Made for you and Recommended for you
from Home through JSON preferences; see
[Home shelves](docs/_reference/settings-and-files.md#home-shelves).
Custom JSON palettes go in a `themes` folder beside `settings.json`.
Since 0.11.0, eight palettes (Catppuccin, Nord, Rose Pine, Tokyo Night and
others) are put there on first start, as files to use, change or delete.
Select them in Appearance; `spotifast reload-themes` loads additions and updates
without interrupting playback. See [custom themes and Omarchy integration](docs/_reference/settings-and-files.md#custom-themes).
New installations default to **Follow system**. On an Omarchy desktop every
Linux build follows the current palette, and Linux packages also set up the
per-user template and hook automatically on first launch. Since 0.10.2, on
Linux, edited palettes and Omarchy theme changes apply without a reload
command. Existing theme choices and custom files stay intact. The picker lists Follow system, Light and Dark first, then the available Omarchy
integration and local palettes. The **Open themes folder** button in Settings
opens the local JSON palette directory.
The interface follows the operating system's language when Spotifast has a
translation for it, and English otherwise. **Settings → Appearance → Language**
picks another one, listed by its own name, and applies it at once; **System**
follows the computer again. Anything a translation does not cover yet appears
in English.
Playback settings apply when you press **Apply and restart playback**.
The Settings page has its own search: type under the title to narrow the
rows, clear the field to see everything again.
You can also check for a new release from Settings. On macOS, the same command
is in the application menu.
The Windows installer, Mac app, and portable Windows and Linux downloads
support updates from inside Spotifast. Click the green update button to
download a release, then choose when to restart and install it. Settings can
enable automatic background downloads; restarting always waits for your click.
Closing the update window keeps a download running.
Spotifast checks each download before installing it. An interrupted or damaged
download leaves the running app alone, and a failed startup restores the
previous installation. Updates keep your settings and sign-ins. On macOS,
move Spotifast to Applications before updating it. See
[how updates are checked and installed](docs/_reference/how-it-connects.md#what-the-client-stores)
for the technical details.
Package-managed installations continue to update through their package manager,
including Homebrew, Flatpak, apt, dnf, pacman, Nix, and Cargo. Unrecognized
installations, the AppImage among them, use the download page. Portable archives identify themselves with
`spotifast-portable.txt`; older archives need one manual upgrade to an
update-enabled build.
Since 0.9.0, Off and System proxies apply immediately. HTTP and SOCKS5 apply
when you press **Apply settings**, and can also be set on the sign-in screen.
A proxy password uses the system credential store, separately from Spotify
sign-in. Only confirmed proxy settings are saved; editing a form does not
change the active connection until you apply it.
Proxy authentication covers Web requests. Local playback can use only an
unauthenticated HTTP proxy; with proxy login or SOCKS5 it connects directly.
Caches (audio, artwork) live under the cache directory and can be deleted at
any time without signing you out.
Since 0.9.0, downloaded artwork uses less temporary memory while
being saved to the cache. Visible cards and collection covers use sharper
640-pixel artwork. Loading transitions may retain up to 64 softened previews
in addition to the existing artwork-cache budget. These previews reuse decoded
artwork, so keeping a collection open does not repeatedly reload its cover.
For blank or incorrectly drawn windows, include `spotifast.log` in the bug
report. Since 0.9.0, it records the app version, platform and active
OpenGL renderer, plus window-creation errors even when launched without a console.
## How it is built
- `src/player.rs`: librespot playback, mixing, and Spotify Connect state.
- `src/api/`: shared and personal Web API sessions, routing, concurrency, and
rate limits.
- `src/backend.rs`: the tokio runtime and channels used by the interface.
- `src/images.rs`: album art loading, caching, and accent-colour extraction.
- `src/app.rs`, `src/model.rs`, `src/ui/`: state, navigation, and views.
- `src/single_instance.rs`: the running copy's guard and the remote control
the `spotifast` command speaks.
Spotifast pins its Rust toolchain in `rust-toolchain.toml`; `cargo test`
covers the API models, dual-session routing, PKCE, the player state machine,
and a headless render of every page, panel, and dialog.
To look at the interface without a Spotify account, build with the `demo`
feature and start it with sample data:
```bash
cargo run --features demo -- --demo --demo-page playlist:pl1 --demo-show queue
```
Demo mode never writes settings. `--demo-shot <PATH>` writes the window to a
PNG and exits, which is useful for reproducible interface screenshots.
`--demo-size WIDTHxHEIGHT` sets the window size in logical pixels for that shot.
`--demo-drag X,Y:X,Y` holds a drag in the shot: it presses at the first point
and keeps the button down at the second.
Demo windows ignore saved window geometry and do not save window or interface state.
Use `--demo-data <DIRECTORY>` to keep demo caches and logs in a separate directory.
## Contributing
Read [CONTRIBUTING.md](CONTRIBUTING.md) before opening an issue or pull
request. It covers project scope and required checks.
Translations use standard gettext `.po` files in `assets/i18n/`, with an English
`.pot` template. The interface is marked for translation throughout and ships
with 14 translations, including Portuguese and Chinese variants.
Spanish and Turkish are complete; the others cover the earlier navigation,
player and panel labels and fall back to English for the rest. See
[Translating Spotifast](docs/_reference/translating.md) for editing with existing
translation tools, previewing, and reporting translation problems.
New and reopened issues and new discussions receive automated triage through
[Copilot Triage](https://github.com/crmne/copilot-triage). A party-popper reaction
marks a completed assessment; it does not promise a reply or a fix. See
[automated triage](CONTRIBUTING.md#automated-triage) for details.
## Acknowledgements
Spotifast uses [librespot](https://github.com/librespot-org/librespot),
[egui](https://github.com/emilk/egui), the [Inter](https://rsms.me/inter/)
typeface (OFL), and [Lucide](https://lucide.dev) icons (ISC).
Spotifast is an independent project and is not affiliated with Spotify.
Spotify is a trademark of Spotify AB.
Licensed under the [MIT License](LICENSE).
## Packaging maintenance
Release packaging uses the [native-packages](https://rubygems.org/gems/native-packages) gem. macOS release builds automatically sign and notarize when the Apple CI credentials are configured. `native-packages.yaml` declares packages and downstream repositories; native recipes and installation assets live in `packaging/`; see [PACKAGING.md](PACKAGING.md) for local commands and CI behavior.