#!/usr/bin/env bash set -u usage() { printf '%s\n' 'usage: opencode-away [--check] [opencode arguments...]' } require_command() { command -v "$1" >/dev/null 2>&1 || { printf 'opencode-away: required command not found: %s\n' "$1" >&2 return 1 } } if [[ ${1-} == --help ]]; then usage exit 0 fi check_only=0 if [[ ${1-} == --check ]]; then check_only=1 shift fi require_command opencode || exit 127 require_command systemd-inhibit || exit 127 require_command git || exit 127 require_command ps || exit 127 require_command kill || exit 127 if [[ $(systemd-inhibit --help 2>&1) != *handle-lid-switch* ]]; then printf '%s\n' 'opencode-away: systemd-inhibit lacks handle-lid-switch' >&2 exit 3 fi if ! git rev-parse --show-toplevel >/dev/null 2>&1; then printf '%s\n' 'opencode-away: run this command inside a Git worktree' >&2 exit 2 fi if ((check_only)); then printf '%s\n' 'OpenCode away mode check: OK' printf 'repository: %s\n' "$(git rev-parse --show-toplevel)" printf 'opencode: %s\n' "$(command -v opencode)" printf 'systemd-inhibit: %s\n' "$(command -v systemd-inhibit)" exit 0 fi declare -a suspended_pids=() cleanup_done=0 child_pid=0 restore_swayidle() { local pid ((cleanup_done)) && return 0 cleanup_done=1 for pid in "${suspended_pids[@]}"; do if kill -0 "$pid" 2>/dev/null && [[ $(ps -o comm= -p "$pid" 2>/dev/null) == swayidle ]]; then kill -CONT "$pid" 2>/dev/null || true fi done if ((${#suspended_pids[@]})); then printf '%s\n' 'swayidle restored' fi } on_signal() { local signal=$1 if ((child_pid > 0)) && kill -0 "$child_pid" 2>/dev/null; then kill -s "$signal" "$child_pid" 2>/dev/null || true wait "$child_pid" 2>/dev/null || true fi restore_swayidle trap - "$signal" kill -s "$signal" "$$" } trap restore_swayidle EXIT trap 'on_signal HUP' HUP trap 'on_signal INT' INT trap 'on_signal TERM' TERM while read -r pid state; do [[ $pid =~ ^[0-9]+$ ]] || continue [[ $state == T* ]] && continue if kill -STOP "$pid" 2>/dev/null; then suspended_pids+=("$pid") fi done < <(ps -C swayidle -o pid=,stat= 2>/dev/null) printf '%s\n' 'OpenCode away mode' printf '%s\n' 'sleep inhibited' printf '%s\n' 'lid switch inhibited' if ((${#suspended_pids[@]})); then printf 'swayidle suspended:' printf ' %s' "${suspended_pids[@]}" printf '\n' else printf '%s\n' 'swayidle suspended: none active' fi export LARDON_OPENCODE_LONG_RUN=1 if [[ -n ${OPENCODE_AWAY_COMMAND-} ]]; then child_command=(bash -c "$OPENCODE_AWAY_COMMAND") else child_command=(opencode --auto "$@") fi systemd-inhibit \ --what=sleep:idle:handle-lid-switch \ --who='OpenCode Long Run' \ --why='Autonomous Lardon3D development ticket' \ --mode=block \ "${child_command[@]}" & child_pid=$! wait "$child_pid" child_status=$? child_pid=0 restore_swayidle exit "$child_status"