Control an LG webOS TV from Linux — wake it when your PC resumes from sleep, switch it to the PC's HDMI input, and put it to sleep when the PC suspends (only if the PC is the active input).
A small, single-binary, no-GUI take on the Windows-only LGTV Companion, aimed at HTPCs running Linux / SteamOS (e.g. Bazzite). Configured with one JSON file and driven by systemd units.
- Wake on resume — Wake-on-LAN magic packets plus a webOS power-on handshake.
- Sleep on suspend, input-aware — powers the TV off when the PC suspends,
but only if the PC's HDMI input is the currently active source (so it won't
turn the TV off while you're watching something else). Use
--forceto skip the check. - Switch HDMI input on wake — optionally select the PC's input after waking.
- Manual control —
lgctl on|off|input N|statusfor scripts and hotkeys.
No external dependencies: it's pure Go standard library (its own minimal
WebSocket client), so go build produces one static binary.
Run the command:
curl -fsSL https://raw.githubusercontent.com/lmrisdal/lgctl/main/packaging/install.sh | shInstalls it to /usr/local/bin/lgctl, writes an example config to /etc/lgctl,
and asks which systemd services to enable (sleep/resume and boot/shutdown).
Then Configure and Pair below.
Non-interactive flags
Answer the service prompts up front (the default with no terminal — e.g. fully piped — is to install both):
... | sh -s -- --no-power # skip the boot/shutdown service
... | sh -s -- --no-sleep # skip the sleep/resume service
... | sh -s -- -y # accept defaults (both services)Run install.sh --help for the full option list.
Each tagged release ships static amd64/arm64 Linux binaries.
sudo lgctl update # fetch the latest release, verify its checksum, swap in placesudo lgctl uninstallInteractive: it lists the installed systemd services (and whether each is
enabled), then lets you pick which to remove — or choose Everything to also
delete the binary and /etc/lgctl (config + saved pairing key). Disabling a
service never runs its shutdown hook, so uninstalling does not toggle the TV.
Prefer to compile from source? Clone and build — it's pure Go standard library, so one command produces the static binary:
git clone https://github.com/lmrisdal/lgctl
cd lgctl
CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -o lgctl .
sudo install -Dm755 lgctl /usr/local/bin/lgctlThen install the config and systemd units as described under Configure and Power events.
install.sh placed an example config at /etc/lgctl/config.json (or copy
packaging/config.example.json there yourself). Edit it:
| Field | Meaning |
|---|---|
ip |
TV's IP address (give it a DHCP reservation). |
mac |
TV's MAC for WOL. String, or array for multiple NICs. |
ssl |
Use the encrypted port 3001 (default true); false = 3000. |
hdmi_input |
HDMI port the PC is on (1–4). |
check_input_on_off |
Only power off if the PC is the active input. |
set_input_on_wake |
Switch to the PC's input after waking. |
input_wake_delay_sec |
Delay before switching input (default 1). |
timeout_sec |
How long to retry WOL + connect on power-on (default 20). |
subnet |
Mask for the directed-broadcast WOL target. |
The config file is searched in this order when --config is omitted:
$LGCTL_CONFIG, /etc/lgctl/config.json, ~/.config/lgctl/config.json.
The TV shows a one-time prompt the first time you connect:
sudo lgctl pair # accept the prompt on the TV with your remoteThe received client_key is written back into your config file. After that,
all commands work non-interactively.
install.sh offers two units (it asks about each) that cover all four power
events:
lgctl-sleep.service— powers the TV off just before suspend, back on at resume.lgctl-power.service— wakes the TV at boot (fire-and-forget, so an unreachable TV never delays boot) and powers it off at shutdown/reboot (ordered after the network so the TV is still reachable).
Both power-off paths are input-aware (check_input_on_off), so they leave the
TV alone if you're watching another source. To skip the boot power-on, remove
the ExecStart= line from lgctl-power.service.
Test it:
systemctl suspendInstalling the units by hand (if you're not using install.sh)
sudo install -Dm644 packaging/lgctl-sleep.service /etc/systemd/system/lgctl-sleep.service
sudo install -Dm644 packaging/lgctl-power.service /etc/systemd/system/lgctl-power.service
sudo systemctl daemon-reload
sudo systemctl enable lgctl-sleep.service lgctl-power.service
# Arm off-at-shutdown now (don't 'start' the sleep unit — that would power the
# TV off immediately).
sudo systemctl start lgctl-power.serviceOn immutable distros (Bazzite/SteamOS),
/usr/local/bin(a symlink to/var/usrlocal/bin),/etc, and/etc/systemd/systemare all writable, so this survives OS image updates.
lgctl on # wake (WOL + power on) and optionally switch input
lgctl off # power off, but only if the PC is the active input
lgctl off --force # power off regardless
lgctl input 2 # switch to HDMI 2 (wakes the TV first if it's off)
lgctl input-type 2 pc # set HDMI 2's input type to "PC" (icon + label)
lgctl input-type list # list the available input types
lgctl status # show power state and active input
sudo lgctl update # download and install the latest release in placeon/off also accept the aliases resume/suspend.
update fetches the latest GitHub release for your architecture, verifies it
against the published SHA256SUMS.txt, and atomically swaps the running binary.
Use sudo when lgctl lives in a root-owned path like /usr/local/bin; add
--force to reinstall even when you're already on the latest version.
lgctl pairautomatically enables Wake-on-LAN on the TV (best-effort, via the same luna workaround the Windows app uses). If it reports it couldn't, enable it manually in the TV's network settings.- The TV must also have "Quick Start+" (or LAN/Wi-Fi standby) enabled for WOL to work from a fully-off state — set this once in the TV's General settings.
- Wire the PC to the TV over Ethernet for the most reliable WOL.