← 목록으로
2026-02-25plans

LaunchAgent Migration Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Consolidate scattered LaunchAgent/cron automation into a single, maintainable system with clear ownership, deduplication, and missing scheduled jobs added.

Architecture: All scripts live in business-builder/scripts/ (canonical source). LaunchAgents reference those scripts directly. OpenClaw workspace copies are eliminated as duplicates. Missing scheduled automation (OKR scheduler, Turso backup) gets new LaunchAgents.

Tech Stack: macOS LaunchAgents (plist), bash scripts, git


Current State Analysis

LaunchAgent Inventory (~/Library/LaunchAgents/)

#FileLabelPurposeScheduleStatus
1ai.openclaw.gateway.plistai.openclaw.gatewayOpenClaw Gateway (v2026.2.23) — VP communication layerRunAtLoad + KeepAlive (always running)Active (PID 8770)
2com.macclaw.jarvis-limit-check.plistcom.macclaw.jarvis-limit-checkMonitors tmux vice-claude session for Claude usage limitsEvery 300s (5 min)Active
3com.macclaw.daily-git-push.plistcom.macclaw.daily-git-pushDaily auto-backup: sync core files + git push12:00 + 23:50 KSTActive

Crontab

ScheduleScriptPurpose
*/30 * * * */Users/nbs22/ObsidianVault/.scripts/auto-sync.shObsidian vault git auto-sync

Script Duplication Problem

Scripts exist in two locations with varying degrees of drift:

ScriptOpenClaw (~/.openclaw/workspace/scripts/)Business-Builder (scripts/)Drift?
check-jarvis-limit.shYesYesIdentical
telegram-reply.shYesYesIdentical
vp_prompt_inject.shYes (HTTP API version)Yes (tmux direct version)DIVERGED
daily-git-push.shYesNoOpenClaw-only
start-vice-claude.shYesNoOpenClaw-only
okr-weekly-review.shYesNoOpenClaw-only
vice-reply.shNoYesBB-only
ceo-reply.shNoYesBB-only
report.shNoYesBB-only (= vice-reply.sh duplicate)
scheduler-report.shNoYesBB-only
okr-scheduler.shNoYesBB-only
backup-turso.shNoYesBB-only

LaunchAgent Issues

  1. Both LaunchAgents point to OpenClaw scripts (~/.openclaw/workspace/scripts/) instead of the git-tracked canonical source (business-builder/scripts/). If OpenClaw workspace is reset or changed, automation breaks.
  2. Script duplication: 3 scripts exist in both locations. vp_prompt_inject.sh has diverged.
  3. Missing LaunchAgents: Several scripts have no automated schedule:
    • okr-scheduler.sh — comment says "6 hours" but no LaunchAgent exists
    • backup-turso.sh — no scheduled backup
    • okr-weekly-review.sh — comment says "Monday 09:00" but no LaunchAgent
  4. report.sh and vice-reply.sh are identicalreport.sh is the old name, vice-reply.sh is the current canonical name (per MEMORY.md). report.sh should be a symlink or removed.
  5. scheduler-report.sh uses Turso HTTP API directly while vice-reply.sh uses @libsql/client via Node.js — inconsistent DB access pattern.

Migration Tasks

Task 1: Consolidate script canonical location to business-builder

Files:

  • Move: ~/.openclaw/workspace/scripts/daily-git-push.sh -> scripts/daily-git-push.sh
  • Move: ~/.openclaw/workspace/scripts/start-vice-claude.sh -> scripts/start-vice-claude.sh
  • Move: ~/.openclaw/workspace/scripts/okr-weekly-review.sh -> scripts/okr-weekly-review.sh
  • Delete from OpenClaw: check-jarvis-limit.sh, telegram-reply.sh (duplicates)
  • Keep in OpenClaw: vp_prompt_inject.sh (OpenClaw-specific HTTP API version)

Step 1: Copy OpenClaw-only scripts to business-builder

BB="/Users/nbs22/(Claude)/(claude).projects/business-builder/scripts"
OC="/Users/nbs22/.openclaw/workspace/scripts"

