DEV Community

Cover image for Switch Your Samsung M8 Monitor HDMI Inputs from the Terminal (No Remote Needed)
Abhishek Sharma
Abhishek Sharma

Posted on

Switch Your Samsung M8 Monitor HDMI Inputs from the Terminal (No Remote Needed)

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 asdf for 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Then install Node.js:

asdf plugin add nodejs
asdf install nodejs 24.13.0
asdf global nodejs 24.13.0
Enter fullscreen mode Exit fullscreen mode

Verify:

node --version   # v24.13.0
Enter fullscreen mode Exit fullscreen mode

Step 2: Install the SmartThings CLI

npm install -g @smartthings/cli
Enter fullscreen mode Exit fullscreen mode

Verify:

smartthings --version
Enter fullscreen mode Exit fullscreen mode

Step 3: Authenticate with SmartThings

smartthings devices
Enter fullscreen mode Exit fullscreen mode

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 │
└────┴─────────────────┴──────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Source it from your .zshrc:

source "$HOME/dotfiles/zsh/aliases/monitor.sh"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Run it directly without sourcing:

~/dotfiles/scripts/monitor_input.sh toggle
~/dotfiles/scripts/monitor_input.sh hdmi1
Enter fullscreen mode Exit fullscreen mode

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)