baa-conductor


baa-conductor / scripts / runtime
im_wower  ·  2026-03-26

stop-launchd.sh

  1#!/usr/bin/env bash
  2set -euo pipefail
  3
  4SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
  5# shellcheck source=./common.sh
  6source "${SCRIPT_DIR}/common.sh"
  7
  8usage() {
  9  cat <<'EOF'
 10Usage:
 11  scripts/runtime/stop-launchd.sh [options]
 12
 13Options:
 14  --scope agent|daemon   launchd domain type. Defaults to agent.
 15  --service NAME         Add one service to the stop set. Repeatable.
 16  --all-services         Stop conductor, codexd, worker-runner, and status-api.
 17  --home-dir PATH        Used only to derive the default LaunchAgents path.
 18  --install-dir PATH     Override launchd install directory.
 19  --domain TARGET        Override launchctl domain target. Defaults to gui/<uid> or system.
 20  --dry-run              Print launchctl commands instead of executing them.
 21  --help                 Show this help text.
 22
 23Notes:
 24  If no service is specified, conductor + codexd are stopped.
 25  Use --service status-api to stop the optional local read-only observer.
 26EOF
 27}
 28
 29require_command launchctl
 30
 31scope="agent"
 32home_dir="$(default_home_dir)"
 33install_dir=""
 34domain_target=""
 35dry_run="0"
 36services=()
 37
 38while [[ $# -gt 0 ]]; do
 39  case "$1" in
 40    --scope)
 41      scope="$2"
 42      shift 2
 43      ;;
 44    --service)
 45      validate_service "$2"
 46      if ! contains_value "$2" "${services[@]-}"; then
 47        services+=("$2")
 48      fi
 49      shift 2
 50      ;;
 51    --all-services)
 52      while IFS= read -r service; do
 53        if ! contains_value "$service" "${services[@]-}"; then
 54          services+=("$service")
 55        fi
 56      done < <(all_services)
 57      shift
 58      ;;
 59    --home-dir)
 60      home_dir="$2"
 61      shift 2
 62      ;;
 63    --install-dir)
 64      install_dir="$2"
 65      shift 2
 66      ;;
 67    --domain)
 68      domain_target="$2"
 69      shift 2
 70      ;;
 71    --dry-run)
 72      dry_run="1"
 73      shift
 74      ;;
 75    --help)
 76      usage
 77      exit 0
 78      ;;
 79    *)
 80      die "Unknown option: $1"
 81      ;;
 82  esac
 83done
 84
 85validate_scope "$scope"
 86
 87if [[ "${#services[@]}" -eq 0 ]]; then
 88  while IFS= read -r service; do
 89    services+=("$service")
 90  done < <(default_node_verification_services)
 91fi
 92
 93if [[ -z "$install_dir" ]]; then
 94  install_dir="$(default_install_dir "$scope" "$home_dir")"
 95fi
 96
 97if [[ -z "$domain_target" ]]; then
 98  domain_target="$(default_domain_target "$scope")"
 99fi
100
101for service in "${services[@]}"; do
102  plist_path="$(service_install_path "$install_dir" "$service")"
103  if [[ ! -f "$plist_path" ]]; then
104    runtime_log "skip ${service}: missing ${plist_path}"
105    continue
106  fi
107
108  if [[ "$dry_run" == "1" ]]; then
109    printf '+ launchctl bootout %q %q 2>/dev/null || true\n' "$domain_target" "$plist_path"
110    continue
111  fi
112
113  launchctl bootout "$domain_target" "$plist_path" 2>/dev/null || true
114  runtime_log "stopped ${service}"
115done
116
117runtime_log "launchd stop completed for ${domain_target}"