cp "$OC/daily-git-push.sh" "$BB/daily-git-push.sh"
cp "$OC/start-vice-claude.sh" "$BB/start-vice-claude.sh"
cp "$OC/okr-weekly-review.sh" "$BB/okr-weekly-review.sh"
chmod +x "$BB/daily-git-push.sh" "$BB/start-vice-claude.sh" "$BB/okr-weekly-review.sh"

Step 2: Update daily-git-push.sh paths

The script already uses $HOME/.openclaw/workspace and $BB variables correctly. No path changes needed inside the script.

Step 3: Remove duplicates from OpenClaw

OC="/Users/nbs22/.openclaw/workspace/scripts"
rm "$OC/check-jarvis-limit.sh"
rm "$OC/telegram-reply.sh"

Keep vp_prompt_inject.sh in OpenClaw (HTTP API version used by VP directly).

Step 4: Commit

cd "/Users/nbs22/(Claude)/(claude).projects/business-builder"
git add scripts/daily-git-push.sh scripts/start-vice-claude.sh scripts/okr-weekly-review.sh
git commit -m "chore: consolidate scripts from openclaw to business-builder canonical location"

Task 2: Remove report.sh duplicate (alias of vice-reply.sh)

Files:

  • Delete: scripts/report.sh
  • Create symlink: scripts/report.sh -> scripts/vice-reply.sh

Step 1: Verify report.sh and vice-reply.sh are identical

diff scripts/report.sh scripts/vice-reply.sh

Expected: identical (they are).

Step 2: Replace report.sh with symlink

cd "/Users/nbs22/(Claude)/(claude).projects/business-builder/scripts"
rm report.sh
ln -s vice-reply.sh report.sh

This maintains backward compatibility for any script calling report.sh.

Step 3: Commit

cd "/Users/nbs22/(Claude)/(claude).projects/business-builder"
git add scripts/report.sh
git commit -m "chore: replace report.sh with symlink to vice-reply.sh (deduplicate)"

Task 3: Migrate LaunchAgent plist paths to business-builder

Files:

  • Modify: ~/Library/LaunchAgents/com.macclaw.jarvis-limit-check.plist
  • Modify: ~/Library/LaunchAgents/com.macclaw.daily-git-push.plist

Step 1: Update jarvis-limit-check.plist

Change ProgramArguments from:

/Users/nbs22/.openclaw/workspace/scripts/check-jarvis-limit.sh

To:

/Users/nbs22/(Claude)/(claude).projects/business-builder/scripts/check-jarvis-limit.sh

Full plist content:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.macclaw.jarvis-limit-check</string>

    <key>ProgramArguments</key>
    <array>
      <string>/bin/zsh</string>
      <string>-lc</string>
      <string>/Users/nbs22/(Claude)/(claude).projects/business-builder/scripts/check-jarvis-limit.sh vice-claude >> /Users/nbs22/.openclaw/logs/jarvis-limit-check.log 2>&1</string>
    </array>

    <key>StartInterval</key>
    <integer>300</integer>

    <key>RunAtLoad</key>
    <true/>

    <key>StandardOutPath</key>
    <string>/Users/nbs22/.openclaw/logs/jarvis-limit-check.stdout.log</string>
    <key>StandardErrorPath</key>
    <string>/Users/nbs22/.openclaw/logs/jarvis-limit-check.stderr.log</string>
  </dict>
</plist>

Step 2: Update daily-git-push.plist

Change ProgramArguments from:

/Users/nbs22/.openclaw/workspace/scripts/daily-git-push.sh

To:

/Users/nbs22/(Claude)/(claude).projects/business-builder/scripts/daily-git-push.sh

