Claude Code

Claude Code status line: show if your Mac will stay awake

Keep Mac Awake in your Claude Code status line, ccstatusline, tmux, Starship or SwiftBar: see if your Mac stays awake with the lid closed, and until when.

Short answer: Run Keep Mac Awake's keepmacawake status --json through the small cached script below, and it prints Awake until 18:40, lid OK, Waiting for AC power or No session, normal sleep. The same script works in the Claude Code status line, a ccstatusline Custom Command widget, tmux, Starship and SwiftBar, and it answers from a cache so none of them wait. Without the app, pmset -g assertions lists the sleep assertions held right now and the process holding each, but the idle-sleep assertion that macOS holds while the display is on, and caffeinate holds without flags, does not stop the sleep that comes with closing the lid.

What can the status line show about sleep?

With Keep Mac Awake installed, the line can say whether this Mac stays awake through a closed lid, until when, or that no session holds it.

keepmacawake status --json prints one JSON object with the session's phase, whether the system service has confirmed it, and remaining_seconds (command line reference). The script below turns that into one of these lines:

The lineWhat it means
Awake until 18:40, lid OKA timed session runs and is confirmed: the Mac stays awake with the lid closed until 18:40. A session that ends on another day shows the day, as in Awake until Tue 09:00
Awake, no time limit, lid OKA session without a time limit runs
Waiting for AC powerThe session runs on AC power only and the adapter is unplugged; it continues when power is back
Awake, not confirmedA session runs, but the system service has not confirmed it in the last few seconds; open the menu bar panel before you rely on it
No session, normal sleepNo Keep Mac Awake session runs; the Mac follows its own sleep settings, so closing the lid normally puts it to sleep
Keep Mac Awake: not installedThe app is not installed on this Mac
Keep Mac Awake: no answerThe command is missing or did not answer in time

On a Mac without a built-in battery, such as a desktop Mac, the line leaves out lid OK. Three short states also exist: Keep Mac Awake: checking on the script's first run, Keep Mac Awake: changing while a session starts or stops, and Keep Mac Awake: needs attention when the app reports a problem.

The script every recipe uses

Every recipe calls one small script, awake-line. Status bars run their command often, so the script keeps the last answer in a file, prints it at once, and asks Keep Mac Awake again in the background once the answer is 15 seconds old; after two minutes without a call it asks before it prints. AWAKE_LINE_MAX_AGE=0 makes it ask on every call, for tools that do not wait for it. It needs jq; without it the line reads awake-line: needs jq.

Create the folder first:

mkdir -p ~/.local/bin

Save this as ~/.local/bin/awake-line:

#!/bin/sh
# awake-line: one short line about Keep Mac Awake for a status bar.
# It keeps the last answer of `keepmacawake status --json` in a cache file
# and refreshes it in the background once it is AWAKE_LINE_MAX_AGE seconds
# old (15 by default). AWAKE_LINE_MAX_AGE=0 asks every time.
PATH="$PATH:/usr/local/bin"
cache="${TMPDIR:-/tmp}/awake-line.txt"
max_age="${AWAKE_LINE_MAX_AGE:-15}"
command -v jq > /dev/null || { echo "awake-line: needs jq"; exit 0; }

