#!/bin/bash # Claude Code Remote Control on-demand controller (클로 스킬용) # # 사용법: # ensure_session.sh open — Remote Control daemon 시작 (이미 떠있으면 안내만) # ensure_session.sh close — daemon 종료 # ensure_session.sh status — 현재 상태 # # launchd 등록 라벨: ai.openclaw.claude-remote-control (RunAtLoad=false, KeepAlive=false) set -euo pipefail LABEL="ai.openclaw.claude-remote-control" PLIST="$HOME/Library/LaunchAgents/$LABEL.plist" SERVICE="gui/$UID/$LABEL" bootstrap_if_needed() { if ! launchctl print "$SERVICE" >/dev/null 2>&1; then if [ ! -f "$PLIST" ]; then echo "ERROR: plist 없음: $PLIST" exit 1 fi launchctl bootstrap "gui/$UID" "$PLIST" fi } is_running() { local state state=$(launchctl print "$SERVICE" 2>/dev/null | awk -F'=' '/^[[:space:]]*state[[:space:]]*=/{gsub(/[[:space:]]/,"",$2);print $2;exit}') [ "$state" = "running" ] } cmd="${1:-status}" case "$cmd" in open|start) bootstrap_if_needed if is_running; then echo "이미 동작 중. claude.ai/code 또는 Claude 앱에서 'openclaw' 세션에 접속하세요." else launchctl kickstart "$SERVICE" >/dev/null 2>&1 || true sleep 2 if is_running; then echo "Claude Code 원격 세션 시작됨. claude.ai/code 또는 Claude 앱에서 'openclaw' 세션에 접속하세요." else echo "ERROR: 시작 실패. 로그: ~/.openclaw/logs/claude-remote-control.err.log" exit 1 fi fi ;; close|stop) if launchctl print "$SERVICE" >/dev/null 2>&1; then launchctl bootout "$SERVICE" 2>/dev/null || true echo "Claude Code 원격 세션 종료됨." else echo "이미 종료 상태." fi ;; status) if launchctl print "$SERVICE" >/dev/null 2>&1 && is_running; then echo "동작 중. claude.ai/code 또는 Claude 앱에서 'openclaw' 세션 접속 가능." else echo "종료 상태. 'open' 명령으로 시작 가능." fi ;; *) echo "Usage: $0 {open|close|status}" exit 1 ;; esac