Full plist content:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.macclaw.daily-git-push</string>

    <key>ProgramArguments</key>
    <array>
      <string>/bin/zsh</string>
      <string>-lc</string>
      <string>/Users/nbs22/(Claude)/(claude).projects/business-builder/scripts/daily-git-push.sh</string>
    </array>

    <key>StartCalendarInterval</key>
    <array>
      <dict>
        <key>Hour</key>
        <integer>12</integer>
        <key>Minute</key>
        <integer>0</integer>
      </dict>
      <dict>
        <key>Hour</key>
        <integer>23</integer>
        <key>Minute</key>
        <integer>50</integer>
      </dict>
    </array>

    <key>StandardOutPath</key>
    <string>/Users/nbs22/.openclaw/logs/daily-git-push.stdout.log</string>
    <key>StandardErrorPath</key>
    <string>/Users/nbs22/.openclaw/logs/daily-git-push.stderr.log</string>
  </dict>
</plist>

Step 3: Reload LaunchAgents

launchctl unload ~/Library/LaunchAgents/com.macclaw.jarvis-limit-check.plist
launchctl load ~/Library/LaunchAgents/com.macclaw.jarvis-limit-check.plist

launchctl unload ~/Library/LaunchAgents/com.macclaw.daily-git-push.plist
launchctl load ~/Library/LaunchAgents/com.macclaw.daily-git-push.plist

Step 4: Verify both agents are running

launchctl list | grep macclaw

Expected: both show with exit code 0.


Task 4: Add missing LaunchAgent for OKR scheduler (6-hour cycle)

Files:

  • Create: ~/Library/LaunchAgents/com.macclaw.okr-scheduler.plist

Step 1: Create plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.macclaw.okr-scheduler</string>

    <key>ProgramArguments</key>
    <array>
      <string>/bin/zsh</string>
      <string>-lc</string>
      <string>/Users/nbs22/(Claude)/(claude).projects/business-builder/scripts/okr-scheduler.sh >> /Users/nbs22/.openclaw/logs/okr-scheduler.log 2>&1</string>
    </array>

    <key>StartInterval</key>
    <integer>21600</integer>

    <key>StandardOutPath</key>
    <string>/Users/nbs22/.openclaw/logs/okr-scheduler.stdout.log</string>
    <key>StandardErrorPath</key>
    <string>/Users/nbs22/.openclaw/logs/okr-scheduler.stderr.log</string>
  </dict>
</plist>

Step 2: Load LaunchAgent

launchctl load ~/Library/LaunchAgents/com.macclaw.okr-scheduler.plist

Step 3: Verify

launchctl list | grep okr-scheduler

Expected: shows with exit code 0 or -.


Task 5: Add missing LaunchAgent for Turso backup (daily)

Files:

  • Create: ~/Library/LaunchAgents/com.macclaw.turso-backup.plist

Step 1: Create plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.macclaw.turso-backup</string>

    <key>ProgramArguments</key>
    <array>
      <string>/bin/zsh</string>
      <string>-lc</string>
      <string>/Users/nbs22/(Claude)/(claude).projects/business-builder/scripts/backup-turso.sh >> /Users/nbs22/.openclaw/logs/turso-backup.log 2>&1</string>
    </array>

    <key>StartCalendarInterval</key>
    <dict>
      <key>Hour</key>
      <integer>4</integer>
      <key>Minute</key>
      <integer>0</integer>
    </dict>

    <key>StandardOutPath</key>
    <string>/Users/nbs22/.openclaw/logs/turso-backup.stdout.log</string>
    <key>StandardErrorPath</key>
    <string>/Users/nbs22/.openclaw/logs/turso-backup.stderr.log</string>
  </dict>
</plist>

Step 2: Load LaunchAgent

launchctl load ~/Library/LaunchAgents/com.macclaw.turso-backup.plist

Step 3: Verify

launchctl list | grep turso-backup

Task 6: Add missing LaunchAgent for OKR weekly review (Monday 09:00)

Files:

  • Create: ~/Library/LaunchAgents/com.macclaw.okr-weekly-review.plist

