sofatui
A terminal remote control for the Apple TV. Press keys or click buttons to navigate,
and stream local video files to the TV from a / command prompt with tab completion.
╭────────────────────────────────────────────────╮
│ ◆ Sofa TV ● ON │
│ Apple TV 4K (gen 3) · tvOS 27.0 build 24J361 │
├────────────────────────────────────────────────┤
│ ▶ PLAYING AirPlay │
│ Untitled media │
│ │
│ ━━━━━─────────────────────────── 5:36 / 38:33 │
├────────────────────────────────────────────────┤
│ ╭───────╮ │
│ │ ▲ │ │
│ ╭───────┼───────┼───────╮ │
│ │ ◀ │ OK │ ▶ │ │
│ ╰───────┼───────┼───────╯ │
│ │ ▼ │ │
│ ╰───────╯ │
│ ╭────────╮ ╭────────╮ ╭────────╮ │
│ │ BACK │ │ HOME │ │ ▶ II │ │
│ ╰────────╯ ╰────────╯ ╰────────╯ │
│ ╭────────╮ ╭────────╮ ╭────────╮ │
│ │ « SKIP │ │ POWER │ │ SKIP » │ │
│ ╰────────╯ ╰────────╯ ╰────────╯ │
├────────────────────────────────────────────────┤
│ › sent up │
╰────────────────────────────────────────────────╯
The layout shrinks with the terminal: boxed remote, compact card, or three status lines.
Run
With uv, no installation needed:
uvx --from git+https://github.com/coffeemakr/sofatui sofatui # find the Apple TV
uvx --from git+https://github.com/coffeemakr/sofatui sofatui 192.168.1.100
From a checkout:
uv run sofatui [host] # in the repository
uvx --from . sofatui [host] # same, as an isolated tool
Or install it as a command: uv tool install git+https://github.com/coffeemakr/sofatui.
Without a host, sofatui scans the network and connects if it finds exactly one device.
$ATV_HOST sets a default address. Linux and macOS only.
Setup
sofatui uses pyatv and its stored credentials (~/.pyatv.conf).
Pair once over AirPlay, which also enables the remote control buttons:
uvx --from pyatv atvremote -s <address> --protocol airplay pair
If the Apple TV has an AirPlay password (Settings → AirPlay and HomeKit), enter that password when asked for the PIN. sofatui notices that the device wants a password and asks for it, offering to save it for next time. To skip the question, provide it in one of these ways:
--password <password>- the
AIRPLAY_PASSWORDenvironment variable - the file
~/.config/sofatui/password, or.airplay-passwordin the current directory
Keys
| Key | Action |
|---|---|
| Arrow keys | Move |
| Enter | OK / select |
| Esc | Back (menu) |
h |
Home |
| Space | Play / pause |
[ and ] |
Skip back / forward |
+ and - |
Volume up / down |
m |
Mute |
P |
Power on / off |
/ |
Open the command prompt |
q, Ctrl+C |
Quit |
The volume keys only work while the Apple TV reports that it controls the volume of your TV or receiver. That needs HDMI-CEC (Settings → Remotes and Devices → Volume Control → Auto); with volume control over infrared, only the physical remote can change the volume.
Buttons can also be clicked. Because the mouse is captured, select text with Shift+drag.
Commands
| Command | Does |
|---|---|
/stream <file> |
Play a local file on the Apple TV, in the background |
/stop |
Stop the background stream |
/help |
List the commands |
/quit |
Leave sofatui |
In the prompt, Tab (or ↓) completes commands and file paths and then steps through the matches, Shift+Tab (or ↑) steps backwards, and Esc closes it. Suggestions can be clicked.
The Apple TV must be able to play the format; only H.264/AAC .mp4 has been tested.
Background streams
The Apple TV pulls the file from your machine and stops as soon as the AirPlay session
that started it closes, so a process has to stay alive while it plays. /stream starts
that process detached: you can quit sofatui or close the terminal and the video keeps
playing. A remote started later shows the running stream (⇡ file) and can /stop it.
The same is available without the remote:
sofatui stream film.mp4 [host] # play and wait until it ends (Ctrl+C stops)
sofatui stream -d film.mp4 [host] # play in the background and return
sofatui stop [host] # stop background streams
There is one stream per device; starting another replaces it. The stream ends when the machine sleeps or shuts down.
Releasing
Bump the version with uv version --bump patch (or minor, major), commit, and
publish a GitHub release tagged v<version>. The Publish workflow builds the package
and uploads it to PyPI; it stops if the tag and the version differ.
Known issues
- pyatv is patched at startup. pyatv 0.18.0 does not yet handle AirPlay passwords
on AirPlay 2, the way current tvOS starts URL playback, or the mute key, so sofatui
patches these in when it starts (
src/sofatui/pyatv_patches.py, based on pyatv#2846). The pyatv version is pinned for that reason, and the patches should go away once pyatv supports this itself. - Tested on one device only: an Apple TV 4K (3rd generation) on tvOS 27.
License
MIT, see LICENSE.
Metadata
Release files for sofatui 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 | |
|---|---|---|---|
| sofatui-0.1.0.tar.gz | 149.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sofatui-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 173.0 kB
Release files / sofatui-0.1.0.tar.gz
| Download URL | sofatui-0.1.0.tar.gz |
|---|---|
| Size | 149.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
63ca7d006d2b6fac52a190e61a24c8f0868447082e3c91c6210304f582e46179
|
|
BLAKE2b-256 checksum How to use checksums |
f2429f040e4d6461c3c383e62ffaa902c4a1f661a6b6fc1b7043795197dee4ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / sofatui-0.1.0-py3-none-any.whl
| Download URL | sofatui-0.1.0-py3-none-any.whl |
|---|---|
| Size | 23.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
19787ff406c979a7eacd6e892a72711ab7a3140164306848ffee83a99297f459
|
|
BLAKE2b-256 checksum How to use checksums |
d88e52661e5c7488a68bfff039c8bc1cb532332e4be2b2fe1c7e4cc3dfc1959e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|