Skip to content

zzwong/wiim-cli

Repository files navigation

wiim-cli

CI Go Reference Release Go 1.25+ License: MIT

Small, scriptable Go CLI for inspecting and controlling a WiiM device on the local network.

$ wiim --host wiim-ultra.local status
Name: WiiM Ultra
Host: wiim-ultra.local
Model: WiiM_Ultra
Firmware: Linkplay.5.2.813259
Online: yes
Wi-Fi: 5 GHz, 5745 MHz, RSSI -62 dBm
Volume: 35
Muted: no
State: play

$ wiim volume 40
Volume set to 40

$ wiim now
State: play
Title: Classical Sunrise
Artist: BBC Radio 3
Volume: 40

Requirements

  • A WiiM device (Pro, Ultra, Mini, etc.) on the same LAN. Other Linkplay-based streamers (Arylic, Audio Pro, etc.) share the same API and likely work too — see Compatibility for what's actually verified.
  • Go 1.25+ to build from source; not needed for prebuilt binaries.
  • Linux keyring (Secret Service / GNOME Keyring or KWallet) for wiim spotify commands; macOS uses Keychain automatically.
  • playerctl for wiim cliamp commands (Linux only).

Install

Prebuilt binaries for Linux, macOS, and Windows are on the Releases page.

With a Go toolchain:

go install github.com/zzwong/wiim-cli/cmd/wiim@latest

Or build from source:

git clone https://github.com/zzwong/wiim-cli.git
cd wiim-cli
make build      # writes ./wiim
make install    # or: go install ./cmd/wiim

make build/make install embed git describe --tags --always --dirty into wiim version. Untagged builds show the commit hash; dirty builds add -dirty.

Configuration

Don't know your device's hostname/IP yet? wiim discover finds it for you:

wiim discover           # SSDP scan of the local network, ~3s
wiim --json discover

Host resolution order: --host flag → WIIM_HOST env var → defaultHost in ~/.config/wiim-cli/config.json → error (host is required).

wiim setup --host <wiim-host>              # writes defaultHost to config
wiim config show
wiim config set maxVolume 55
wiim config set spotifyRedirectURI http://127.0.0.1:19872/login
wiim config unset spotifyRedirectURI
wiim config path
{
  "defaultHost": "wiim-ultra.local",
  "timeout": 3.0,
  "spotifyRedirectURI": "http://127.0.0.1:19872/login",
  "maxVolume": 55
}

maxVolume (default 55) caps absolute volume sets and relative volume increases.

Commands

# Discovery
wiim discover
wiim --json discover

# Status
wiim status
wiim --json status
wiim now
wiim cast-now

# Playback
wiim play
wiim pause
wiim stop
wiim next
wiim prev
wiim seek 30
wiim clear

# Volume
wiim volume
wiim volume 30
wiim volume +5
wiim volume -5
wiim mute
wiim unmute

# Input & presets
wiim input
wiim input hdmi
wiim preset list
wiim preset play 1

# Play media
wiim play-url https://example.com/song.mp3
wiim play-m3u https://example.com/station.m3u
wiim prompt-url https://example.com/alert.mp3
wiim play-file ./song.flac

# Spotify Connect
wiim spotify credentials set
wiim spotify credentials set-secret
wiim spotify credentials import-clipboard id
wiim spotify credentials import-clipboard secret
wiim spotify credentials status
wiim spotify credentials clear
wiim spotify login
wiim spotify logout
wiim spotify devices [--reauth]
wiim spotify transfer <spotify-device-id> [--no-play] [--reauth]
wiim spotify play spotify:playlist:<id> [spotify-device-id] [--reauth]

# cliamp (Linux, requires playerctl)
wiim cliamp status
wiim cliamp handoff

# Utility
wiim raw getStatusEx
wiim version
wiim completion bash        # also: fish, zsh, powershell

Global options (--host, --timeout, --config, --json) work before or after the command. Prefer config for daily use; --host is mainly an override for scripts/testing.

discover doesn't take --host — it multicasts an SSDP search and only lists devices that also answer the WiiM HTTP API, so unrelated UPnP gear (TVs, printers, routers) on the same LAN is filtered out. --timeout (default 3.0s) controls how long it waits for replies. See Compatibility in docs/api.md for which devices this can find.

Spotify — store credentials once, then log in:

wiim spotify credentials set   # prompts for client ID and secret
wiim spotify login

Clipboard imports use explicit id/secret subcommands so the CLI never guesses which is which. Tokens live in the OS keychain and refresh automatically; add --reauth to a Spotify command to relaunch the browser login flow if refresh fails. The default redirect URI is http://127.0.0.1:19872/login — override with config spotifyRedirectURI or env WIIM_SPOTIFY_REDIRECT_URI. See docs/security.md for storage details.

cliamp bridges playerctl -p cliamp (MPRIS) to WiiM. handoff only works for HTTP/HTTPS URLs — use play-file for local files and Spotify Connect for Spotify.

play-file serves the given file over a local HTTP server until stopped, so the WiiM can fetch it.

Output and errors

Human-readable output by default; --json for scripting. Runtime/API errors exit 1; validation/usage errors exit 2.

On failure, --json also changes what's printed to stderr: instead of a plain wiim: <message> line, you get a JSON error envelope so scripts don't have to string-match prose:

{
  "error": {
    "kind": "usage",
    "message": "volume must be between 0 and 100",
    "exitCode": 2
  }
}

kind is "usage" (exit 2) or "runtime" (exit 1), matching the process exit code.

Docs

  • docs/api.md — WiiM/Linkplay API reference, endpoint mappings, verified fields, quirks, and device compatibility.
  • docs/security.md — credential storage, OAuth token handling, LAN file-serving exposure, and TLS caveats.

Contributing

go test ./...   # no real WiiM device required

See CONTRIBUTING.md for dev setup, linting, and PR guidelines, and SECURITY.md to report a vulnerability.

Acknowledgments

This CLI was built directly from official WiiM and Arylic/Linkplay HTTP API documentation — see Acknowledgments in docs/api.md for the specific sources.

License

MIT — see LICENSE.

About

Scriptable Go CLI for controlling WiiM audio streamers over the LAN. Playback, volume with a safety cap, presets, Spotify Connect, Cast metadata

Resources

License

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages