couchctl
couchctl controls Samsung (Tizen) televisions and Android TV devices on your home network. It reads whether each screen is on, switches it on and off, opens apps, and sends the remote's app buttons to the apps you actually use.
Most remotes have buttons for apps you may never open (Prime Video, Disney+, a local streaming service). These buttons cannot be remapped on the device. couchctl watches which app is in front, and when a button opens one of those apps it opens your chosen app on top.
Install
pip install couchctl
Android TV devices also need adb (brew install android-platform-tools on macOS, apt install adb on Debian and Ubuntu).
Configure
couchctl reads ~/.config/couchctl/config.toml (or the file in $COUCHCTL_CONFIG, or --config). Copy examples/config.example.toml and change the addresses.
[devices.living-room]
kind = "samsung"
host = "192.168.1.20"
mac = "aa:bb:cc:dd:ee:ff"
[[devices.living-room.redirect]]
from = "3201910019365"
to = "3201606009684"
name = "Prime Video button to Spotify"
[devices.projector]
kind = "androidtv"
adb = "192.168.1.30:5555"
Give each television a fixed address in your router, so the config stays correct.
Use
couchctl state # on, off or unknown, for every device
couchctl pair living-room # once per Samsung set, then choose Allow on the TV
couchctl off living-room
couchctl on living-room # wake-on-LAN
couchctl launch living-room 3201606009684
couchctl key living-room KEY_HOME
couchctl front living-room # which redirected app is on screen
couchctl watch # redirect the app buttons until stopped
couchctl watch --dry-run # log presses without launching anything
Samsung televisions
The set answers HTTP on port 8001 without a password. That is enough to read its state, see which app is in front and open an app. Remote keys (power off, home, volume) use a websocket on port 8002, and newer sets ask for permission the first time. Run couchctl pair <device> while the set is on, and choose Allow on the television when it asks. couchctl keeps the token the set returns in ~/.config/couchctl/tokens.json (readable only by you) and uses it from then on.
couchctl on sends a wake-on-LAN packet to the mac in the config. The set only answers it when "Power on with mobile" is enabled (Settings, General, Network, Expert settings on most models).
A Samsung app id is the long number in the Samsung app store (3201606009684 is Spotify), or for a sideloaded app the id its package declares. To find the id behind a button, press the button and run couchctl front <device> <id> <id> ... with the ids you suspect, or read the list from the set with sdb shell 0 vd_applist if you have Tizen Studio.
Android TV
Turn on network debugging in the device's developer options and allow the adb prompt on screen once. Apps are named by their package (com.spotify.tv.android), and couchctl front prints whatever package is in front. A device in standby usually stops answering adb, so couchctl reconnects by itself when it comes back.
Most Android TV devices cannot be woken over the network. Some projectors only wake from a Bluetooth signal sent by their own remote.
How the redirect works
The watcher asks each device once a second which app is in front. When an app with a redirect becomes visible, it opens the replacement.
- It acts only when the app appears, so if you go back to that app on purpose it is left alone.
- When the watcher starts, or when a device comes back after being out of reach, the app already on screen is never treated as a press.
- Each device has its own thread, so a television that is off does not slow down the others.
The original app does appear for a second or two before it is replaced, and the redirect works only while the watcher runs on the same network as the screens. A Raspberry Pi is a good host for it. A systemd unit is in examples/couchctl-watch.service.
With --report-url, every redirect is also posted as JSON (device, from, to, name, outcome, message, time), with an optional bearer token read from the environment variable named by --report-token-env.
Limits
- couchctl must be on the same network as the screens. From another network every device reads as off, so use
couchctl state --maybe-awayon a laptop that moves between networks. - The Samsung websocket uses the set's own self-signed certificate, so that one connection is not verified.
- Tested on Samsung Tizen televisions from recent years and an XGIMI projector running Android TV.
Development
python -m venv .venv && .venv/bin/pip install -e '.[test]'
.venv/bin/pytest
The tests use a fake Samsung set and a fake adb, so they need no hardware.
License
MIT
Metadata
Release files for couchctl 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| couchctl-0.1.0.tar.gz | 18.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| couchctl-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.3 kB
Release files / couchctl-0.1.0.tar.gz
| Download URL | couchctl-0.1.0.tar.gz |
|---|---|
| Size | 18.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0e1a96690ab052725b22db0a07923c99d8fcfd866d4bd029a23cd4f6641a75e4
|
|
BLAKE2b-256 checksum How to use checksums |
0151c7b175b740092910bd4683bd5739098c2fc880d1150c959314a749e848f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logRelease files / couchctl-0.1.0-py3-none-any.whl
| Download URL | couchctl-0.1.0-py3-none-any.whl |
|---|---|
| Size | 17.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4b8a5f681fdd7b6ce7f9f8afb44597892fc0a98fb78f5b9f87476d98a22fa6b4
|
|
BLAKE2b-256 checksum How to use checksums |
ba1ba6c843a1beea91273abe8db43fe2c89e91bfd67efccd2c6462f7ef33bb8f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency log