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}"