Omahub
← All plugins
A

SmartThings AC

by artur-hash

Control an air conditioner from the bar through the SmartThings API. Authenticates through the SmartThings CLI, whose session renews itself.

Security review

Review recommended · 10 findings

Deterministic scan — not a security guarantee

Medium
Risk level
Medium
Analyzed commit
190915c
Scanned
1 month ago
  • medium package_manager …/workflows/ci.yml:9

    System package manager operation.

    apt-get install -y jq curl libsecret-tools
  • medium package_manager scripts/setup.sh:50

    Global npm package installation.

    npm install -g @smartthings/cli${RESET}"
  • medium package_manager scripts/setup.sh:53

    Global npm package installation.

    npm install -g @smartthings/cli || fail "npm install failed. If it was a permissions error, set a user prefix (npm config set prefix ~/.local) and try again"
  • medium package_manager bin/smartac:426

    Global npm package installation.

    npm install -g @smartthings/cli\n'
  • medium package_manager bin/smartac:432

    Global npm package installation.

    npm install -g @smartthings/cli && smartthings locations\n'
  • Command runs with sudo, elevating the process beyond the plugin environment.

    sudo apt-get install -y jq curl libsecret-tools
  • System package manager operation.

    apt-get install -y jq curl libsecret-tools
  • Docs package_manager README.md:45

    Global npm package installation.

    npm install -g @smartthings/cli`
  • Docs package_manager README.md:69

    Global npm package installation.

    npm install -g @smartthings/cli
  • Command runs with sudo, elevating the process beyond the plugin environment.

    sudo apt-get install -y jq curl libsecret-tools

Automated analysis only — not a security guarantee.

AI advisory review

No obvious issues detected

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

Low
AI risk level
Low
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
190915c
Reviewed
1 month ago

The plugin is a well-documented bar widget that controls a SmartThings air conditioner via a bash backend. The deterministic scan flagged package-manager operations (apt-get, npm install -g) and sudo, but those appear only in documentation, CI, and the user-run setup script (which asks for consent before installing the CLI). The plugin itself never elevates privileges, runs nothing at install time, and handles credentials carefully (reads the SmartThings CLI session, never stores its own token). No obfuscation, persistence, or destructive behavior was found.

  • The setup script performs a global npm install of @smartthings/cli, but only after explicit user confirmation and with clear messaging.
  • The plugin reads the SmartThings CLI's credentials file from the user's home directory; this is a standard pattern but means the plugin has access to that session token.
  • The deterministic scan's medium findings are based on documentation and CI snippets, not on the plugin's runtime code.
How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/artur-hash/omarchy-smartac --enable
Hardware #bar #quickshell #system

SmartThings AC

<p align="center"> <img src="preview.png" alt="The SmartThings AC panel, expanded" width="360"> </p>

Control an air conditioner from the Omarchy bar: power, target temperature, mode, fan speed, swing and presets. The bar shows the room temperature whether or not the unit is running, and the panel adds humidity and a feels-like figure.

Built against a Samsung WindFree, but nothing in it is Samsung-specific. Every control is built from the capability list the device itself publishes, so a unit offering different modes shows different buttons with no code change, and the temperature range comes from the device rather than a constant.

What it does not do

Scheduling, and more than one unit at a time. Both are possible; neither is here yet.

Air quality is deliberately absent. The capability exists on the unit this was built against, but both of its dust sensors report null, so there would be nothing to show.

There is no local control. Newer Samsung units answer only through Samsung's cloud — the local protocol older models spoke on port 2878 is gone — so this plugin talks to SmartThings and needs the internet to do anything.

Upgrading from 1.x

A pasted personal access token no longer works. SmartThings expires one 24 hours after it is created, which made the plugin ask for a new credential every morning, so that path was removed rather than kept as a fallback nobody should choose. Run the setup script once and the plugin authenticates through the SmartThings CLI instead, whose session renews itself.

Any token 1.x stored in your keyring is now unused; the plugin no longer reads or writes there at all. secret-tool clear service smartac key token removes it if you want it gone.

Requirements

  • Omarchy 4 (Quattro)
  • curl and jq — present on a default install
  • Node, for the SmartThings CLI: npm install -g @smartthings/cli

Install

omarchy plugin add https://github.com/artur-hash/omarchy-smartac.git --enable

Setup

~/.config/omarchy/plugins/io.github.artur-hash.smartac/scripts/setup.sh

It checks for node, installs the SmartThings CLI after asking, opens a browser to log in, and finishes by running this plugin's own doctor so you know it worked before you go looking at the bar. then pick your air conditioner in the panel.

Omarchy never executes plugin code at install time, which is the right call, so nothing here runs on its own — you run this once.

By hand, if you prefer:

npm install -g @smartthings/cli
smartthings locations

The panel also has a Log in button once the CLI is installed, which does the same thing as that second command.

Install the CLI globally, not through npx. This plugin stores no credential of its own and never touches the keyring — it reads the session the CLI keeps, the way other tools read gcloud's or gh's, and that session renews itself. But the CLI only renews it when one of its own commands runs, so the plugin has to be able to find it. PATH is not enough on its own — the shell takes its environment from the session, not from your terminal's rc — so it also looks where npm, mise, nvm, volta and asdf put things. If it cannot find the binary anywhere, the panel and doctor both say so rather than letting the session work for a day and then quietly stop renewing.

Why there is no token to paste

SmartThings expires a personal access token 24 hours after it is created. Tokens issued before 30 December 2024 could last fifty years; new ones cannot. A bar widget that asks for a fresh credential every morning is not one anybody keeps, so that path was removed rather than kept as a fallback nobody should choose.

The remaining route — registering an OAuth app — is closed to anyone whose home was set up by someone else and shared with them: authorising an app means installing it into a location you own, and a shared member owns none. Their devices read and control perfectly; only app authorisation is refused. The CLI sidesteps it because its own client installs with no location.

When a setting does not take

Some units silently ignore a command that does not apply to their current state. The cloud still answers COMPLETED — the device simply drops it. The panel reads the state back a few seconds after every write and says so when the value did not change, rather than showing a button that quietly springs back.

Observed on a Samsung AR12BSEAAWKNAZ:

  • WindFree only engages in cool. In auto or heat the preset is accepted and discarded.
  • The setpoint cannot be changed while the unit is off.
  • Each mode keeps its own setpoint, so the temperature shown changes on its own when the mode does. That is the device remembering, not a misread.
  • Choosing a mode turns the unit on. Sending a mode to a unit that is off powers it up rather than storing the setting for later.

The cloud reflects a change about three seconds after the command returns -- measured on this unit, absent at 1.4s and present by 3.2s -- so the panel confirms in roughly that time rather than the instant the write succeeds.

None of these rules are hardcoded. Other hardware has other constraints, and a list written here would go stale the first time a firmware update moved one.

What the backend trusts

Nothing the network says, beyond its shape.

omarchy-shell is one long-lived process shared by every widget, and the QML side collects this helper's whole stdout. A response with no ceiling on it is therefore a way for whatever answers on the other end of the socket to exhaust the shell, not just this plugin. So the ceiling is enforced while the response is arriving rather than after it has been read: head closes the pipe once it has taken its fill and curl dies of SIGPIPE, and an overflow fails closed — a truncated body is never parsed, guessed at, or passed on.

Past that, every value forwarded to the panel is clamped: strings to 128 characters, supported-value lists to 64 entries, the device picker to 200 rows. A real payload is orders of magnitude under all of these. They exist so the cost of a hostile or broken response stays bounded, not to be tight.

Diagnostics

bin/smartac doctor
bin/smartac doctor --capabilities --device <id>

The second prints the raw capability list your device reports, which is the quickest way to find out why a control is missing.

Removal

omarchy plugin remove io.github.artur-hash.smartac

Nothing is left behind but the keyring entry, which token clear removes. There is no systemd unit and no file outside the plugin directory.

License

MIT.