If you run two machines — a work laptop and a personal desktop — connected to a Samsung M8, you already know the pain: reach for the remote, navigate the OSD menu, switch source, repeat twenty times a day. Here's how to collapse that into a single terminal command using the SmartThings CLI.
The best part: this approach works identically on both macOS and Linux since it's Node.js-based.
How This Works
The Samsung M8 is a SmartThings-connected display. Samsung exposes a first-party CLI — @smartthings/cli — that can send commands to any registered SmartThings device, including input source switching on the M8. No hacking, no reverse engineering, no X11 tools.
What You Need
- Samsung M8 monitor connected to your SmartThings account
- Node.js (we'll use
asdffor version management) - SmartThings CLI installed globally via npm
- Your M8's SmartThings device ID
Step 1: Install Node.js via asdf
asdf works the same on macOS and Linux, which is why it's the cleanest approach here.
macOS:
brew install asdf
Linux (Ubuntu/Debian):
sudo apt install curl git
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
echo '. "$HOME/.asdf/asdf.sh"' >> ~/.zshrc
source ~/.zshrc
Then install Node.js:
asdf plugin add nodejs
asdf install nodejs 24.13.0
asdf global nodejs 24.13.0
Verify:
node --version # v24.13.0
Step 2: Install the SmartThings CLI
npm install -g @smartthings/cli
Verify:
smartthings --version
Step 3: Authenticate with SmartThings
smartthings devices
This will open a browser and ask you to log in with your Samsung account. After authentication, it lists all your SmartThings devices.
Step 4: Find Your M8 Device ID
After authentication, smartthings devices outputs a table. Find your Samsung M8 and copy its device ID — it looks like a UUID:
┌────┬─────────────────┬──────────────────────────────────────┐
│ # │ Label │ Device ID │
├────┼─────────────────┼──────────────────────────────────────┤
│ 1 │ Samsung M8 │ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │
└────┴─────────────────┴──────────────────────────────────────┘
Export it in your ~/.zshrc.local (keep it out of your dotfiles repo since it's device-specific):
export SMARTTHINGS_MONITOR_ID='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
Step 5: The Toggle Script
Create ~/dotfiles/scripts/monitor_input.sh:
#!/usr/bin/env bash
# Control Samsung M8 monitor input via SmartThings CLI
# Requires: smartthings CLI + SMARTTHINGS_MONITOR_ID env var set in ~/.zshrc.local
_smartthings_cmd() {
local st_bin="$HOME/.asdf/installs/nodejs/24.13.0/bin/smartthings"
if [[ -x "$st_bin" ]]; then
"$st_bin" "$@"
else
command smartthings "$@"
fi
}
_monitor_check() {
if ! _smartthings_cmd --version &>/dev/null; then
echo "smartthings CLI not found." >&2
echo "Run: npm install -g @smartthings/cli" >&2
return 1
fi
if [[ -z "$SMARTTHINGS_MONITOR_ID" ]]; then
echo "SMARTTHINGS_MONITOR_ID is not set." >&2
echo "Run: smartthings devices → find your M8 device ID" >&2
echo "Then add to ~/.zshrc.local: export SMARTTHINGS_MONITOR_ID='<id>'" >&2
return 1
fi
}
monitor_hdmi1() {
_monitor_check || return 1
echo "Switching to HDMI 1..."
_smartthings_cmd devices:commands "$SMARTTHINGS_MONITOR_ID" \
'main:mediaInputSource:setInputSource("HDMI1")'
}
monitor_hdmi2() {
_monitor_check || return 1
echo "Switching to HDMI 2..."
_smartthings_cmd devices:commands "$SMARTTHINGS_MONITOR_ID" \
'main:mediaInputSource:setInputSource("HDMI2")'
}
monitor_toggle() {
_monitor_check || return 1
local current
current=$(_smartthings_cmd devices:status "$SMARTTHINGS_MONITOR_ID" 2>/dev/null \
| jq -r '.components.main."samsungvd.mediaInputSource".inputSource.value // empty')
if [[ -z "$current" ]]; then
echo "Could not read current input source." >&2
return 1
fi
echo "Current input: $current"
if [[ "$current" == "HDMI1" ]]; then
monitor_hdmi2
else
monitor_hdmi1
fi
}
# Allow running directly: ./monitor_input.sh [hdmi1|hdmi2|toggle]
case "${1:-}" in
hdmi1) monitor_hdmi1 ;;
hdmi2) monitor_hdmi2 ;;
toggle) monitor_toggle ;;
*)
echo "Usage: $0 [hdmi1|hdmi2|toggle]"
echo " or source this file and call monitor_hdmi1 / monitor_hdmi2 / monitor_toggle"
;;
esac
A couple of things worth noting in _smartthings_cmd: it tries the asdf-managed binary path first, then falls back to whatever smartthings is on $PATH. This means the script works whether you're using asdf or a global npm install.
Step 6: Wire Up the Aliases
Create ~/dotfiles/zsh/aliases/monitor.sh:
# ── Samsung M8 Monitor Input (SmartThings) ──────────────────────────────────
if command -v smartthings &>/dev/null; then
source "$HOME/dotfiles/scripts/monitor_input.sh" 2>/dev/null
alias hdmi1='monitor_hdmi1'
alias hdmi2='monitor_hdmi2'
alias hdmi-toggle='monitor_toggle'
alias t='monitor_toggle'
fi
Source it from your .zshrc:
source "$HOME/dotfiles/zsh/aliases/monitor.sh"
The command -v smartthings guard means the aliases are silently skipped on any machine that doesn't have the CLI installed — no errors, no noise.
Usage
hdmi1 # switch to HDMI 1 (machine A)
hdmi2 # switch to HDMI 2 (machine B)
hdmi-toggle # toggle between whichever is active
t # same as hdmi-toggle, just shorter
Run it directly without sourcing:
~/dotfiles/scripts/monitor_input.sh toggle
~/dotfiles/scripts/monitor_input.sh hdmi1
Workflow in Practice
My setup: work MacBook on HDMI 1, personal Linux desktop on HDMI 2. A single t in the terminal and the monitor switches — no remote, no OSD, no context switch. Since it goes through SmartThings rather than DDC/CI, it works over the network too, so you don't even need to be in the same session as the machine you're switching away from.
Troubleshooting
smartthings CLI not found — Make sure the npm global bin is on your $PATH. Check with npm bin -g and add it to your shell profile if missing.
SMARTTHINGS_MONITOR_ID is not set — Add the export to ~/.zshrc.local (not your dotfiles repo) and re-source your shell.
Could not read current input source — Run smartthings devices:status $SMARTTHINGS_MONITOR_ID manually to inspect the raw JSON. The capability key may differ slightly on older M8 firmware; look for mediaInputSource in the output.
Commands time out — The M8 needs to be on and connected to your Wi-Fi network. Wake it from standby first, or disable deep sleep in the monitor's power settings.
That's it. SmartThings CLI, one script, four aliases, zero remote-reaching.
Full script and aliases live in my dotfiles: github.com/abhsss96/dotfiles — see scripts/monitor_input.sh and zsh/aliases/monitor.sh.
Top comments (0)