SoundSync by Botify — Windows Electron tray app that auto-syncs SoundCloud likes and playlists to a local folder using yt-dlp + ffmpeg.
Previously released as SoundCloud Auto Sync / SC Auto Downloader. Rebranded to SoundSync in v2.0.6.
Current version: v2.0.7
- What it does
- Install / update
- Basic usage
- Update controls
- Architecture
- Security
- Developer setup
- Troubleshooting
- CLI
- Brand assets
- Project links
- License
- Runs in the system tray; no foreground window required.
- Monitors a list of SoundCloud usernames (their public likes) and playlist URLs.
- On an interval, fetches new tracks and downloads them as MP3 with embedded metadata + artwork.
- One-off Download URL... entry point for any SoundCloud track or playlist.
- Tray menu surfaces status (Syncing / Idle / Error), last-sync time, and download count.
- Auto-update via GitHub Releases through
electron-updater(configurable — see Update controls).
Install via the released NSIS installer published on GitHub:
- Releases: https://github.com/Botify-Network/soundsync/releases
- Latest release: see the Latest release badge above.
electron-updater only detects an update when the target GitHub Release has both the packaged installer and the manifest attached:
SoundSync Setup <version>.exe— NSIS installer produced byelectron-builderlatest.yml— manifestelectron-updaterreads
A notes-only release (tag + body, no binaries) will not be detected by installed clients. See docs/deployment.md for the full release flow.
- Launch the app (it minimizes to the tray; double-click the tray icon to open Settings).
- Downloads page → choose a download folder.
- Monitoring page → add SoundCloud usernames (their
/likesare followed) and/or full playlist URLs (must contain/sets/). - Toggle Auto-sync on launch in Startup to begin monitoring immediately on app start.
- Set Sync interval (default 15 min).
- Sync Now from the tray menu or footer button forces an immediate sync.
See docs/operator.md for the full tray + settings walkthrough.
Settings → Startup / App Updates card:
| Setting | Default | Effect |
|---|---|---|
| Check for updates automatically | on | Startup check + background download via electron-updater |
| Install updates on next restart | on | Apply downloaded update silently when app quits. Off = wait for explicit "Install now" |
| Check for updates (button) | n/a | Manual on-demand check; works regardless of the auto-check toggle |
| Install now (button) | n/a | Triggers quitAndInstall() when a downloaded update is pending |
Update errors surface as tray balloons.
┌─ Tray menu ────────┐ ┌─ Settings window (Electron renderer) ─┐
│ Status / Sync Now │ │ Dashboard · Downloads · Monitoring │
│ Pause / Auto-Sync │ │ Engine · Diagnostics │
└─────────┬──────────┘ └────────────────┬──────────────────────┘
│ │
│ IPC (contextIsolation: true) │
└────────────────┬───────────────┘
│
┌────────▼──────────────────────────────────────┐
│ Electron main (src/main.js) │
│ · Lifecycle · Tray · IPC handlers · Updater │
│ · electron-store settings │
└──┬──────────────┬─────────────────┬───────────┘
│ │ │
┌────────────▼──┐ ┌────────▼─────────┐ ┌────▼──────────────────┐
│ services/ │ │ services/ │ │ services/paths.js │
│ downloader.js │ │ soundcloud- │ │ (yt-dlp / ffmpeg path │
│ (queue + │ │ monitor.js │ │ resolution: bundled │
│ rate-limit + │ │ (sync loop + │ │ resources/ → PATH │
│ encode) │ │ URL validation) │ │ fallback) │
└────────┬──────┘ └────────┬─────────┘ └────┬───────────────────┘
│ │ │
└──────────────────┴─────┬───────────┘
│
┌───────────▼──────────────┐
│ Bundled tools │
│ resources/yt-dlp.exe │
│ resources/ffmpeg.exe │
└──────────────────────────┘
Full architecture details: docs/architecture.md.
Highlights (full policy in SECURITY.md, full hardening notes in docs/security.md):
- Renderer XSS fix — settings UI never injects user-supplied usernames / playlist URLs / titles via
innerHTML. All list-item construction usescreateElement+textContent. - Safer process execution — main-process diagnostics and
fetch-playlist-metadata(which receives a user-controlled URL) do not shell-interpolate. Allyt-dlpandffmpeginvocations use argv arrays viaspawn/execFile. - CLI hardening —
cli.jsshell-interpolated calls converted toexecFileSyncwith argv arrays. - Rate-limit / network hardening —
yt-dlpcalls pass--retries 10,--retry-sleep http:exp=1:30,--socket-timeout 30,--sleep-requests 1; 3-attempt app-level retry with 15s/30s/60s backoff; 90s queue cooldown on 429. - Configurable auto-updater — checks, downloads, and install-on-quit can each be disabled.
- Electron security —
contextIsolation: true,nodeIntegration: false, whitelisted preload bridge.
npm install
npm start # launches Electron pointing at src/main.jsRequires yt-dlp and ffmpeg either bundled in resources/ (preferred — picked up by getYtDlpPath() / getFfmpegPath()) or on PATH.
Syntax checks (no test suite yet — see #2)
node --check src/main.js
node --check src/preload.js
node --check cli.js
node --check src/services/downloader.js
node --check src/services/soundcloud-monitor.jsnpm run build:winprebuild/prebuild:winauto-runscripts/bump-version.js(patch bump). To build without bumping, runelectron-builder --windirectly.- Output goes to
dist/. BothSoundSync Setup <version>.exeandlatest.ymlmust be uploaded to the GitHub Release for the auto-updater to detect the new version.
npm run bump # patch: 2.0.7 → 2.0.8
npm run bump:minor # minor: 2.0.7 → 2.1.0
npm run bump:major # major: 2.0.7 → 3.0.0Full developer guide: docs/developer.md.
| Symptom | Cause | Fix |
|---|---|---|
| Sync stalls, no new downloads | SoundCloud rate-limit (429) | App auto-applies 90s queue cooldown + 3-attempt backoff. Wait or reduce monitored sources. |
yt-dlp not found in diagnostics |
Bundled resources/yt-dlp.exe missing and not on PATH |
Install yt-dlp globally or restore the bundled binary. |
ffmpeg not found in diagnostics |
Same as above for ffmpeg. | Install ffmpeg globally or restore the bundled binary. |
| Auto-updater never finds new version | Release missing latest.yml or SoundSync Setup <version>.exe |
Re-upload both artifacts to the release; see auto-updater artifact requirement. |
| Google Drive File Stream download path errors | Drive virtual mount not present | Diagnostics now hints when My Drive is unavailable; mount Drive or pick a local folder. |
| Tray icon missing after install | App didn't acquire single-instance lock | Quit any existing SoundSync process, relaunch. |
Full guide: docs/troubleshooting.md.
cli.js provides a console interface independent of the Electron app:
node cli.js test # diagnostics
node cli.js config # interactive configure
node cli.js settings # show current config
node cli.js sync # run a sync now
node cli.js install # install deps + check bundled tools
node cli.js gui # launch the Electron app
⚠️ The CLI maintains its own config at%APPDATA%\soundsync\config.json(separate from the Electron app'selectron-store). It reads the legacy%APPDATA%\soundcloud-auto-sync\config.jsonif the new path doesn't exist. The CLI'ssyncpath does not yet share the rate-limit hardening that the Electron sync uses — tracked in #2.
Local brand pack lives in assets/brand/ and is governed by the Botify design tokens. Runtime assets used by the app:
SoundSync_app_icon_{64,128,256,512}.png— app icon (rounded-square master with radar rings)SoundSync_badge_orb_512.png— circular badge variantSoundSync_sidebar_logo_{128,256,512}.png— sharpened sidebar mark (minimal style, optimized for small render)SoundSync_favicon_{16,32}.png— favicon setSoundSync_taskbar_icon.ico— multi-size Windows .ico (16/32/48/64/128/256)SoundSync_transparent_banner_{2048x682,trimmed}.png— README / about banner
Source 1254×1254 masters and the runtime contact sheet live in design/soundsync-template-review/.
- Repository: https://github.com/Botify-Network/soundsync
- Releases: https://github.com/Botify-Network/soundsync/releases
- Issues: https://github.com/Botify-Network/soundsync/issues
- Docs initiative: #1
- Engineering cleanup initiative: #2
- Governance hub (parent org): Botify-Network/botify-network-site
See CONTRIBUTING.md. All PRs require operator approval before merge. No deploys without explicit operator approval. No secrets in any commit, issue, comment, or attachment.
See CHANGELOG.md.
MIT — see package.json.
