.claude/skills/openclaw-upgrade-plist-overwrite/SKILL.md
Fix OpenClaw gateway crash-looping after npm upgrade overwrites LaunchAgent plist. Use when: (1) Gateway exits with code 1 after `npm install -g openclaw`, (2) gateway.err.log shows MissingEnvVarError for BLUEBUBBLES_PASSWORD or other secrets, (3) LaunchAgent plist ProgramArguments changed from wrapper script to direct node execution, (4) `openclaw install --service` ran as post-install hook and replaced the plist. Covers diagnosis, fix, and safeguard for future upgrades.
npx skillsauth add Dbochman/dotfiles openclaw-upgrade-plist-overwriteInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
npm install -g openclaw runs openclaw install --service as a post-install hook,
which overwrites ~/Library/LaunchAgents/ai.openclaw.gateway.plist. The new plist
uses direct node execution with inline EnvironmentVariables but is missing secrets
like BLUEBUBBLES_PASSWORD that the wrapper script sources from ~/.openclaw/.secrets-cache.
This causes the gateway to crash-loop with exit code 1.
launchctl list | grep openclaw shows non-zero exit code~/.openclaw/logs/gateway.err.log contains MissingEnvVarError or config parse errorsProgramArguments points to /opt/homebrew/opt/node@22/bin/node directly instead of the wrapper appThe openclaw install --service post-install hook:
/opt/homebrew/opt/node@22/bin/node /opt/homebrew/lib/node_modules/openclaw/dist/entry.js gatewayEnvironmentVariables dict~/.openclaw/.secrets-cache (e.g., BLUEBUBBLES_PASSWORD, OP_SERVICE_ACCOUNT_TOKEN)The wrapper script at ~/Applications/OpenClawGateway.app/Contents/MacOS/OpenClawGateway
sources all secrets from .secrets-cache before exec'ing node, which is the correct pattern
for headless launchd services (no biometric/1Password available).
ssh dylans-mac-mini 'launchctl list | grep openclaw.gateway'
Non-zero exit code (e.g., 1) confirms crash.
ssh dylans-mac-mini 'tail -50 ~/.openclaw/logs/gateway.err.log'
Look for MissingEnvVarError, Config invalid, or env var substitution failures like
${BLUEBUBBLES_PASSWORD} appearing literally in config.
ssh dylans-mac-mini 'plutil -p ~/Library/LaunchAgents/ai.openclaw.gateway.plist'
If ProgramArguments contains /opt/homebrew/opt/node@22/bin/node instead of the
wrapper path (~/Applications/OpenClawGateway.app/Contents/MacOS/OpenClawGateway),
the plist was overwritten.
New OpenClaw versions may change the entry point (e.g., dist/index.js to dist/entry.js).
Check what the new plist points to and update the wrapper:
# Check new entry point from the overwritten plist
ssh dylans-mac-mini 'plutil -p ~/Library/LaunchAgents/ai.openclaw.gateway.plist | grep entry'
# Update wrapper script's exec line
ssh dylans-mac-mini 'cat ~/Applications/OpenClawGateway.app/Contents/MacOS/OpenClawGateway'
# Edit the exec line to use the correct dist/*.js path
Replace the overwritten plist with the wrapper-based version:
ssh dylans-mac-mini "cat > ~/Library/LaunchAgents/ai.openclaw.gateway.plist << '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>ai.openclaw.gateway</string>
<key>ProgramArguments</key>
<array>
<string>/Users/dbochman/Applications/OpenClawGateway.app/Contents/MacOS/OpenClawGateway</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/dbochman/.openclaw/logs/gateway.log</string>
<key>StandardErrorPath</key>
<string>/Users/dbochman/.openclaw/logs/gateway.err.log</string>
</dict>
</plist>
PLIST"
ssh dylans-mac-mini 'launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plist 2>/dev/null; launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.openclaw.gateway.plist'
ssh dylans-mac-mini 'sleep 3 && launchctl list | grep openclaw.gateway'
Exit code should be 0. Check logs:
ssh dylans-mac-mini 'tail -5 ~/.openclaw/logs/gateway.log'
The ~/bin/openclaw-weekly-upgrade script on Mini should backup/restore the plist
around npm install:
# Before npm install
PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
PLIST_BAK="/tmp/openclaw-gateway-plist-backup.plist"
cp "$PLIST" "$PLIST_BAK"
# npm install happens here
/opt/homebrew/opt/node@22/bin/npm install -g openclaw@latest
# After npm install — restore plist
if ! diff -q "$PLIST_BAK" "$PLIST" > /dev/null 2>&1; then
cp "$PLIST_BAK" "$PLIST"
echo "WARN: plist was overwritten by npm install, restored from backup"
fi
launchctl list | grep openclaw.gateway shows exit code 0tail ~/.openclaw/logs/gateway.err.log has no MissingEnvVarErrorplutil -p ~/Library/LaunchAgents/ai.openclaw.gateway.plist shows wrapper path in ProgramArguments~/.openclaw/.secrets-cache which contains BLUEBUBBLES_PASSWORD,
OP_SERVICE_ACCOUNT_TOKEN, and other secrets in KEY=VALUE format (chmod 600)dist/index.js to dist/entry.js in v2026.3.2 — check
the installed version's actual entry point if wrapper fails after upgradeopenclaw install --service hook cannot be disabled via npm flagslaunchctl bootout + bootstrap is required (not just kickstart) to pick up plist changesopenclaw.json config changes but plist changes require full service reloaddevelopment
Search the web for current information, news, facts, and answers. Use when asked questions about current events, needing to look something up, finding websites, researching topics, or when you need up-to-date information beyond your training data.
development
Summarize any URL, YouTube video, podcast, PDF, or file into concise text. Use when asked to read an article, summarize a link, get the gist of a video or podcast, extract content from a URL, or when you need to understand what a web page or document contains.
development
Play music via Spotify and control Google Home speakers. Use when asked to play music, songs, artists, playlists, podcasts, or control speakers/volume/audio.
testing
Create new OpenClaw skills, modify and improve existing skills, and measure skill performance with evals. Use when users want to create a skill from scratch, update or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy. Also use when asked to "make a skill", "turn this into a skill", "improve this skill", or "test this skill".