npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

alexa-remote-mqtt

v2.0.4

Published

Bridge between Amazon Echo devices and MQTT

Readme

alexa-remote-mqtt

Node.js CLI that bridges Amazon Echo devices to MQTT, built on alexa-remote2 and mqtt-interfaces-core. It follows the mqtt-smarthome convention and is a lightweight replacement for a Node-RED flow using node-red-contrib-alexa-remote2-applestrudel.

Upgrading from 1.x? Topics, payloads and the CLI changed — see Upgrading from 1.x.

Topics

alexa is the instance name (--name, also the topic prefix). <device> is the name shown in the Alexa app (/, +, # replaced with _); the serial number works too, and for commands all addresses every music-capable device at once.

Status payloads are {"val": …, "ts": …, "lc": …} JSON (ts = time published, lc = last change); --no-json-payloads publishes the plain value instead. They are retained unless noted. set payloads may be a plain value or {"val": …}.

| Topic | Payload | | -------------------------------- | ---------------------------------------------------------------------- | | alexa/connected | 0 offline (LWT), 1 MQTT only, 2 MQTT + Alexa | | alexa/info | JSON about the running instance, incl. amazonPage, devices, push | | alexa/status/bridge/devices | list of devices (name, topic, serial, type, capabilities) | | alexa/status/bridge/routines | list of Alexa routines (after the first use of the routine command) | | alexa/maintenance/set/loglevel | error / warn / info / debug at runtime (--no-maintenance) | | alexa/maintenance/set/restart | graceful restart (systemd starts the service again) |

Status: alexa/status/<device>/…

| Item | Value | | -------------------------- | ----------------------------------------------------------------------------------------------------- | | player_state | PLAYING, PAUSED, IDLE, INTERRUPTED, FINISHED | | volume | 0-100 | | mute | true / false (volume 0 counts as muted) | | title, artist, album | current track / station info (empty when idle) | | provider | source, e.g. TuneIn, Spotify, Amazon Music | | image_url | cover art URL | | media | {state, title, artist, album, provider, image_url, media_id} | | progress | {progress, length} in ms — event, not retained, at most every 10 s | | last_voice_command | text spoken to this device (without wake word) — event, not retained | | last_activity | {text, response, utterance_type, timestamp} of the last utterance | | notifications | timers/alarms/reminders: [{id, type, status, label, time, trigger_time, remaining_time, recurring}] | | dnd | Do-Not-Disturb true / false | | bluetooth | {connected, name, address, paired: [{name, address, connected, profiles}]} | | equalizer | {bass, mid, treble} (push only, after a change) | | microphone | raw microphone-state push payload | | connected | device online true / false |

Commands: alexa/set/<device>/…

| Item | Payload | | ----------------------------------- | --------------------------------------------------------------------------------------- | | play, pause, next, previous | any (may be empty) | | player_state | PLAYING / PAUSED (or play / pause, true / false) | | shuffle, repeat | true / false | | volume | 0-100 | | mute | true / false — emulated as volume 0 and restore | | tunein | TuneIn guide id, e.g. s25111, or {"id":"p12345","type":"show"} | | text_command | text as if spoken to Alexa, e.g. play SWR3, next track, set a timer for 5 minutes | | speak | text-to-speech on the device | | announcement | announcement with chime; alexa/set/all/announcement plays on all devices in sync | | ssml | SSML, must start with <speak> | | sound | Amazon sound id, e.g. amzn_sfx_doorbell_chime_01 | | routine | Alexa routine by name, trigger utterance or id | | dnd | true / false | | bluetooth | paired device name or address to connect, false to disconnect | | equalizer | {"bass":2,"mid":0,"treble":-1} or 2,0,-1 (range usually -6..6) | | refresh | re-poll all state of this device now |

Aliases: say (speak), announce (announcement), text (text_command), prev (previous), skip (next), do_not_disturb (dnd). Text commands (speak, announcement, ssml, text_command, routine, sound) take the payload as it is, so 42 or true are said as written.

State updates arrive instantly via the Alexa push connection; additionally the full state is polled every --poll-interval seconds (default 300) to resynchronise.

Home Assistant

MQTT discovery is on by default (--no-ha-discovery disables it and clears what was announced). Every music-capable Echo becomes one HA device linked to a bridge device, with sensors (player state, title, artist, album, source, last voice command, bluetooth, timers), a volume slider, mute/DND switches, transport buttons, a text entity for text commands and notify entities for speak/announcement. An Echo that Amazon reports as offline shows as unavailable on its own.

Install & run

Requires Node.js ^20.19, ^22.12 or >= 24.

npm install -g alexa-remote-mqtt
alexa-remote-mqtt --mqtt-url mqtt://broker.local --amazon-page amazon.de

From a checkout: npm install && npm link (or npm start -- …). Lint with npm run lint, test with npm test.

Docker

Images are published to ghcr.io/hobbyquaker/alexa-remote-mqtt (latest, X.Y, X.Y.Z). Mount a volume for the login data and publish the login-proxy port for the first start:

docker run -d --name alexa-remote-mqtt -v alexa-remote-mqtt:/data -p 3001:3001 \
  -e ALEXA_REMOTE_MQTT_MQTT_URL=mqtt://broker.local -e ALEXA_REMOTE_MQTT_AMAZON_PAGE=amazon.de \
  ghcr.io/hobbyquaker/alexa-remote-mqtt

Inside the container --proxy-own-ip defaults to 127.0.0.1; open http://<docker-host>:3001/ for the login.

First start: login

On the first start no Amazon login exists yet. alexa-remote-mqtt starts a local login proxy and logs a URL like http://192.168.1.10:3001/ (at warn, so it is visible at any log level). Open it in a browser (on the same network), sign in with your Amazon account, and the login is stored in ~/.alexa-remote-mqtt/cookie.json (override with --cookie-file). Subsequent starts reuse and auto-refresh it.

--proxy-own-ip must be the IP address (not hostname) under which you reach the machine running alexa-remote-mqtt; it defaults to the first non-internal IPv4 address.

WSL2 / Docker: the auto-detected IP is the VM's/container's internal address, which your browser can't reach. Pass --proxy-own-ip 127.0.0.1 and open http://127.0.0.1:3001/ on the host (WSL2 forwards localhost ports; for Docker publish port 3001), or use a host IP that is actually routed to the process (e.g. WSL2 mirrored networking mode).

Run as a systemd service

sudo alexa-remote-mqtt --install --name alexa --mqtt-url mqtt://broker --amazon-page amazon.de --proxy-own-ip 192.168.1.10

--install sets up the template service alexa-remote-mqtt@<name>, so a second Amazon account is just another instance (with its own --proxy-port):

  • /etc/alexa-remote-mqtt/<name>.env — the given options as ALEXA_REMOTE_MQTT_* variables; edit and systemctl restart alexa-remote-mqtt@<name>.
  • /etc/mqtt-interfaces/broker.env — optional, shared by all mqtt-interfaces adapters (MQTT_URL, MQTT_USERNAME, MQTT_PASSWORD).
  • /var/lib/alexa-remote-mqtt/<name>/cookie.json — the login. An existing one (--cookie-file, the invoking user's ~/.alexa-remote-mqtt/cookie.json or a 1.x service) is copied there; otherwise the service starts the login proxy: journalctl -u alexa-remote-mqtt@<name> -f.

sudo alexa-remote-mqtt --uninstall --name <name> removes the instance and keeps its login.

Since the maintenance topics can restart the process and speak on your devices, restrict alexa/maintenance/# and alexa/set/# with a broker ACL if the broker is not on a trusted network — or run with --no-maintenance.

Options

-u, --mqtt-url               MQTT broker URL                       [default: "mqtt://localhost"]
    --mqtt-username          MQTT username
    --mqtt-password          MQTT password
    --mqtt-client-id-prefix  Prefix for the MQTT client id
    --mqtt-tls-ca            CA certificate file for mqtts://
-n, --name                   Instance name, also the topic prefix          [default: "alexa"]
-a, --amazon-page            Amazon domain of your account                 [default: "amazon.de"]
    --alexa-service-host     Alexa API host                        [default: "layla.amazon.com"]
-c, --cookie-file            File to persist the Amazon login
                                              [default: "~/.alexa-remote-mqtt/cookie.json"]
    --proxy-own-ip           IP of this machine for the login proxy        [default: auto]
    --proxy-port             Port of the login proxy                       [default: 3001]
-p, --poll-interval          Seconds between full state polls, 0 = push only  [default: 300]
    --json-payloads          {val, ts, lc} status payloads   [default: true, --no-json-payloads]
    --ha-discovery           Home Assistant MQTT discovery     [default: true, --no-ha-discovery]
    --ha-prefix              Home Assistant discovery prefix    [default: "homeassistant"]
    --maintenance            Accept maintenance topics         [default: true, --no-maintenance]
-v, --verbosity              Log level: error, warn, info, debug           [default: "info"]
    --install / --uninstall  Install/remove the systemd service alexa-remote-mqtt@<name>
    --config-schema          Print the JSON Schema of all options and exit

Every option can also be given as an environment variable with the prefix ALEXA_REMOTE_MQTT_, e.g. ALEXA_REMOTE_MQTT_MQTT_URL=mqtt://broker.local; the broker settings fall back to the unprefixed MQTT_URL, MQTT_USERNAME, MQTT_PASSWORD.

Example

mosquitto_sub -v -t 'alexa/#'
mosquitto_pub -t 'alexa/set/Kitchen/pause' -m ''
mosquitto_pub -t 'alexa/set/Kitchen/volume' -m 30
mosquitto_pub -t 'alexa/set/Kitchen/text_command' -m 'play SWR3'
mosquitto_pub -t 'alexa/set/all/announcement' -m 'Dinner is ready'
mosquitto_pub -t 'alexa/set/Kitchen/routine' -m 'Good night'

Upgrading from 1.x

2.0 moves the adapter onto mqtt-interfaces-core and the mqtt-smarthome 2.x spec. There are no compatibility shims — topics, payloads and options changed:

| 1.x | 2.0 | | ------------------------------------------------------------- | --------------------------------------------------------------------- | | alexa/status/bridge/connected | alexa/connected | | plain status payloads | {"val": …, "ts": …, "lc": …} (--no-json-payloads for the old way) | | audioPlayerState, playerState | player_state | | isMuted (ON/OFF) | mute (true/false) | | imageUrl, lastVoiceCommand, lastActivity, textCommand | image_url, last_voice_command, last_activity, text_command | | ON/OFF booleans | true/false everywhere | | --topic-prefix / -t | --name / -n (same default alexa) | | --verbose / -v | --verbosity debug | | --ha-discovery (off by default) | on by default, --no-ha-discovery | | service alexa-remote-mqtt | template service alexa-remote-mqtt@<name> | | /etc/default/alexa-remote-mqtt | /etc/alexa-remote-mqtt/<name>.env | | /var/lib/alexa-remote-mqtt/cookie.json | /var/lib/alexa-remote-mqtt/<name>/cookie.json |

New: alexa/info, the maintenance topics, --config-schema, typed environment variables with the shared MQTT_* fallback, per-device availability and a bridge device in Home Assistant.

sudo alexa-remote-mqtt --install --name alexa … copies the login of the 1.x service and tells you how to remove the old unit:

sudo systemctl disable --now alexa-remote-mqtt
sudo rm /etc/systemd/system/alexa-remote-mqtt.service /etc/default/alexa-remote-mqtt

The 1.x Home Assistant discovery used one config topic per entity; those retained messages are not cleared automatically. Remove them once with:

mosquitto_sub -v -t 'homeassistant/+/alexa-remote-mqtt_+/+/config' --retained-only -W 2 |
  awk '{print $1}' | xargs -I{} mosquitto_pub -r -n -t {}

Known upstream issue

alexa-remote2 8.x drops push messages that are split across several HTTP/2 chunks (all larger media/player events). alexa-remote-mqtt works around this by reassembling chunks before they reach the library; see alexa-remote2-issue-draft.md.

Credits

alexa-remote-mqtt is a thin layer on top of the hard work of others:

License

MIT © Sebastian "hobbyquaker" Raff [email protected] — see LICENSE.