chopstick
All widgets

Caffeinate

Comes with Chopstick

Keeps the Mac and its display from sleeping for a while (45m, 2h) or until you stop it, showing the time left on the island.

Already installed? It's in your widget library.

Type it in the notch's search

  • Keep awake for length
  • Keep awake until I stop it
  • Stop keeping awake

What it runs

A widget is a folder of plain files. Here is all of its code.

widget.json
{
  "id": "caffeinate",
  "name": "Caffeinate",
  "icon": "icon.png",
  "description": "Keeps the Mac and its display from sleeping for a while (45m, 2h) or until you stop it, showing the time left on the island.",
  "initial": "running",
  "opens_at": "pick",
  "show_when": {
    "awake.on": true
  },
  "watch": [
    {
      "script": "state.sh",
      "every": 30,
      "on": [
        "file:state"
      ],
      "as": "awake"
    }
  ],
  "commands": {
    "start": {
      "description": "Keep the Mac awake for a while.",
      "phrase": "Keep awake for {length}",
      "inputs": {
        "length": {
          "type": "duration",
          "description": "How long: 45m, 2h, 1h30, or a number of minutes"
        }
      },
      "do": [
        {
          "set": {
            "seconds": "{{input.length.seconds}}",
            "error": ""
          }
        },
        {
          "run": "start.sh",
          "then": "running",
          "else": "pick"
        },
        {
          "refresh": "awake"
        }
      ]
    },
    "forever": {
      "description": "Keep the Mac awake until told to stop.",
      "phrase": "Keep awake until I stop it",
      "do": [
        {
          "set": {
            "seconds": "",
            "error": ""
          }
        },
        {
          "run": "start.sh",
          "then": "running",
          "else": "pick"
        },
        {
          "refresh": "awake"
        }
      ]
    },
    "stop": {
      "description": "Let the Mac sleep again.",
      "phrase": "Stop keeping awake",
      "do": [
        {
          "run": "stop.sh"
        },
        {
          "refresh": "awake"
        },
        "dismiss"
      ]
    }
  },
  "states": {
    "pick": {
      "open": true,
      "on_enter": [
        {
          "run": "running.sh",
          "then": "running"
        }
      ],
      "compact": {
        "leading": {
          "symbol": "cup.and.saucer.fill",
          "tint": "yellow"
        }
      },
      "expanded": {
        "size": "compact",
        "header": {
          "symbol": "cup.and.saucer.fill",
          "tint": "yellow",
          "title": "Caffeinate"
        },
        "blocks": [
          {
            "row": [
              {
                "button": {
                  "label": "30 min",
                  "do": [
                    {
                      "set": {
                        "seconds": "1800",
                        "error": ""
                      }
                    },
                    {
                      "run": "start.sh",
                      "then": "running",
                      "else": "pick"
                    },
                    {
                      "refresh": "awake"
                    }
                  ]
                }
              },
              {
                "button": {
                  "label": "1 h",
                  "do": [
                    {
                      "set": {
                        "seconds": "3600",
                        "error": ""
                      }
                    },
                    {
                      "run": "start.sh",
                      "then": "running",
                      "else": "pick"
                    },
                    {
                      "refresh": "awake"
                    }
                  ]
                }
              },
              {
                "button": {
                  "label": "2 h",
                  "do": [
                    {
                      "set": {
                        "seconds": "7200",
                        "error": ""
                      }
                    },
                    {
                      "run": "start.sh",
                      "then": "running",
                      "else": "pick"
                    },
                    {
                      "refresh": "awake"
                    }
                  ]
                }
              },
              {
                "button": {
                  "label": "Until I stop",
                  "do": [
                    {
                      "set": {
                        "seconds": "",
                        "error": ""
                      }
                    },
                    {
                      "run": "start.sh",
                      "then": "running",
                      "else": "pick"
                    },
                    {
                      "refresh": "awake"
                    }
                  ]
                }
              }
            ],
            "spacing": "tight"
          },
          {
            "input": {
              "placeholder": "How long? 45m, 3h",
              "do": [
                {
                  "command": "start",
                  "with": {
                    "length": "{{item.text}}"
                  }
                }
              ]
            }
          },
          {
            "note": "{{error}}"
          }
        ]
      }
    },
    "running": {
      "compact": {
        "leading": {
          "symbol": "cup.and.saucer.fill",
          "tint": "yellow"
        },
        "trailing": {
          "text": "{{awake.label | On}}"
        }
      },
      "expanded": {
        "size": "compact",
        "header": {
          "symbol": "cup.and.saucer.fill",
          "tint": "yellow",
          "title": "Keeping your Mac awake"
        },
        "blocks": [
          {
            "text": "{{awake.until}}",
            "style": "body"
          },
          {
            "button": {
              "label": "Stop",
              "do": [
                {
                  "run": "stop.sh"
                },
                {
                  "refresh": "awake"
                },
                "dismiss"
              ]
            }
          }
        ]
      }
    }
  },
  "preview": {
    "states": [
      "pick",
      "running"
    ],
    "data": {
      "awake": {
        "on": true,
        "label": "1:25",
        "until": "Until 18:40"
      }
    }
  }
}
running.sh
#!/bin/sh
# Succeeds while start.sh's caffeinate runs: opened then, the widget shows it instead of the lengths.
F="$CHOPSTICK_STORAGE/state"
[ -f "$F" ] && read -r PID END < "$F" && [ "$(ps -o comm= -p "$PID" 2>/dev/null)" = "caffeinate" ]
start.sh
#!/bin/sh
# Keeps the Mac and its display awake with `caffeinate`, for $CHOPSTICK_SECONDS or, without it,
# until stopped. caffeinate also ends when Chopstick quits (-w), so nothing is left keeping the
# Mac up. $CHOPSTICK_STORAGE/state holds "<pid> <end, 0 for until stopped>".
F="$CHOPSTICK_STORAGE/state"
SECS=$(printf '%.0f' "${CHOPSTICK_SECONDS:-0}" 2>/dev/null) || SECS=0
sh stop.sh >/dev/null
if [ "$SECS" -gt 0 ]; then
  caffeinate -di -t "$SECS" -w "$PPID" </dev/null >/dev/null 2>&1 &
  END=$(( $(date +%s) + SECS ))
