Playlist Forge Platten
winget install --id=Platten.Playlistforge -e Describe your ideal playlist, and with the power of OpenAI create your playlists in your favorite streaming service.
winget install --id=Platten.Playlistforge -e Describe your ideal playlist, and with the power of OpenAI create your playlists in your favorite streaming service.
Turn a sentence into a researched playlist, review every track, and hand it to your streaming service.
Playlist Forge is a local, single-user desktop application. You describe the
playlist you want; it uses OpenAI's Responses API (gpt-6-sol or gpt-6-luna) with web search
to assemble a coherent, intentionally ordered tracklist of real recordings. You
review and revise it track by track, then generate a temporary
Soundiiz import link to transfer it to TIDAL, Qobuz,
Spotify, Apple Music, or another service Soundiiz supports.
The React/TypeScript interface is embedded in a single Go binary that runs on the operating system's native webview. There is no server, no bundled runtime, and no database service — just an executable and a local SQLite file.
See ARCHITECTURE.md for package responsibilities, security
invariants, and the files that must change together when an API or persisted
model evolves.
Download the build for your platform and launch Playlist Forge. It opens its own window and does not listen on a network port. Every platform is built for both x86-64 and ARM64.
| Platform | Artifact | Notes |
|---|---|---|
| Windows | playlist-forge--windows--setup.exe | NSIS installer for x64 or ARM64; suitable for Winget. |
| Windows (portable) | playlist-forge--windows-.exe | The standalone application. No installation — download and run it. |
| macOS | playlist-forge.app (universal) | Intel and Apple Silicon in one bundle. |
| Linux | .deb, .rpm, .AppImage (per architecture) | Needs GTK 4 and WebKitGTK 6.0 (Ubuntu 24.04+, Fedora 38+, Debian 13+); the .deb/.rpm declare this. The .AppImage is portable. |
Release builds are currently unsigned. Configure Windows code-signing and an Apple Developer ID / notarization identity before distributing them as a warning-free public release.
Because the build is not signed with an Apple Developer ID or notarized, Gatekeeper blocks the first launch — macOS says Playlist Forge "cannot be opened because Apple cannot check it for malicious software", or that the app is "damaged and can't be opened". This is expected for an unsigned app. Clear it once per download with either method:
System Settings (recommended). Double-click playlist-forge.app and dismiss
the warning. Open System Settings → Privacy & Security, scroll to the
Security section, and click Open Anyway next to the Playlist Forge message,
confirming with Touch ID or your password. Launch the app again and click
Open. (On macOS 14 and earlier you can instead Control-click the app in
Finder and choose Open; macOS 15 removed that shortcut, so use Privacy &
Security there.)
Terminal. Remove the quarantine attribute the download added, then open the app normally:
xattr -dr com.apple.quarantine /path/to/playlist-forge.app
Use xattr -cr instead if -dr reports the attribute is missing on some files
inside the bundle.
Signing and notarization will remove this step in a later release. Background: Apple's Safely open apps on your Mac.
Open Settings, paste a key into API key, and choose Save key.
Playlist Forge loads the available models from OpenAI and validates that the key can access
gpt-6-sol or gpt-6-luna before storing it.
To create a key:
Playlist Forge), and copy the value.Treat the key like a password: never share it, commit it, put it in a screenshot, or paste it into an untrusted page. You can revoke it from the API keys page at any time.
OPENAI_API_KEY, if set, takes precedence and is shown in Settings as a
read-only, environment-managed credential. Otherwise Playlist Forge uses the OS
credential store — Windows Credential Manager, macOS Keychain, or the Linux
Secret Service. If that store is unavailable, Settings offers an explicit opt-in
to a permission-restricted config.json fallback in the application directory.
The key is never written to playlists.db.
Playlist Forge can mirror the playlists you already own on a streaming service so you can browse them, draw on them as inspiration, or hand them to Soundiiz. This is optional and needs no OpenAI usage.
Open Settings > Streaming connections and choose Connect next to TIDAL or Qobuz.
Sign in with the exact method that owns the library you want — Google, Apple, Facebook, and email/password logins can resolve to different profiles on the same address.
Open Browse. Imported playlists appear grouped by origin — Forged here, then TIDAL, then Qobuz — each row showing its track count and a badge for every place it lives. Open one to preview its tracks.
Use Reload TIDAL / Reload Qobuz in Browse to refresh the mirror. It runs as a cancellable background job with progress: new playlists are added, changed ones re-fetched, and playlists deleted upstream are removed. A streaming playlist whose contents match one you forged here is folded into that record rather than listed twice.
Imported playlists are read-only snapshots. Playlist Forge never writes to
your streaming account — it only reads playlist and track metadata. Credentials
live only in your OS credential store (with the same file fallback as the OpenAI
key), never in playlists.db.
Connections are re-checked in the background (shortly after launch and every few minutes). If a session has expired or been revoked, a banner and the Settings row prompt you to Reconnect; your imported playlists are kept. A transient outage of TIDAL, Qobuz, or Soundiiz surfaces as "… is not available right now. Please try again later." — retry the action after a moment.
Soundiiz receives only the accepted playlist title, description, track titles, and artist names. Playlist Forge never receives your streaming credentials.
Playlist Forge prepares a temporary import page; Soundiiz handles authorization and writes the playlist to the streaming service.
Sign in to the destination streaming service (in its own app or website) on the exact profile where the playlist should be created. Some services require a paid subscription for third-party playlist writes.
Create a Soundiiz account or sign in. Use a consistent sign-in method so you do not create a second Soundiiz account.
In Soundiiz, open the left panel, select the streaming service (or Connect more services), choose Connect, and complete its authorization screen. The icon turns green on success. Manage connections later under Settings > Platforms. See the Soundiiz connection guide.
Check the service-specific prerequisite:
| Service | Before authorizing Soundiiz |
|---|---|
| TIDAL | Use the same TIDAL sign-in method that owns the intended library. Google, Apple, Facebook, and email/password sign-ins can resolve to different TIDAL profiles even with a shared email address. |
| Qobuz | Sign in to the intended Qobuz account in the same browser first. To switch accounts, disconnect Qobuz under Settings > Platforms, sign out, sign in to the other account, and reconnect. |
| Spotify | Approve Soundiiz's playlist read/write permissions. If Spotify later expires the grant, reconnect under Settings > Platforms and retry. |
| Apple Music | Use the Apple Account with an active Apple Music subscription, enable Sync Library, and allow pop-ups and cookies during authorization. See the Apple Music checklist. |
The free Soundiiz plan supports one transfer at a time of up to 200 tracks, which covers Playlist Forge's 100-track maximum; see Soundiiz plans for current limits. Catalogs vary by service and region, so a track may be unavailable or resolve to a different edition.
Each request's preview shows an estimated cost derived from reported input,
cached-input, output, reasoning, and web-search usage. The embedded rate card is
versioned 2026-09-27: Sol uses $2.00 / M input, $0.20 / M cached input,
and $10.00 / M output tokens; Luna uses $0.10, $0.01, and $0.50
respectively. Both include $0.01 per web-search call.
Search-result content counts toward input tokens.
This is an estimate, not an invoice. Prices change, long-context or regional processing may use different rates, and credits or discounts are not reflected. Your OpenAI dashboard is authoritative.
Requirements: Go 1.27+ (matching go 1.27 in go.mod), Node.js 24,
pnpm 11.19, and — on Linux — a C toolchain plus the GTK 4 / WebKitGTK 6.0
development headers (CGO is required for the webview).
# System build dependencies
sudo apt-get update
sudo apt-get install -y build-essential pkg-config git curl \
libgtk-4-dev libwebkitgtk-6.0-dev
# Go — Ubuntu's package is older than 1.27, so install the official tarball.
# Set GO_VERSION to the current 1.27.x from https://go.dev/dl/.
GO_VERSION=1.27.0
curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-$(dpkg --print-architecture).tar.gz" \
| sudo tar -C /usr/local -xz
export PATH="$PATH:/usr/local/go/bin" # add to ~/.profile to persist
# Node.js 24 (Ubuntu ships 18) and pnpm 11.19, via corepack
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
sudo apt-get install -y nodejs
corepack enable && corepack prepare pnpm@11.19.0 --activate
Then:
git clone https://github.com/platten/playlistforge.git
cd playlistforge
bash scripts/build-desktop.sh # runs the quality gate, then writes
# .deb, .rpm, and .AppImage to build/bin
scripts/build-desktop.sh installs the frontend dependencies and builds the
embedded UI itself; curl and sha256sum (from coreutils) are the only other
tools the Linux packaging step needs. Fedora is analogous with gcc,
pkg-config, gtk4-devel, and webkitgtk6.0-devel.
This is a Wails v3 application. Wails v3 embeds the built
frontend with a plain //go:embed, so a build is: build the frontend, then
go build. There is no wails build step.
Run the desktop build for the current OS:
bash scripts/build-desktop.sh # macOS / Linux
pwsh -File scripts/build-desktop.ps1 # Windows
Artifacts land in build/bin. On Linux the build targets the host architecture
and produces the .deb, .rpm, and .AppImage; macOS produces the universal
playlist-forge.app; Windows cross-compiles both architectures and produces
the standalone playlist-forge-.exe plus NSIS installers with silent
/S install and uninstall support (the release job also publishes the exe as
playlist-forge--windows-.exe). Pass -SkipInstaller when NSIS
packaging is not needed. The product version comes
from the VERSION file. build/appicon.svg is the icon
master; build/appicon.png, build/darwin/icons.icns, and
build/windows/icon.ico are generated from it.
For an iteration loop without packaging:
pnpm --dir web run build
CGO_ENABLED=1 go run . # Linux (GTK4 / WebKitGTK 6.0)
go run . # macOS / Windows
scripts/test.sh (Bash) and scripts/test.ps1 (PowerShell) are the canonical
quality gate. Each installs the locked frontend dependencies and runs the full
frontend and Go checks — formatting, linting, type-checking, unit tests, the Go
race detector (when CGO is available on Linux or macOS), and the embedded
frontend build — then enforces coverage thresholds.
bash scripts/test.sh
pwsh -File scripts/test.ps1
Pass --skip-tests / -SkipTests to a build script only when the matching test
script has already passed for the same source state.
The individual commands, for troubleshooting a single stage:
# Go
gofmt -l main.go internal
go vet ./...
go test -race ./...
# Frontend (from web/)
pnpm run format:check
pnpm run lint
pnpm run typecheck
pnpm test
pnpm run build
Coverage. CI requires ≥ 95% statement coverage across the business and
external-boundary packages (app, playlist, openaiapi, soundiiz). The
frontend adapter, job polling, and delayed-overlay logic are held to 95% for
statements, branches, functions, and lines; page-level tests additionally cover
rendering and XSS-safe handling of user text.
Releases. Pushing a v* tag runs .github/workflows/release.yml: it writes
the tag version to VERSION, builds the native Linux, Windows, and macOS
artifacts (Linux on both an x86-64 and an ARM64 runner), writes
SHA256SUMS.txt, and creates or updates the GitHub Release.
https://api.openai.com/v1; no environment
variable can redirect it.https://soundiiz.com/go/import-playlist.
Redirects are not followed, and a returned handoff URL must use the exact
HTTPS Soundiiz host and documented path or it is rejected.OPENAI_API_KEY is read at runtime, never returned to the frontend, and
cannot be changed or removed through the interface while it is set.playlists.db or returned to
the frontend.| Symptom | Resolution |
|---|---|
| Credential store unavailable | Enable the config-file fallback in Settings, or configure Keychain / Credential Manager / Secret Service. |
| OpenAI validation failed | Confirm the key is active, billing is enabled, and the project can access gpt-6-sol or gpt-6-luna. |
| Operation is slow | After three seconds the app shows live progress and a Cancel button. Higher efforts and larger playlists take longer. |
| Soundiiz link expired | Create a fresh handoff from the saved playlist preview. |
| Streaming session expired | Open Settings (or use the banner) and choose Reconnect for that service. Imported playlists are kept; Browse shows Reconnect in place of Reload until you do. |
| "… is not available right now" | A transient TIDAL, Qobuz, or Soundiiz outage. Wait a moment and retry the Reload or handoff; the connection itself is still fine. |
| macOS won't open the app ("damaged" / "cannot be checked") | Expected for the unsigned build. See Opening the unsigned macOS build. |
Playlist Forge is distributed under the MIT License; see LICENSE.
Copyright © 2026 Paul Pietkiewicz.