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- 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 spotifycommands; macOS uses Keychain automatically. - playerctl for
wiim cliampcommands (Linux only).
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@latestOr 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/wiimmake build/make install embed git describe --tags --always --dirty into wiim version. Untagged builds show the commit hash; dirty builds add -dirty.
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 discoverTargeted host resolution precedence is exactly: --host > WIIM_HOST > explicit --device > defaultDevice > defaultHost. The first four entries select a host from the command line, environment, named profile, or configured default profile; defaultHost is the
legacy direct-host fallback. If no source resolves, the command errors.
wiim setup --host <wiim-host> # writes legacy 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
# Name multiple WiiM devices and select one by default (all local config operations).
wiim device add living-room wiim-living.local
wiim device add office wiim-office.local
wiim device use living-room
wiim device listThe complete config shape is:
{
"defaultHost": "wiim-ultra.local",
"timeout": 3.0,
"spotifyRedirectURI": "http://127.0.0.1:19872/login",
"maxVolume": 55,
"defaultDevice": "living-room",
"devices": {
"living-room": {"host": "wiim-living.local"},
"office": {"host": "wiim-office.local"}
}
}defaultDevice names an entry in devices; each profile currently contains a host. The
device list, device add, device use, and device remove commands mutate only this local
JSON file and never device state. Existing defaultHost configurations remain valid, and the
CLI does not automatically migrate them to a profile; use device add/device use explicitly
when adopting named profiles. maxVolume (default 55) caps absolute volume sets and relative
volume increases.
# Discovery (read-only; no target is selected)
wiim discover
wiim device discover # alias for the same hostless discovery path
wiim --json discover
# Named device profiles (local config only)
wiim device list
wiim device add <name> <host>
wiim device remove <name>
wiim device use <name>
# Noninteractive discovery-to-config workflow
wiim device discover
wiim device add living-room <discovered-host>
wiim device use living-room
wiim --device living-room status
# Status
wiim status
wiim --json status
wiim now
wiim cast-now
# Multiroom group inspection (read-only)
wiim --device living-room group status
wiim --device living-room group members
wiim --device living-room --json group status
wiim --device living-room --json group members
# 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 versionGlobal options (--host, --device, --timeout, --config, --json) work before or after
commands where applicable. --device <name> targets a saved profile without changing the
config and applies only to commands that target a WiiM (including cliamp handoff/status);
it is rejected for setup, configuration, profile-management, Spotify, version, and discovery
commands. Prefer named profiles/config for daily use, while --host is mainly an override for
scripts/testing.
group status and group members are read-only multiroom inspection commands. They query
the selected host (including the host resolved from --device <name>); they do not change
that profile, grouping, playback, volume, mute state, or any other audio state. group status
supports --json and reports the stable normalized fields name, host, model, firmware,
role, grouped, groupName, memberCount, wmrmVersion, and masterUUID (optional empty
fields are omitted). Roles are master (the selected host reports guest devices), slave (the
selected device reports that it is a guest), standalone (not grouped and has no guests), or
unknown (the response does not provide enough reliable role information). group members
lists the guest devices reported by the selected host and also supports --json; it does not
discover or modify other devices. There are no first-class mutating group commands: join,
leave, kick, group volume/mute, and channel changes are out of scope. The raw escape hatch
can issue arbitrary API requests,
including mutations; use it only with explicit care and permission.
discover and device discover reject explicit --host or --device flags — they
multicast an SSDP search and only list devices that also answer the WiiM HTTP API, so
unrelated UPnP gear (TVs, printers, routers) on the same LAN is filtered out. Ambient
WIIM_HOST, defaultDevice, and defaultHost are ignored by discovery. Discovery is read-only:
it validates candidates with status requests but does not write config or change device state.
--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 loginClipboard 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.
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/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.
go test ./... # no real WiiM device requiredSee CONTRIBUTING.md for dev setup, linting, and PR guidelines, and SECURITY.md to report a vulnerability.
This CLI was built directly from official WiiM and Arylic/Linkplay HTTP API documentation —
see Acknowledgments in docs/api.md for the specific sources.
MIT — see LICENSE.