diff --git a/README.md b/README.md
index 142546c..b6c253d 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,6 @@ This is where I tweak config files till 4am like a goblin. It's pretty cozy in h
- **[pi](https://github.com/badlogic/pi-mono)**
- **[wezterm](https://wezterm.org/index.html)**
- **[stow](https://www.gnu.org/software/stow/)**
-- **[SwiftBar](https://github.com/swiftbar/SwiftBar)**
- **[Tinycast](https://github.com/abue-ammar/tinycast)**
- **[yazi](https://yazi-rs.github.io/)**
diff --git a/fish/.config/fish/functions/latte.fish b/fish/.config/fish/functions/latte.fish
new file mode 100644
index 0000000..60ead69
--- /dev/null
+++ b/fish/.config/fish/functions/latte.fish
@@ -0,0 +1,128 @@
+# latte: friendlier `caffeinate` wrapper that takes hours or minutes instead
+# of seconds. Handy for keeping the Mac awake while long-running agents /
+# background jobs do their thing. `latte -a` stays awake only as long as
+# coding agents (claude, codex, pi) are running, then exits.
+function latte --description 'caffeinate with -h HOURS, -m MINUTES, or -a until coding agents finish'
+ argparse 'h/hours=' 'm/minutes=' 'a/agents' -- $argv
+ or return
+
+ set -l seconds
+ set -l label
+
+ function __latte_plural -S -a n word
+ if test "$n" = 1
+ echo "$n $word"
+ else
+ echo "$n "$word"s"
+ end
+ end
+
+ function __latte_brew -S -a msg
+ set_color -o magenta
+ echo -n "☕ latte"
+ set_color normal
+ echo " · $msg"
+ end
+
+ # Coding agents watched by -a/--agents. pi execs a node script, so its
+ # process name is `node` — match its command line instead. claude is
+ # lowercase so this won't match the Claude desktop app (capital C).
+ function __latte_agents_running -S
+ pgrep -qx claude; and echo claude
+ pgrep -qx codex; and echo codex
+ pgrep -qf pi-coding-agent; and echo pi
+ end
+
+ # Run caffeinate with the TTY in no-echo, non-canonical mode so stray
+ # keystrokes in the pane don't corrupt the display or leak into the next
+ # prompt. isig stays on so Ctrl-C still terminates caffeinate normally.
+ # Restored via a SIGINT handler so interrupts can't leave the TTY broken.
+ function __latte_run -S -a mode seconds
+ set -l tty_saved ""
+ set -l tty_active false
+ if isatty stdin
+ set tty_saved (stty -g 2>/dev/null)
+ if test -n "$tty_saved"
+ stty -echo -icanon 2>/dev/null
+ printf '\e[?25l'
+ set tty_active true
+ end
+ end
+ function __latte_restore_tty --inherit-variable tty_saved --inherit-variable tty_active
+ if test "$tty_active" = true
+ command -q python3; and python3 -c 'import termios,sys; termios.tcflush(sys.stdin, termios.TCIFLUSH)' 2>/dev/null
+ stty "$tty_saved" 2>/dev/null
+ printf '\e[?25h'
+ set tty_active false
+ end
+ functions -q __latte_sigint_handler; and functions -e __latte_sigint_handler
+ end
+ function __latte_sigint_handler --on-signal SIGINT
+ __latte_restore_tty
+ end
+ switch $mode
+ case timed
+ caffeinate -dimsu -t $seconds
+ case agents
+ # Poll for agents every 30s; caffeinate -t doubles as the
+ # sleep so the wake assertion is held between checks.
+ while test (count (__latte_agents_running)) -gt 0
+ caffeinate -dimsu -t 30
+ if test $status -gt 128
+ break
+ end
+ end
+ case '*'
+ caffeinate -dimsu
+ end
+ set -l rc $status
+ __latte_restore_tty
+ return $rc
+ end
+
+ set -l flag_count 0
+ set -q _flag_hours; and set flag_count (math $flag_count + 1)
+ set -q _flag_minutes; and set flag_count (math $flag_count + 1)
+ set -q _flag_agents; and set flag_count (math $flag_count + 1)
+ if test $flag_count -gt 1
+ set_color -o red
+ echo -n "☕ latte"
+ set_color normal
+ echo " · pick one: -h/--hours, -m/--minutes, or -a/--agents" >&2
+ return 1
+ end
+
+ if set -q _flag_agents
+ set -l running (__latte_agents_running)
+ if test (count $running) -eq 0
+ __latte_brew "no coding agents running — nothing to babysit"
+ return 0
+ end
+ __latte_brew "keeping macOS awake while agents run: "(string join ', ' $running)
+ __latte_run agents
+ set -l rc $status
+ __latte_brew "all agents done — macOS can nap now"
+ return $rc
+ else if set -q _flag_hours
+ set seconds (math -s0 "$_flag_hours * 3600")
+ or begin
+ __latte_brew "invalid hours: $_flag_hours" >&2
+ return 1
+ end
+ set label (__latte_plural $_flag_hours hour)
+ else if set -q _flag_minutes
+ set seconds (math -s0 "$_flag_minutes * 60")
+ or begin
+ __latte_brew "invalid minutes: $_flag_minutes" >&2
+ return 1
+ end
+ set label (__latte_plural $_flag_minutes minute)
+ else
+ __latte_brew "bottomless cup — keeping macOS awake until ctrl-c"
+ __latte_run forever
+ return
+ end
+
+ __latte_brew "keeping macOS awake for $label — sip slow"
+ __latte_run timed $seconds
+end
diff --git a/homebrew/Brewfile b/homebrew/Brewfile
index 74961c2..31ff798 100644
--- a/homebrew/Brewfile
+++ b/homebrew/Brewfile
@@ -44,7 +44,6 @@ if OS.mac?
cask "codex"
cask "handy"
cask "orbstack"
- cask "swiftbar"
cask "tamnd/tap/kage"
cask "tinycast"
cask "vlc"
diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh
index bedecf1..e3649ba 100644
--- a/scripts/bootstrap.sh
+++ b/scripts/bootstrap.sh
@@ -176,46 +176,6 @@ bootstrap_fish() {
ok 'Login shell changed to Fish (takes effect on next login)'
fi
}
-bootstrap_insomnia() {
- section 'SwiftBar / Insomnia'
- if [[ "$(uname -s)" != Darwin ]]; then warn 'SwiftBar skipped: macOS only'; return; fi
- ensure_brew
- if ! brew list --cask swiftbar >/dev/null 2>&1; then
- run 'Install SwiftBar' brew install --cask swiftbar
- else
- ok 'SwiftBar already installed'
- fi
- link_configs swiftbar
- local plugins domain plist reload=0
- plugins="$HOME/.config/swiftbar/plugins"
- domain="gui/$(id -u)"
- plist="$HOME/Library/LaunchAgents/com.wu-json.swiftbar-login.plist"
- need defaults 'Run this recipe on macOS.'
- need launchctl 'Run this recipe in a macOS desktop session.'
- if [[ "$(defaults read com.ameba.SwiftBar PluginDirectory 2>/dev/null || true)" != "$plugins" ]]; then
- run 'Set SwiftBar plugin directory' defaults write com.ameba.SwiftBar PluginDirectory -string "$plugins"
- reload=1
- else
- ok 'SwiftBar plugin directory already configured'
- fi
- if ! launchctl print "$domain" >/dev/null 2>&1; then
- warn 'SwiftBar launch skipped: no GUI session; rerun just bootstrap insomnia from the desktop'
- return
- fi
- if ! launchctl print "$domain/com.wu-json.swiftbar-login" >/dev/null 2>&1; then
- run 'Register SwiftBar login agent' launchctl bootstrap "$domain" "$plist"
- else
- ok 'SwiftBar login agent already registered'
- fi
- if [[ "$reload" == 1 ]] && pgrep -x SwiftBar >/dev/null 2>&1; then
- run 'Quit SwiftBar to apply its plugin directory' osascript -e 'tell application "SwiftBar" to quit'
- fi
- if ! pgrep -x SwiftBar >/dev/null 2>&1; then
- run 'Start SwiftBar' open -a SwiftBar
- else
- ok 'SwiftBar already running'
- fi
-}
bootstrap_tinycast() {
section 'Tinycast'
if [[ "$(uname -s)" != Darwin ]]; then warn 'Tinycast skipped: macOS only'; return; fi
@@ -292,11 +252,11 @@ bootstrap_tailscale() {
require_tool just just
case "${1:-all}" in
- all) bootstrap_brew; bootstrap_stow; bootstrap_gh; bootstrap_pi; bootstrap_fish; bootstrap_insomnia; bootstrap_tinycast ;;
+ all) bootstrap_brew; bootstrap_stow; bootstrap_gh; bootstrap_pi; bootstrap_fish; bootstrap_tinycast ;;
brew) bootstrap_brew ;; stow) bootstrap_stow ;; gh) bootstrap_gh ;; pi) bootstrap_pi ;;
- fish) bootstrap_fish ;; insomnia) bootstrap_insomnia ;; obscura) bootstrap_obscura ;; tailscale) bootstrap_tailscale ;;
+ fish) bootstrap_fish ;; obscura) bootstrap_obscura ;; tailscale) bootstrap_tailscale ;;
tinycast) bootstrap_tinycast ;;
- *) fail "Unknown setup target: $1. Use all, brew, stow, gh, pi, fish, insomnia, tinycast, obscura, or tailscale." ;;
+ *) fail "Unknown setup target: $1. Use all, brew, stow, gh, pi, fish, tinycast, obscura, or tailscale." ;;
esac
printf '\n'
if [[ "$skipped" -gt 0 ]]; then
diff --git a/swiftbar/.config/swiftbar/plugins/insomnia.sh b/swiftbar/.config/swiftbar/plugins/insomnia.sh
deleted file mode 100755
index 290114f..0000000
--- a/swiftbar/.config/swiftbar/plugins/insomnia.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-# Insomnia
-# Toggle macOS sleep prevention.
-# true
-
-pid_file="$HOME/Library/Caches/insomnia/caffeinate.pid"
-legacy_pid_file="$HOME/Library/Caches/latte/caffeinate.pid"
-if [[ -f "$legacy_pid_file" && ! -e "$pid_file" ]]; then
- mkdir -p "${pid_file%/*}"
- mv "$legacy_pid_file" "$pid_file"
-fi
-
-running_pid() {
- local command
- [[ -f "$pid_file" ]] || return 1
- read -r pid < "$pid_file"
- [[ "$pid" =~ ^[0-9]+$ ]] || return 1
- command=$(ps -p "$pid" -o command= 2>/dev/null) || return 1
- [[ "$command" == "/usr/bin/caffeinate -dimsu" ]] && kill -0 "$pid" 2>/dev/null
-}
-
-if [[ "${1:-}" == toggle ]]; then
- if running_pid; then
- kill "$pid"
- rm -f "$pid_file"
- else
- mkdir -p "${pid_file%/*}"
- nohup /usr/bin/caffeinate -dimsu /dev/null 2>&1 &
- printf '%s\n' "$!" > "$pid_file"
- fi
- exit
-fi
-
-if running_pid; then
- symbol='eye.fill'
- checked=true
-else
- symbol='eye'
- checked=false
-fi
-printf '| sfimage=%s\n' "$symbol"
-echo '---'
-printf 'Keep Mac Awake | checked=%s bash="%s" param1=toggle terminal=false refresh=true shortcut=CTRL+CMD+I\n' "$checked" "$0"
diff --git a/swiftbar/Library/LaunchAgents/com.wu-json.swiftbar-login.plist b/swiftbar/Library/LaunchAgents/com.wu-json.swiftbar-login.plist
deleted file mode 100644
index 61c1fe3..0000000
--- a/swiftbar/Library/LaunchAgents/com.wu-json.swiftbar-login.plist
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
- Label
- com.wu-json.swiftbar-login
- ProgramArguments
-
- /usr/bin/open
- -a
- /Applications/SwiftBar.app
-
- RunAtLoad
-
-
-
diff --git a/tests/integration.py b/tests/integration.py
index 00b9688..fcce4c5 100644
--- a/tests/integration.py
+++ b/tests/integration.py
@@ -40,7 +40,7 @@ def main():
repo = base / 'repo with spaces'
home = base / 'home'
home.mkdir()
- for directory in ('scripts', 'homebrew', 'fish', 'gh-dash', 'nvim', 'pi', 'wezterm', 'yazi', 'swiftbar', 'tinycast'):
+ for directory in ('scripts', 'homebrew', 'fish', 'gh-dash', 'nvim', 'pi', 'wezterm', 'yazi', 'tinycast'):
shutil.copytree(ROOT / directory, repo / directory,
ignore=shutil.ignore_patterns('node_modules', '__pycache__'))
shutil.copy2(ROOT / 'justfile', repo / 'justfile')