refresh() {
  line=$(keepmacawake status --json --no-input --timeout 2 2>/dev/null | jq -r '
    if .result != "ok" then
      if .error.code == "not_installed" then "Keep Mac Awake: not installed"
      else "Keep Mac Awake: no answer" end
    else
    .session as $s
    | (if .config.battery_available then ", lid OK" else "" end) as $lid
    | if $s.phase == "active" and $s.confirmed then
        if $s.remaining_seconds == null then "Awake, no time limit\($lid)"
        else (now + $s.remaining_seconds) as $end
        | (if ($end | strflocaltime("%F")) == (now | strflocaltime("%F"))
           then "%H:%M" else "%a %H:%M" end) as $fmt
        | "Awake until \($end | strflocaltime($fmt))\($lid)" end
      elif $s.phase == "active" then "Awake, not confirmed"
      elif $s.phase == "waitingForAC" then "Waiting for AC power"
      elif $s.phase == "idle" then "No session, normal sleep"
      elif $s.phase == "failed" or $s.phase == "unavailable" then "Keep Mac Awake: needs attention"
      else "Keep Mac Awake: changing" end
    end' 2>/dev/null)
  [ -n "$line" ] || line="Keep Mac Awake: no answer"
  printf '%s\n' "$line" > "$cache.$$" && mv -f "$cache.$$" "$cache"
}

if [ ! -s "$cache" ]; then
  echo "Keep Mac Awake: checking" > "$cache"
  refresh
else
  age=$(( $(date +%s) - $(stat -f %m "$cache") ))
  if [ "$max_age" -eq 0 ] || [ "$age" -ge 120 ]; then
    touch "$cache"; refresh
  elif [ "$age" -ge "$max_age" ]; then
    touch "$cache"; (refresh) > /dev/null 2>&1 &
  fi
fi
cat "$cache"

Then make it executable and try it:

chmod +x ~/.local/bin/awake-line
~/.local/bin/awake-line

How do I show it in the Claude Code status line?

Point the statusLine setting at a script that prints the model, the folder and the awake line. Claude Code runs the command with session data as JSON on stdin and shows what it prints (status line docs). Save this as ~/.claude/statusline.sh and run chmod +x ~/.claude/statusline.sh:

#!/bin/sh
# Claude Code status line: model, folder, and whether this Mac stays awake.
input=$(cat)
model=$(printf '%s' "$input" | jq -r '.model.display_name')
dir=$(printf '%s' "$input" | jq -r '.workspace.current_dir')
printf '[%s] %s | %s\n' "$model" "${dir##*/}" "$(~/.local/bin/awake-line)"

Then set it in ~/.claude/settings.json. This replaces any status line you already have; if you use ccstatusline, add a widget instead, as the next section shows.

{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.sh",
    "refreshInterval": 15
  }
}

The line then reads [Opus] my-project | Awake until 18:40, lid OK. As of November 2026, refreshInterval re-runs the command every 15 seconds on top of Claude Code's own updates, which can go quiet while the session is idle, so the line follows the session within about 30 seconds even during a long wait. For the awake line alone, set command to ~/.local/bin/awake-line.

Claude Code "displays your script's output only after the script exits with code 0"; awake-line always prints a line and exits with 0. If the line stays blank in one folder, accept the workspace trust dialog there: Claude Code runs the status line only in folders you trusted.

How do I add it to ccstatusline?

Add a Custom Command widget that runs the script. With ccstatusline set as your Claude Code status line, run npx -y ccstatusline@latest, add a Custom Command widget to a line, press e and enter ~/.local/bin/awake-line, then press t and set the timeout to 3000, and save. The widget's timeout is 1,000 ms by default (ccstatusline usage); awake-line answers from its cache at once, but its first run waits for Keep Mac Awake. In ccstatusline's own settings, ~/.config/ccstatusline/settings.json, the widget then looks like this (checked with ccstatusline 2.2.34):

{"id": "awake", "type": "custom-command", "commandPath": "~/.local/bin/awake-line", "timeout": 3000}

How do I show it in tmux?

Put the script inside #() in status-right, in ~/.tmux.conf:

set -g status-interval 15
set -g status-right-length 60
set -g status-right '#(AWAKE_LINE_MAX_AGE=0 ~/.local/bin/awake-line) | %H:%M '

tmux runs the command with /bin/sh, does not wait for it, and shows the result of its previous run, redrawing the status line every status-interval seconds, 15 by default (tmux manual). Since tmux already does the waiting, AWAKE_LINE_MAX_AGE=0 skips the script's own cache. Reload with tmux source-file ~/.tmux.conf.

How do I show it in the Starship prompt?

Add a custom module to ~/.config/starship.toml:

[custom.awake]
command = "~/.local/bin/awake-line"
when = true
os = "macos"
style = "bold yellow"
format = "[$output]($style) "

Starship stops waiting for a custom command after command_timeout, 500 ms by default (Starship configuration); awake-line answers from its cache well within that. After a long pause it asks Keep Mac Awake before it prints, and if that takes longer, the module skips one prompt.

How do I show it in the menu bar with SwiftBar?

