Install
openclaw skills install post-update-maintenanceAfter an OpenClaw version bump, fix what post-update-awareness noticed. Syncs drifted externalized plugins, restarts the gateway, verifies channel health, and prints a patch for stale openclaw.json entries. Every mutation is dry-run by default and gated behind --apply or explicit user confirmation. Requires post-update-awareness to be installed (reuses its drift detector). Use after an OpenClaw update when post-update-awareness reports drift or stale config, or when the user asks to "fix the things noura flagged".
openclaw skills install post-update-maintenanceThis skill changes things. Install deliberately.
It pairs with post-update-awareness — that skill reads release notes and notices broken state; this one fixes it. The split is intentional: awareness is safe to install and run on every heartbeat, maintenance is invoked when you actually want mutations.
Run this skill when any of the following is true:
post-update-awareness surfaced drifted plugins or stale config entries and the user wants them resolved.Do not run this skill from a heartbeat. It belongs in an attended session or an explicitly scheduled maintenance job, never as ambient background work.
This skill does:
openclaw plugins update <id>)Runtime: runningopenclaw.json (and apply it only on explicit confirmation)openclaw.json before any mutation; if post-restart gateway is unhealthy, restore the backupThis skill does not:
post-update-awareness)sharp, ffmpeg, node-pty) — those need package-manager context this skill shouldn't haveopenclaw-update-guard.sh)plugins.entries.<id> entries flagged by the gateway as "disabled but configured"This skill requires post-update-awareness >= 0.3.1 to be installed. It reuses two scripts from that skill:
scripts/resolve.sh — locates the awareness install across known layoutsscripts/check-plugin-drift.sh — the authoritative drift detectorIf awareness is not installed, the skill exits with a clear error pointing the user at clawhub install post-update-awareness. The two skills are versioned independently — pin a compatible awareness version in _meta.json if you find a regression.
Why the hard dep instead of vendoring: vendoring the drift detector in two skills would re-create exactly the drift problem this whole pair exists to solve. One source of truth.
{baseDir}/scripts/preflight.sh <profile>
The script:
post-update-awareness is installed (via its resolve.sh)openclaw.json is readable and writable${OPENCLAW_PROFILE_DIR}/post-update-maintenance/backups/openclaw.json.<epoch>channels status JSON to ${OPENCLAW_PROFILE_DIR}/post-update-maintenance/snapshots/channels-before.<epoch>.jsonIf any check fails, the script prints BLOCKED <reason> on stdout and exits 2. The skill must stop here and surface the reason to the user. Do not attempt to repair pre-flight failures — that's outside scope.
{baseDir}/scripts/detect-drift.sh <profile>
Internally this calls scripts/check-plugin-drift.sh from post-update-awareness via the resolver. Output is the same DRIFT <plugin-id> <version> (gateway <gw>) lines, one per drifted plugin.
If output is empty → skip to step 4 (config cleanup may still have work to do).
{baseDir}/scripts/sync-drifted-plugins.sh <profile> [--apply] [--yes]
Default mode is dry-run. Without --apply, the script prints the exact openclaw plugins update <id> commands it would run, one per line, and exits 0. Nothing changes.
With --apply, the script:
openclaw --profile <profile> plugins update <plugin-id> (sequential, not parallel — plugin updates can rewrite openclaw.json).openclaw --profile <profile> gateway restart.gateway status for up to 60 seconds waiting for Runtime: running.RESTORE <reason>.--yes skips the per-plugin confirmation prompt when running attended. Without --yes, the skill should prompt the user before each plugin (good practice when one of the drifted plugins is a sensitive transport like @openclaw/whatsapp).
Plugin updates often rewrite openclaw.json and log lines like:
Config overwrite: <path> (sha256 <old> -> <new>, backup=<path>.bak)
The script captures these and includes them in the run report. The user-facing summary should mention every config rewrite and where the .bak lives, even on success — this is information they need.
{baseDir}/scripts/detect-stale-config.sh <profile>
Parses openclaw --profile <profile> gateway status (and plugins list) for lines like:
plugins.entries.<id>: plugin disabled (...) but config is present
Output: one stale entry per line, in the form:
STALE plugins.entries.<id>
These entries are safe to remove but the gateway leaves them in place because removing config the user wrote is risky without explicit consent.
{baseDir}/scripts/clean-stale-config.sh <profile> [--apply] [--entries <id1,id2,...>]
Default mode is dry-run. Without --apply:
{ "op": "remove", "path": "/plugins/entries/<id>" } per stale entry)With --apply:
openclaw.json (defensive — config may have changed since pre-flight if step 3 ran)${OPENCLAW_PROFILE_DIR}/post-update-maintenance/backups/openclaw.json.<epoch>jq (or a Python fallback) — atomic write via <file>.tmp + mvopenclaw --profile <profile> gateway restartRESTORE <reason>--entries lets the user opt into a subset rather than all detected stale entries. Useful when one of the entries is something they intend to re-enable later.
{baseDir}/scripts/verify-channels.sh <profile>
Snapshots channels status JSON, diffs against the pre-flight snapshot. Output:
OK_HEALTHY <channel-id> — was healthy, still healthyRECOVERED <channel-id> — was unhealthy before, now healthy (good news to surface)BROKE <channel-id> <reason> — was healthy before, now unhealthy (bad news; surface loudly)STILL_BROKEN <channel-id> <reason> — was unhealthy before, still unhealthy (mention, but don't blame this skill)The pre-flight + post-mutation pairing matters: a channel that was already disconnected before the maintenance run isn't a regression caused by this skill, and the report should distinguish.
Send one brief message via the active channel.
Maintenance complete on profile <profile>.
✅ Synced: @openclaw/whatsapp 2026.5.3 → 2026.5.5
✅ Cleaned 2 stale config entries (plugins.entries.device-pair, plugins.entries.cognee-openclaw)
✅ Gateway restarted, runtime healthy
Channels:
- WhatsApp noura-moi: healthy (unchanged)
- Telegram default: healthy (unchanged)
Backups: ${OPENCLAW_PROFILE_DIR}/post-update-maintenance/backups/
Logs: ${OPENCLAW_PROFILE_DIR}/post-update-maintenance/runs/<epoch>.log
If anything restored:
⚠️ Maintenance rolled back on profile <profile>.
Attempted: sync @openclaw/whatsapp 2026.5.3 → 2026.5.5
Result: gateway unhealthy after restart — restored openclaw.json from backup.
Restored config: ${OPENCLAW_PROFILE_DIR}/post-update-maintenance/backups/openclaw.json.<epoch>
Restart log: ${OPENCLAW_PROFILE_DIR}/post-update-maintenance/runs/<epoch>.log
Recommend investigating before retrying. The gateway is now running the previous config.
Hard cap: ~18 lines, same as awareness. Drop empty sections.
Write a JSON run record to ${OPENCLAW_PROFILE_DIR}/post-update-maintenance/runs/<epoch>.json containing:
This run history lets the user (or a future agent) audit what happened without re-running anything.
All state lives under ${OPENCLAW_PROFILE_DIR}/post-update-maintenance/, resolved in the same order as post-update-awareness:
$OPENCLAW_PROFILE_DIR/post-update-maintenance/$HOME/.openclaw-<profile>/post-update-maintenance/$HOME/.openclaw/post-update-maintenance/Subdirectories:
backups/ — openclaw.json.<epoch> snapshots taken before every mutationsnapshots/ — channels-before.<epoch>.json and channels-after.<epoch>.jsonruns/ — <epoch>.json run record + <epoch>.log raw command outputOld backups and run logs older than 30 days are not auto-pruned. The skill is not allowed to delete anything in ${OPENCLAW_PROFILE_DIR} — that's the user's data.
This skill respects the following invariants:
--apply to actually change anything.RESTORE <reason> or BLOCKED <reason> line.npm install -g openclaw@<version>. Version-level recovery is the update-guard's job.sharp, ffmpeg, node-pty) are out of scope. The skill assumes the host package manager has them or doesn't.NOTHING_TO_DO and doesn't restart the gateway.Operational. Terse. Factual. Match the awareness skill's tone — this is not marketing.
| Situation | Behavior |
|---|---|
post-update-awareness not installed | BLOCKED missing-dep: post-update-awareness; tell user to clawhub install post-update-awareness first |
| Pre-flight gateway unhealthy | BLOCKED gateway-unhealthy; refuse to start — update-guard's territory |
| Plugin update fails | Skip that plugin, continue with the rest, report in run record. Don't restart unless at least one succeeded. |
| Gateway unhealthy after sync | Restore backup, restart, exit 3 |
| Gateway unhealthy after stale-config clean | Restore backup, restart, exit 3 |
--apply passed but no drift and no stale entries | NOTHING_TO_DO; exit 0 cleanly |
jq not on PATH | Fall back to a Python json-patch implementation; if both missing, BLOCKED missing-tool: jq or python3 |
post-update-awareness surfaces problems. Users were then expected to remember the exact commands to fix each one — and to remember to back up openclaw.json first, and to restart the gateway, and to check that channels didn't break. In practice they ran the wrong subset, or forgot the backup, or didn't notice when WhatsApp came back as not-linked.
This skill is the small, deliberate, gated mutation layer that closes that loop. It's separate from awareness so the trust posture is clear: awareness is safe to install everywhere, maintenance is invoked when you want changes.