sonoscli is a modern Go CLI to control Sonos speakers over your local network (UPnP/SOAP).
- Reliable discovery: SSDP + topology (
ZoneGroupTopology.GetZoneGroupState) with subnet scan fallback. - Coordinator-aware control: target any room; commands go to the group coordinator automatically.
- Playback controls: play/pause/stop/next/prev, plus
play-uri,linein, andtv. - Grouping: inspect groups, join/unjoin, party mode, dissolve groups, and solo a room.
- Queue: list/play/remove/clear queue entries.
- Favorites: list and play Sonos Favorites by index or title.
- Scenes: save/apply presets (grouping + per-room volume/mute).
- Spotify:
- Enqueue/play Spotify share links or canonical
spotify:<type>:<id>URIs (no Spotify credentials required). - Search Spotify via SMAPI (Sonos Music API; uses your linked service in Sonos).
- Optional Spotify Web API search (client credentials) if you want it.
- Enqueue/play Spotify share links or canonical
- Live events:
watchsubscribes to AVTransport + RenderingControl and prints changes. - Scriptable output:
--format plain|json|tsvplus--debugtracing.
This is not an official Sonos project.
- Your machine must be on the same network as your Sonos system.
- Speakers must be reachable on TCP port
1400(e.g.http://<speaker-ip>:1400/).
Spotify:
- Spotify must already be linked in the Sonos app.
- This CLI does not authenticate with Spotify; it enqueues Sonos “Spotify” URIs/metadata.
Spotify search (recommended, no Spotify Web API credentials):
sonos smapi searchuses Sonos SMAPI to search linked services (e.g. Spotify).- Some services require a one-time DeviceLink/AppLink flow:
sonos auth smapi begin|complete.
Spotify search via Spotify Web API (optional):
- If you want
sonos search spotify, you’ll need a Spotify Web API app (client credentials). SetSPOTIFY_CLIENT_IDandSPOTIFY_CLIENT_SECRET(or pass--client-id/--client-secret).
Install (Homebrew, single line):
brew install steipete/tap/sonoscliThis installs the sonos binary.
Upgrade later:
brew upgrade steipete/tap/sonoscliInstall from source (Go):
go install github.com/steipete/sonoscli/cmd/sonos@latest
sonos --versionBuild a local binary:
go build -o sonos ./cmd/sonos
./sonos --version
./sonos --helpNote: if you installed via Homebrew or go install, replace ./sonos with sonos.
Discover speakers:
./sonos discover
./sonos discover --format json
./sonos discover --all # include invisible/bonded devices (advanced)Show status (text or JSON):
./sonos status --name "Kitchen"
./sonos now --name "Kitchen"
./sonos status --name "Kitchen" --format jsonPlayback:
./sonos play --name "Kitchen"
./sonos pause --name "Kitchen"
./sonos stop --name "Kitchen"
./sonos next --name "Kitchen"
./sonos prev --name "Kitchen"Watch live events (track/volume changes):
./sonos watch --name "Kitchen"
./sonos watch --name "Kitchen" --format json
./sonos watch --name "Kitchen" --format tsvNote: this starts a local callback server for UPnP events; your OS firewall may prompt to allow incoming connections.
Run sonos --help for the full list. Most commonly used:
- Discovery & status:
discover,status/now,watch - Playback:
play,pause,stop,next,prev,open,enqueue,play-uri,linein,tv - Grouping:
group status,group join,group unjoin,group solo,group party,group dissolve - Queue:
queue list,queue play,queue remove,queue clear - Favorites:
favorites list,favorites open - Scenes:
scene save,scene apply,scene list,scene delete - Spotify search:
smapi search(recommended), optionalsearch spotify(Spotify Web API)
List the queue:
./sonos queue list --name "Kitchen"
./sonos queue list --name "Kitchen" --format jsonPlay or remove a queue entry (positions are 1-based):
./sonos queue play --name "Kitchen" 1
./sonos queue remove --name "Kitchen" 3Clear the queue:
./sonos queue clear --name "Kitchen"Save a scene (grouping + per-room volume/mute):
./sonos scene save "Evening"Apply a scene later:
./sonos scene apply "Evening"List / delete scenes:
./sonos scene list
./sonos scene delete "Evening"Scenes are stored in your user config dir as sonoscli/scenes.json (e.g. ~/.config/sonoscli/scenes.json on macOS/Linux).
List Sonos Favorites:
./sonos favorites list --name "Kitchen"
./sonos favorites list --name "Kitchen" --format jsonPlay by index (from the list):
./sonos favorites open --name "Kitchen" --index 1Or play by title (case-insensitive exact match):
./sonos favorites open --name "Kitchen" "BBC Radio 6 Music"Play an arbitrary URI:
./sonos play-uri --name "Kitchen" "https://example.com/stream.mp3"Force radio-style playback (useful for station-like streams):
./sonos play-uri --name "Kitchen" --radio --title "My Stream" "https://example.com/live.mp3"Switch to line-in (optionally from another speaker):
./sonos linein --name "Kitchen" --from "Living Room"Switch to TV input (soundbar):
./sonos tv --name "Living Room"Show current groups:
./sonos group status
./sonos group status --all # include invisible/bonded devices (advanced)Join Bedroom into Living Room’s group:
./sonos group join --name "Bedroom" --to "Living Room"Room targeting supports fuzzy substring matching (and will suggest matches on ambiguity):
./sonos group join --name "Off" --to "Bar" # "Office" joins "Bar"
./sonos group join --name "Bed" --to "Liv" # "Bedroom" joins "Living Room"Ungroup a speaker (make it standalone):
./sonos group unjoin --name "Bedroom"Solo a speaker (ungroup its current group so it plays alone):
./sonos group solo --name "Office"Party mode (join all visible speakers to a target group):
./sonos group party --to "Bar"Dissolve a group (ungroup all members of the group):
./sonos group dissolve --name "Living Room"Ungroup Office and play on Office only:
./sonos group solo --name "Office"
./sonos open --name "Office" "https://open.spotify.com/album/<id>"Re-join a speaker back into another group:
./sonos group join --name "Office" --to "Bar"Group volume / mute (affects the whole group):
./sonos group volume get --name "Living Room"
./sonos group volume set --name "Living Room" 25
./sonos group mute get --name "Living Room"
./sonos group mute toggle --name "Living Room"Volume / mute:
./sonos volume get --name "Kitchen"
./sonos volume set --name "Kitchen" 25
./sonos mute get --name "Kitchen"
./sonos mute toggle --name "Kitchen"Target a speaker by:
--name "Kitchen"(Sonos room name)--ip 192.168.0.250(speaker IP)
Most commands must be sent to the group coordinator (the device that owns transport state for the group). sonoscli resolves the coordinator automatically so commands behave like the Sonos app.
Search via Sonos (SMAPI; no Spotify Web API credentials):
./sonos smapi services
./sonos smapi categories --service "Spotify"
./sonos smapi browse --service "Spotify" --id root
./sonos auth smapi begin --service "Spotify"
# open the printed URL in a browser, link your account, then:
./sonos auth smapi complete --service "Spotify" --code <linkCode> --wait 5m
./sonos smapi search --service "Spotify" --category tracks "gareth emery"
./sonos smapi search --service "Spotify" --category tracks --open --name "Office" "gareth emery"Play from a search query (shortcut for SMAPI search + open):
./sonos play spotify --name "Office" "gareth emery"
./sonos play spotify --name "Office" --category albums "gareth emery"SMAPI tokens are stored under your user config dir as sonoscli/smapi_tokens.json (e.g. ~/.config/sonoscli/smapi_tokens.json on macOS/Linux).
Search via Spotify Web API (prints playable URIs):
export SPOTIFY_CLIENT_ID="..."
export SPOTIFY_CLIENT_SECRET="..."
./sonos search spotify --type track --limit 5 "daft punk harder better"
./sonos search spotify --type playlist "focus"Open the first search result directly on Sonos:
./sonos search spotify --open --name "Kitchen" "miles davis so what"Enqueue + play:
./sonos open --name "Kitchen" spotify:track:6NmXV4o6bmp704aPGyTVVG
./sonos open --name "Kitchen" https://open.spotify.com/track/6NmXV4o6bmp704aPGyTVVGEnqueue only:
./sonos enqueue --name "Kitchen" spotify:playlist:37i9dQZF1DXcBWIGoYBM5MNotes:
- The enqueue implementation tries Spotify Sonos service numbers
2311and3079for compatibility. - Use
--titleto override the queue display title for some entries.
make fmt
make test
make build
make lintmake lint requires golangci-lint:
brew install golangci-lint
# or:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latestThis repo includes a minimal package.json so you can drive the workflow with pnpm (no Node dependencies required):
pnpm build
pnpm test
pnpm format
pnpm lint
pnpm sonos -- discover
pnpm sonos -- status --name "Kitchen"
pnpm sonos -- open --name "Kitchen" spotify:track:6NmXV4o6bmp704aPGyTVVG
pnpm sonos -- search spotify "miles davis so what"
pnpm sonos -- group status
pnpm sonos -- queue list --name "Kitchen"CI runs: gofmt check, go vet, go test, and golangci-lint.
--ip <ip>: target by IP--name <name>: target by speaker name (defaults tosonos config defaultRoomif set)--timeout <duration>: discovery/network timeout (default5s)--format plain|json|tsv: output format (defaults tosonos config formatif set)--json: deprecated alias for--format json--debug: enable detailed trace logs (SSDP/topology/SOAP timings)
Persist small local defaults:
./sonos config get
./sonos config set defaultRoom "Office"
./sonos config set format json
./sonos config unset defaultRoomdiscoveris empty:- Some networks block multicast/SSDP;
sonosclifalls back to scanning local /24 subnets for port1400and then uses Sonos topology to list all rooms. - Ensure Wi‑Fi client isolation is off and you’re on the same LAN/subnet.
- Some networks block multicast/SSDP;
- Discovery is slow or flaky:
- Run
sonos --debug discoverto see whether SSDP multicast is timing out and whether topology calls are slow.
- Run
- Discovery / SOAP calls hang or time out on your network:
sonoscliretries local Sonos HTTP/SOAP calls viacurlas a workaround for some network/firmware quirks.
- Commands fail with UPnP/SOAP errors:
- Verify you can reach
http://<speaker-ip>:1400/from this machine. - Try targeting by
--name(it resolves the coordinator).
- Verify you can reach
- Spotify enqueue fails:
- Confirm Spotify is linked and playable in the Sonos app.
- Some systems behave differently per firmware/service configuration.
This project was informed by the Sonos control ecosystem and the SoCo Python library:
https://github.com/SoCo/SoCo
See docs/spec.md.
MIT License. See LICENSE.