else
  caffeinate -di -w "$PPID" </dev/null >/dev/null 2>&1 &
  END=0
fi
echo "$! $END" > "$F"
echo '{"ok":true}'
state.sh
#!/bin/sh
# {"on": true, "label": "1:25", "until": "Until 17:40"} while start.sh's caffeinate runs.
F="$CHOPSTICK_STORAGE/state"
OFF='{"on":false,"label":"","until":""}'
[ -f "$F" ] || { echo "$OFF"; exit 0; }
read -r PID END < "$F"
[ "$(ps -o comm= -p "$PID" 2>/dev/null)" = "caffeinate" ] || { rm -f "$F"; echo "$OFF"; exit 0; }
if [ "$END" -eq 0 ]; then
  echo '{"on":true,"label":"On","until":"Until you stop it"}'
  exit 0
fi
LEFT=$(( END - $(date +%s) )); [ "$LEFT" -lt 0 ] && LEFT=0
M=$(( (LEFT + 59) / 60 ))
if [ "$M" -ge 60 ]; then LABEL=$(printf '%d:%02d' $((M / 60)) $((M % 60))); else LABEL="${M}m"; fi
printf '{"on":true,"label":"%s","until":"Until %s"}\n' "$LABEL" "$(date -r "$END" +%H:%M)"
stop.sh
#!/bin/sh
# Ends the caffeinate start.sh began, if it's still the one running.
F="$CHOPSTICK_STORAGE/state"
[ -f "$F" ] || { echo '{"ok":true}'; exit 0; }
read -r PID END < "$F"
[ "$(ps -o comm= -p "$PID" 2>/dev/null)" = "caffeinate" ] && kill "$PID"
rm -f "$F"
echo '{"ok":true}'