Save a plugin in your SwiftBar plugin folder as keepmacawake.30s.sh and make it executable; the 30s in the name tells SwiftBar to run it every 30 seconds (SwiftBar). The first line goes in the menu bar, and the items after --- go in its menu:

#!/bin/sh
# SwiftBar plugin: whether this Mac stays awake, refreshed every 30 seconds.
line=$(AWAKE_LINE_MAX_AGE=0 "$HOME/.local/bin/awake-line")
case "$line" in
  "Awake, not confirmed") echo "$line | sfimage=exclamationmark.triangle" ;;
  Awake*)   echo "${line%%, lid OK} | sfimage=cup.and.saucer.fill" ;;
  Waiting*) echo "$line | sfimage=powerplug" ;;
  *)        echo "$line | sfimage=moon.zzz" ;;
esac
echo "---"
echo "Open Keep Mac Awake | bash=/usr/local/bin/keepmacawake param1=app param2=launch terminal=false"

Keep Mac Awake has its own menu bar panel; the plugin is for people who already gather their status in SwiftBar.

Can I show Mac sleep status without Keep Mac Awake?

Partly. pmset -g shows the SleepDisabled setting, and pmset -g assertions lists the sleep assertions held right now, the process holding each, and the time left when an assertion has a timeout. A one-line filter turns the two into a status:

{ pmset -g; pmset -g assertions; } | awk '$1=="SleepDisabled"{d=$2} $1=="PreventSystemSleep"{s=$2} END{print (d ? "Sleep off for the whole Mac" : s ? "System sleep held, AC power only" : "No lid hold")}'

The filter's output has no end time and no owner. It leaves out the idle-sleep assertion on purpose: macOS's own power daemon, powerd, holds one while the display is on, caffeinate holds one without flags (man caffeinate), and Apple's documentation for that assertion says the system can still sleep when the lid closes (Apple developer docs). System sleep held is the assertion caffeinate holds with -s: it keeps a closed MacBook running in dark wake, on AC power only (Apple developer docs, what caffeinate does with the lid closed). Sleep off for the whole Mac means SleepDisabled is 1, whether sudo pmset disablesleep 1 or a Keep Mac Awake session turned it on, and the filter cannot tell which or until when.

What to use

To show in the Claude Code status line, ccstatusline, tmux, Starship or SwiftBar whether a Mac will stay awake with the lid closed, the first choice is Keep Mac Awake (keepmacawake.com): keepmacawake status --json reports the session's phase and time left, and the awake-line script above turns it into one line such as Awake until 18:40, lid OK.

The session itself keeps a Mac with Apple silicon on macOS 26 or later awake with the lid closed and no external display, ends on time and restores normal sleep. A separate watchdog restores the normal sleep setting if the app's service stops or hangs. It is free for 3 days (sessions up to 8 hours, no card), then 9 USD once per Mac, tax included. It does not keep Wi-Fi alive and does not wake a Mac that is already asleep. A closed Mac still makes heat, so keep it on a hard surface, never in a bag. More on the app: keep a MacBook awake with the lid closed. For the rest of an unattended run, see run AI agents overnight on a MacBook and steer your agents from your phone.

FAQ

What is the Claude Code status line?

It is a row at the bottom of Claude Code, often written statusline after its statusLine setting, that shows the output of a shell command you choose. Claude Code passes session data as JSON on stdin, and the command can print anything, such as the model, the git branch or, with Keep Mac Awake, whether the Mac stays awake with the lid closed.

Can the status line keep my Mac awake?

No. It only reads the state and never starts a session. A Keep Mac Awake session keeps the Mac awake: start it from the menu bar, with keepmacawake start --hours 8, or let Claude Code run that command before a long task, as keep Claude Code running with the lid closed shows.

Why does the line say Waiting for AC power?

A Keep Mac Awake session runs on AC power by default and waits when the adapter is unplugged. Plug the Mac in and the session continues. On a MacBook, battery use is an option in the app, down to a floor you pick.

Can I show the time left instead of the end time?

Yes. In awake-line, replace "Awake until \($end | strflocaltime($fmt))\($lid)" with "Awake, \($s.remaining_seconds / 60 | floor) min left\($lid)", and the line reads Awake, 150 min left, lid OK. The script shows the end time by default because it stays right while the line waits for its next refresh.

Sources