Intelligent upgrade management for OpenClaw skills, extensions, and core. HITL (Human-in-the-Loop) mode: scan installed assets, read changelogs, analyze risk...
---
name: smart-updater
version: 1.1.0
changelog:
- version: 1.1.0
date: 2026-03-12
changes:
- "feat: SkillHub (腾讯国内镜像) integration — scan uses SkillHub index for batch version check (single request, no rate limit); upgrade downloads from SkillHub COS first, falls back to clawhub"
- "perf: ClawHub skills in SkillHub top-50 are checked instantly without clawhub inspect calls"
- "fix: scan result now includes inSkillHub flag for each clawhub update entry"
- version: 1.0.0
date: 2026-03-11
changes:
- "Initial release: inventory/scan/upgrade three-script system with Three Gates safety framework"
- "Supports npm (core + extensions), ClawHub skills, GitHub-cloned skills"
- "HITL mode: changelog analysis before any upgrade, user approval required"
description: "Intelligent upgrade management for OpenClaw skills, extensions, and core. HITL (Human-in-the-Loop) mode: scan installed assets, read changelogs, analyze risk, recommend upgrades, then execute only what the user approves. Use when: (1) user asks to check for updates or 检查升级, (2) user asks what's installed or 装了什么, (3) user wants to upgrade a specific skill/extension/plugin, (4) user mentions update/upgrade/版本/新版本, (5) periodic upgrade check via cron. Covers npm packages, ClawHub skills, GitHub-cloned skills, and OpenClaw core."
---
# Smart Updater
**Principle: 宁可不升,不可升坏。**
## Execution Contract
A final report is **invalid** unless ALL of the following are true:
- `inventory.json` exists (Phase 1 complete)
- `scan-result.json` exists (Phase 2 complete)
- Every update candidate has a changelog summary or explicit "unavailable" note (Phase 3 complete)
- Every update candidate has a risk level (Phase 4 complete)
If any condition is not met, do NOT generate the report. Output `BLOCKED` with the missing items instead.
### Never Do This
- Never generate the report before changelog fetch
- Never infer or invent changelog contents — fetch them
- Never present updates to the user without changelog evidence
- Never skip an update candidate in the report because its changelog was hard to find
---
## Quick Commands
### Inventory only
```bash
bash ~/.openclaw/workspace/skills/smart-updater/scripts/inventory.sh
```
Scans all installed assets → `~/.openclaw/inventory.json`
### Scan only
```bash
bash ~/.openclaw/workspace/skills/smart-updater/scripts/scan.sh
```
Checks each trackable asset for updates → `~/.openclaw/scan-result.json`
### Full Check (most common)
Execute Phases 1–5 below in order.
---
## Workflow
### Phase 1 — Inventory
**Action**: Run `inventory.sh`
**Output**: `~/.openclaw/inventory.json`
**Exit criteria**: File exists and contains `assets` array
Asset types: `core/npm`, `extension/npm`, `extension/local`, `extension/github`, `skill/clawhub`, `skill/github`, `skill/local`, `builtin/bundled`
Do not continue until Phase 1 exit criteria are met.
### Phase 2 — Scan
**Action**: Run `scan.sh`
**Output**: `~/.openclaw/scan-result.json`
**Exit criteria**: File exists and contains `updates` array
Do not continue until Phase 2 exit criteria are met.
If `updates` is empty → report "all up to date" and stop. No further phases needed.
### Phase 3 — Changelog Fetch
**Action**: For EACH update in `scan-result.json`, fetch changelog/release notes.
**Output**: Changelog summary per update candidate.
| Source | How to fetch |
|--------|-------------|
| **ClawHub** | `clawhub inspect <slug> --versions --limit 5` |
| **npm** | `npm info <pkg> --json` → check `repository`, then `web_fetch` GitHub releases |
| **GitHub** | `cd <dir> && git log --oneline HEAD..origin/main` or `changelogUrl` from scan-result |
Note: scan-result.json may already contain a `changelog` array for ClawHub skills. Use it if present, but verify/supplement if sparse.
**For each update, record:**
- One-line summary of what changed
- Source URL or command used
- Breaking changes (if any)
- "unavailable" with reason (if fetch failed)
**Exit criteria**: Every update candidate has EITHER:
- a changelog summary with source, OR
- an explicit "changelog unavailable" note with the source attempted
⛔ Do not continue to Phase 4 until Phase 3 exit criteria are met.
### Phase 4 — Risk Assessment
**Action**: Assign risk level to each update using this matrix:
| Condition | Risk | Action |
|-----------|------|--------|
| patch + bugfix | 🟢 Low | Recommend |
| minor + feature | 🟡 Medium | Suggest |
| major + breaking | 🔴 High | Require confirmation |
| extension type | 🟡+ | Always full Gate 2 flow |
| changelog unavailable | 🟠 Unknown | Flag for manual review |
| new executable scripts | 🟠+ | Suggest skill-vetter |
| name conflict | 🔴 | Block upgrade (Gate 1) |
**Exit criteria**: Every update candidate has a risk level assigned.
### Gate — Pre-Report Verification
Before generating the report, verify:
- [ ] Every update has changelog summary or "unavailable" note
- [ ] Every update has risk level
- [ ] Every update has changelog source (URL or command)
If ANY checkbox fails → output `BLOCKED: <missing items>`. Do NOT proceed.
### Phase 5 — Report
**Only now** read `references/report-format.md` and generate the report using that template.
The report MUST include changelog summaries from Phase 3. If Phase 3 data is absent, return to Phase 3.
### Phase 6 — Wait for User
Present the report and wait. Do NOT auto-upgrade. Do NOT proceed without explicit user selection.
---
## Upgrade Execution
When the user selects updates to apply:
**Execute upgrades one at a time, sequentially.** Each must pass Three Gates:
```
Gate 1: Pre-flight → Gate 2: Isolation → Gate 3: Post-flight → ✅
fail↓ fail↓ fail↓
阻止升级 中止+回滚 回滚+通知
```
- **Gate 1**: Source tracked, no name conflict, gateway healthy (extensions), local/github extensions blocked
- **Gate 2**: Backup isolated, jiti cleared (extensions), config preserved (core), upgrade executed
- **Gate 3**: Version verified, file count checked, provenance validated, rollback on failure
**For detailed gate definitions and rollback procedures**: Read `references/three-gates.md`
For each upgrade: Announce → Gate 1 → Gate 2 (backup+execute) → Gate 3 (verify) → Report result
---
## Files
| File | Purpose |
|------|---------|
| `~/.openclaw/inventory.json` | Asset inventory (Phase 1) |
| `~/.openclaw/scan-result.json` | Scan results with changelog data (Phase 2) |
| `references/report-format.md` | Report template (Phase 5 only) |
| `references/three-gates.md` | Detailed gate definitions |
| `~/.openclaw/skill-backups/` | Skill backup directory |
| `~/.openclaw/extensions-backup/` | Extension backup directory |
| `~/.openclaw/plist-backup/` | Gateway plist backup (core upgrades) |
don't have the plugin yet? install it then click "run inline in claude" again.
smart updater handles version checking and upgrade approval for openclaw core, extensions, and skills across npm, clawhub, skiphub, and github sources. run this when the user asks to check for updates (检查升级), list what's installed (装了什么), upgrade a specific asset, or mentions update/upgrade/版本/新版本 keywords. the skill scans your inventory, fetches changelogs from each source, assigns risk levels, presents findings for user approval, then executes approved upgrades using the three gates safety framework. principle: never upgrade without user confirmation and verified changelog evidence (宁可不升,不可升坏).
local context:
~/.openclaw/workspace/skills/smart-updater/scripts/inventory.sh , executable script that scans installed assets~/.openclaw/workspace/skills/smart-updater/scripts/scan.sh , executable script that checks each asset for updatesreferences/report-format.md , template for final report (read in phase 5 only)references/three-gates.md , detailed gate definitions and rollback proceduresexternal sources and credentials:
registry.npmjs.org or configured npm registry; no auth needed for public packages; set NPM_TOKEN env var if using private packages (scope: read)CLAWHUB_API_KEY optional but recommended (scope: skill metadata, version history); rate limit 1000 req/min per IPGITHUB_TOKEN env var (scope: read public repos); rate limit 60 req/hour unauthenticated, 5000 req/hour authenticatedoutput directories (auto-created if missing):
~/.openclaw/inventory.json , phase 1 output~/.openclaw/scan-result.json , phase 2 output~/.openclaw/skill-backups/ , backup location for skill upgrades~/.openclaw/extensions-backup/ , backup location for extension upgrades~/.openclaw/plist-backup/ , gateway plist backup for core upgradesedge cases to prepare for:
references/report-format.md or references/three-gates.md , fail phase 5 or phase 6 with "config missing" errorbash ~/.openclaw/workspace/skills/smart-updater/scripts/inventory.sh~/.openclaw/inventory.json with asset arraytype: one of core/npm, extension/npm, extension/local, extension/github, skill/clawhub, skill/github, skill/local, builtin/bundledname: asset name or package nameversion: currently installed version (semver)source: url or local pathlocation: filesystem pathassets array is non-empty (or empty if intentional "nothing installed")~/.openclaw/inventory.json from phase 1bash ~/.openclaw/workspace/skills/smart-updater/scripts/scan.sh~/.openclaw/scan-result.json with updates arrayinSkillHub flag in resultcd <location> && git ls-remote --tags origin to find latest release tagname, current, latest, type, sourcechangelogUrl (if detected from source)inSkillHub (boolean, for clawhub skills)skipped_reason (for non-trackable types)updates array is present (may be empty)input: ~/.openclaw/scan-result.json with each update candidate
for each update in the array, fetch changelog using source-specific method:
clawhub skills:
clawhub inspect <slug> --versions --limit 5current and latestnpm packages:
npm info <package> --jsonversions object to extract entries between current and latestrepository field exists, fetch github releases from that urlcurl -s https://api.github.com/repos/<owner>/<repo>/releases | jqgithub-cloned skills/extensions:
cd <location> && git log --oneline HEAD..origin/main --max-count=20per update, record:
changelog_summary: one-line text describing key changes (e.g. "bugfixes in parser, improved error handling")changelog_source: url (github releases, npm, etc) or command usedbreaking_changes: array of breaking items or empty arraychangelog_status: "available" or "unavailable"fetch_error: (if status is unavailable) reason stringexit check: every update entry has changelog summary or explicit "unavailable" note with reason. do not proceed until all entries are populated.
input: ~/.openclaw/scan-result.json enriched from phase 3
assign risk level to each update using this matrix:
| condition | risk level | recommendation |
|---|---|---|
| patch version bump + bugfix only | 🟢 low | recommend upgrade |
| minor version bump + feature (no breaking) | 🟡 medium | suggest upgrade |
| major version bump + breaking change declared | 🔴 high | require explicit user confirmation |
| extension type (any version) | 🟡+ medium-high | always require full gate 2 flow + user confirmation |
| changelog unavailable | 🟠 unknown | flag for manual review, suggest user vets manually |
| new executable scripts in upgrade | 🟠+ unknown-high | suggest running skill-vetter before upgrade |
| name conflict (same name, different source) | 🔴 high | block upgrade in gate 1 |
per update, record:
risk_level: one of "low", "medium", "high", "unknown"risk_reason: string explaining why (e.g. "major + breaking changes", "changelog unavailable")action: one of "recommend", "suggest", "confirm", "block", "manual_review"exit check: every update has risk_level and action assigned.
BLOCKED: <missing item list> and stop. do not generate report.references/report-format.md template~/.openclaw/upgrade-report.txtfor each user-selected update, execute in order (do not parallelize):
announce: "upgrading
gate 1: pre-flight checks:
gate 2: isolation and backup:
~/.openclaw/skill-backups/ or ~/.openclaw/extensions-backup/)~/.openclaw/plist-backup/gate 3: post-flight verification:
latest from scanon all gates pass: output "✅
rollback on any gate failure:
final output: summary of successful upgrades, failed upgrades, and rollbacks
after phase 2 scan completes:
updates array is empty: output "all assets are up to date" and stop. do not proceed to phase 3.updates array has entries: proceed to phase 3 (changelog fetch).after phase 3 changelog fetch:
before phase 5 report generation:
references/report-format.md is missing: output "config missing: report-format.md not found, halt".BLOCKED: <missing items> and stop.in phase 6 (wait for user approval):
in phase 7 (gate 1 execution):
extension/local or skill/local: block upgrade, output "local assets cannot be auto-upgraded, manual action required".in phase 7 (gate 2 execution):
in phase 7 (gate 3 execution):
on network errors (any phase):
phase 1 output:
~/.openclaw/inventory.json{ "assets": [ { "type": string, "name": string, "version": string, "source": string, "location": string }, ... ] }phase 2 output:
~/.openclaw/scan-result.json{ "updates": [ { "name": string, "current": string, "latest": string, "type": string, "source": string, "changelogUrl": string?, "inSkillHub": boolean?, "skipped_reason": string? }, ... ], "timestamp": string }phase 3 output (in-memory enrichment to scan-result.json):
changelog_summary, changelog_source, breaking_changes (array), changelog_status, fetch_error (if unavailable)phase 4 output (in-memory enrichment to scan-result.json):
risk_level (one of "low", "medium", "high", "unknown"), risk_reason, actionphase 5 output:
~/.openclaw/upgrade-report.txt (optional stdout also)references/report-format.md templatephase 7 output:
~/.openclaw/skill-backups/, ~/.openclaw/extensions-backup/, ~/.openclaw/plist-backup/ (kept on disk for manual recovery)overall execution contract: a final report is invalid unless all of the following are true:
~/.openclaw/inventory.json exists (phase 1 complete)~/.openclaw/scan-result.json exists and is enriched with phase 3 and 4 fields (phase 2, 3, 4 complete)if any condition is not met, output BLOCKED: <missing items> with the specific missing items listed. do not generate the report.
never do this:
when the skill worked:
user knows it worked when:
failure signals (user knows it did not work):
original author: clawhub / openclaw team