Step 1: Create plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.macclaw.okr-weekly-review</string>

    <key>ProgramArguments</key>
    <array>
      <string>/bin/zsh</string>
      <string>-lc</string>
      <string>/Users/nbs22/(Claude)/(claude).projects/business-builder/scripts/okr-weekly-review.sh >> /Users/nbs22/.openclaw/logs/okr-weekly-review.log 2>&1</string>
    </array>

    <key>StartCalendarInterval</key>
    <dict>
      <key>Weekday</key>
      <integer>1</integer>
      <key>Hour</key>
      <integer>9</integer>
      <key>Minute</key>
      <integer>0</integer>
    </dict>

    <key>StandardOutPath</key>
    <string>/Users/nbs22/.openclaw/logs/okr-weekly-review.stdout.log</string>
    <key>StandardErrorPath</key>
    <string>/Users/nbs22/.openclaw/logs/okr-weekly-review.stderr.log</string>
  </dict>
</plist>

Step 2: Update okr-weekly-review.sh to use business-builder paths

The script currently references $PROJECT_ROOT/scripts/report.sh. After Task 2, report.sh is a symlink to vice-reply.sh, so this works. No changes needed.

Step 3: Load LaunchAgent

launchctl load ~/Library/LaunchAgents/com.macclaw.okr-weekly-review.plist

Completion Checklist

After all tasks:

CheckVerification Command
All 6 LaunchAgents loadedlaunchctl list | grep -E 'macclaw|openclaw' — expect 6 entries
No duplicate scripts in OpenClawls ~/.openclaw/workspace/scripts/ — only vp_prompt_inject.sh and start-vice-claude.sh remain
All plists point to business-buildergrep -l 'openclaw/workspace/scripts' ~/Library/LaunchAgents/*.plist — expect 0 results
report.sh is symlinkls -la scripts/report.sh — shows -> vice-reply.sh
jarvis-limit-check workingcat ~/.openclaw/workspace/memory/jarvis-limit-state.json — recent timestamp
daily-git-push scheduledlaunchctl list | grep daily-git-push — exit 0
OKR scheduler runningWait 6h or bash scripts/okr-scheduler.sh manual test
Turso backup scheduledlaunchctl list | grep turso-backup — loaded
OKR weekly review scheduledlaunchctl list | grep okr-weekly-review — loaded

Final State

After migration:

~/Library/LaunchAgents/
  ai.openclaw.gateway.plist              → OpenClaw gateway (unchanged)
  com.macclaw.jarvis-limit-check.plist   → scripts/check-jarvis-limit.sh (path updated)
  com.macclaw.daily-git-push.plist       → scripts/daily-git-push.sh (path updated)
  com.macclaw.okr-scheduler.plist        → scripts/okr-scheduler.sh (NEW)
  com.macclaw.turso-backup.plist         → scripts/backup-turso.sh (NEW)
  com.macclaw.okr-weekly-review.plist    → scripts/okr-weekly-review.sh (NEW)

business-builder/scripts/  (canonical source for all scripts)
  backup-turso.sh
  ceo-reply.sh
  check-jarvis-limit.sh
  daily-git-push.sh          (moved from openclaw)
  okr-scheduler.sh
  okr-weekly-review.sh       (moved from openclaw)
  report.sh -> vice-reply.sh (symlink)
  scheduler-report.sh
  start-vice-claude.sh       (moved from openclaw)
  telegram-reply.sh
  vice-reply.sh
  vp_prompt_inject.sh

~/.openclaw/workspace/scripts/  (VP-specific only)
  vp_prompt_inject.sh         (HTTP API version, VP-specific)

Risk Notes

  • ai.openclaw.gateway.plist: NOT touched. This is OpenClaw's own managed plist with secrets. Changing it could break VP communication.
  • Parentheses in paths: (Claude)/(claude).projects contains special characters. All plist entries must quote or escape properly. macOS LaunchAgent handles this natively in <string> XML elements.
  • okr-weekly-review.sh references $PROJECT_ROOT/projects/jarvis-system/apps/worker: Requires @libsql/client to be installed there. Verify with ls projects/jarvis-system/apps/worker/node_modules/@libsql/ before enabling the LaunchAgent.
plans/2026/02/25/launchagent-migration.md