I try to execute shell script using Keyboard Maestro. In macOS Terminal and Raspberry everything works good. KM shows a strange error. Looks like the script works but poorly recognizes characters or something. Password saved in sha1 is correct.

KM with error:

Terminal with correct result on this same device:

Script (works on every device):

# ------------------------------------------------------------------------------------------
# This script mimics the usage of the Home Wizard Lite app
# ------------------------------------------------------------------------------------------
# Dependencies: curl and jq (sudo apt-get install curl jq)
# It needs three parameters:
# - the SmartSwitch you want to control, between quotes (exactly as named in the Home Wizard Lite app)
# - the device you want to control, between quotes (exactly as named in the Home Wizard Lite app)
# - the action you want to perform, between quotes
# Depending on the device you control, one of the following actions may apply:
actionlist="On, Off, Up, Down, Left, Right, Stop, Favorite, Pair, ManualMode, AutomaticMode, DayMode, NightMode, GetState, Range, Open, Close"
# The fourth parameter is optional and indicates the time (in seconds) that the script will keep trying to perform the action.
# Example call: ./send_homewizard.sh "SmartSwitch1" "Controller1" "On" 60
# ------------------------------------------------------------------------------------------
# You have to fill in your HomeWizard Lite username and the sha1-hash of your password between the quotes:
password_sha1="4bg7j41b3785d06465b507790z09drge96414386" #can be generated on https://hash.online-convert.com/sha1-generator
# ------------------------------------------------------------------------------------------

# Checking the parameters
# -----------------------------------
searchswitch=$1 # e.g. SmartSwitch1
if [ "$searchswitch" = "" ]; then echo -e "Missing parameter SmartSwitch ...\nExiting ..."; exit; fi
searchdevice=$2 # e.g. Controller1
if [ "$searchdevice" = "" ]; then echo -e "Missing parameter Device ...\nExiting ..."; exit; fi
doaction=$3 # On, Off, or one of the other applicable actions
if [ "$doaction" = "" ]; then echo -e "Missing parameter Action ...\nExiting ..."; exit; fi
if [[ ! ", $actionlist, " = *", $doaction, "* ]]; then echo -e "Action not in list {$actionlist}\nExiting ..."; exit; fi
timeout=$4 # in seconds (default 10)
if ! [[ "$timeout" =~ ^[0-9]+$ ]]; then timeout=10; fi
echo "Sending {"$searchswitch", "$searchdevice", "$doaction"} during max. "$timeout" seconds ..."

# Login to HomeWizard cloud
# -----------------------------------
login=$(curl -sS -u $username:$password_sha1 "https://cloud.homewizard.com/account/login")
#echo $login
if [[ ! "$(echo $login | jq -r '.status')" = "ok" ]]; then
   echo -e "Login failed ... Did you enter correctly your username and password_sha1 in the script?\nExiting ..."
sessionid=$(echo $login | jq -r '.session')
#echo $sessionid

# Determining the plugid and deviceid
# -----------------------------------
alljson=$(curl -sS -H "X-Session-Token: $sessionid" "https://plug.homewizard.com/plugs")
#echo $alljson
plugid=$(echo $alljson | jq --arg ss $searchswitch -r 'select(.[].name==$ss) | .[].id')
#echo $plugid
if [ "$plugid" = "" ]; then
   echo -e "$searchswitch not found ... Is the name exactly as in the app?\nExiting ..."
devices=$(echo $alljson | jq --arg ss $searchswitch 'select(.[].name==$ss) | .[].devices')
#echo $devices
deviceid=$(echo $devices | jq --arg sd $searchdevice -r '.[] | select(.name==$sd) | .id')
#echo $deviceid
if [ "$deviceid" = "" ]; then
   echo -e "$searchdevice not found ... Is the name exactly as in the app?\nExiting ..."

# Sending the action
# -----------------------------------
#echo $startsec
#echo $endsec
while [ $SECONDS -lt $endsec ] ; do
      status=$(curl -sS -H "X-Session-Token: $sessionid" -H "Content-Type: application/json; charset=utf-8" -X POST -d '{"action": "'$doaction'"}' 'https://plug.homewizard.com/plugs/'$plugid'/devices/'$deviceid'/action')
      echo $status
      if [ "$status" = "{\"status\":\"Success\"}" ]; then
  • 1
    Can you change the script to show the full value of $login after the first call to curl, and add that to the question? Basically "remove the # before echo $login, rerun and update the output you get from Keyboard Maestro". – nohillside Jan 27 at 10:24
  • 4
    Have you tried a Minimal, Complete, and Verifiable example? Can you simplify the script to narrow down exactly what lines are causing the issue? This is a very long script with all sorts of other content. – grg Jan 27 at 10:24
  • Scripts in the terminal have the advantage of whatever was done in your profile. I doubt those run from Keyboard Maestro do. Create a new user. Try running the scripts from there. add in debug commands to your script pwd >>mylog.txt; id >>mylog.txt – historystamp Jan 27 at 20:34
  • touch /Users/youruserid/mylog3.txt;date >>/Users/youruserid/mylog3.txt;pwd >>/Users/youruserid/mylog3.txt; id >>/Users/youruserid/mylog3.txt;# notice I added the full path. added touch so I could always append. – historystamp Jan 27 at 20:42
  • see also shellcheck.net as you have unsafe forms such as $username:$password_sha1 that really should be quoted to prevent POSIX shells from doing stupid things with it – thrig Jan 28 at 1:41

Given that the issue is somewhere in here:

[[ ! "$(echo $login | jq -r '.status')" = "ok" ]]

I'd guess that jq isn't in the path of the environment that KM is running with.

Try to use the full path.

The docs for KM back me up here:

Path in Shell Scripts
In essence, the default path in a Keyboard Maestro Execute Shell Script is the base path for the system:

Change jq into a full path, see what happens. If you don't know where jq is installed, then do:

which jq

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .