Files
openclaw/docs/cli/plugins/uninstall-and-update.md
T
Patrick Erichsen 2d5c68187a fix(plugins): allow reloads to wait for long-running work (#158688)
* fix(plugins): allow reloads to wait for long-running work

* test(plugins): await reload drain readiness without polling

* test(sessions): await resource retirement before reopening cleanup fixtures
2026-09-26 08:08:14 +00:00

17 KiB

summary, title, read_when
summary title read_when
What `plugins uninstall` removes, how `plugins update` resolves sources, channels, pins, and integrity drift, and reloading edited plugins Uninstall and update plugins
You want to remove a plugin and know exactly what uninstall touches
You want to update a plugin and understand pin, channel, and integrity rules
You want to reload an edited plugin without restarting the Gateway

This page covers removing and updating installed plugins, and reloading edited plugin code without restarting the Gateway.

With a running Gateway, ordinary uninstall waits for the package runtime owners to stop before removing files, and update refreshes the Gateway after the local package operation finishes. Without a running Gateway, these commands save changes for its next startup. See Install plugins for installation sources and Gateway-host path requirements.

If the Gateway rejects a lifecycle request because another operation is still running, the CLI honors its retry delay within the existing request timeout. Connection failures and failures after a mutation starts still stop the command.

Uninstall

openclaw plugins uninstall <ids...>
openclaw plugins uninstall <ids...> --dry-run
openclaw plugins uninstall <ids...> --keep-files
openclaw plugins uninstall <ids...> --force

uninstall removes plugin settings from plugins.entries, the persisted plugin index, plugin allow/deny list entries, and any plugins.load.paths entry that exactly resolves to the recorded install path. It leaves only an exact enabled: false entry for each removed plugin id. This marker records the explicit uninstall choice so remaining model, provider, or channel selections do not automatically reinstall the package during startup repair. Reinstalling does not silently re-enable it; enabling the plugin again replaces the marker. For a package with multiple child entries, any child id resolves to the package owner; uninstall removes every sibling's policy and slot/channel references, the one package install record, and the managed directory once. Linked path installs also remove an exact entry for their recorded source path. Parent directories, child paths, prefix matches, and unrelated load paths are preserved. Unless --keep-files is set, uninstall also removes the tracked managed install directory, but only when it resolves inside OpenClaw's plugin extensions root. If the plugin currently owns the memory or contextEngine slot, that slot resets to its default (memory-core for memory, legacy for context engine).

Matching load-path references are removed before package files so symlink aliases cannot leave invalid config. With a running Gateway, runtime drain also precedes removal of the install record, including with --keep-files or a linked install. If runtime drain or file removal fails, the plugin stays disabled and tracked so you can retry uninstall.

uninstall prints a preview of what will be removed. Multi-entry packages name the package owner and every affected child before prompting. Pass --force to skip the confirmation prompt (useful for scripts and non-interactive runs); without it, uninstall requires an interactive TTY. --dry-run prints the same preview and exits without prompting or changing anything.

When several IDs are supplied, uninstall resolves the whole selection before removing anything. Repeated IDs and children of the same package select that package once. Packages are processed in first-requested order, with a separate preview and confirmation for each. Cancellation or failure stops the remaining removals; earlier successful removals stay committed. An invalid target rejects the selection before any package is removed.

If a tracked package has no discovered plugin entries, uninstall can remove its exact install record and same-owner policy, including owner-keyed channel config that no other discovered plugin claims. This recovery is allowed only when no other install record shares its package path and no discovered plugin matches its id or recorded paths. Unrelated policy remains unchanged. Registry refresh rebuilds discovery metadata; it does not remove these orphan install records.

Discovered packages with missing, ambiguous, or conflicting ownership still fail closed without changing package files, config, or the installed index. Run openclaw plugins registry --refresh, inspect openclaw plugins doctor, and use openclaw doctor --fix for repairable legacy index state. If ownership is still ambiguous, reinstall the package before retrying update or uninstall.

`--keep-config` is supported as a deprecated alias for `--keep-files`.

Update

openclaw plugins update <ids-or-npm-specs...>
openclaw plugins update --all
openclaw plugins update <ids-or-npm-specs...> --dry-run
openclaw plugins update @openclaw/voice-call
openclaw plugins update @acme/demo
openclaw plugins update openclaw-codex-app-server --acknowledge-install-policy-warning

Updates apply to tracked plugin installs in the managed plugin index and tracked hook-pack installs in shared SQLite state. They reuse the source that the user already chose when installing the plugin, so they do not require a second source acknowledgement.

Supply multiple IDs or npm specs to update a selection, or use --all without IDs. Repeated targets and sibling plugin IDs update their package once. An explicit npm spec overrides an ID-only selection of the same package; two different explicit specs for one package are rejected. Unknown targets and conflicting selections fail before updates start, including with --dry-run. The existing bulk updater processes plugin packages and then hook packs, retains successful updates when another package fails, and applies saved changes to the running Gateway with one final refresh.

If update finalization fails, the error reports the original cause first and retains any rollback failures as additional diagnostic context. A failed rollback remains retryable; a successfully committed or rolled-back install is not applied again during cleanup.

On source installations, a selected plugin built with the host stays in use. Named updates, --all, and stable/beta core updates report why the registry copy was not admitted and leave its dormant install record unchanged. Package ownership checks still apply to plugins being updated; explicit plugin paths retain their selection priority.

During openclaw update, a locally linked plugin with an explicit load path keeps its selection even when OpenClaw bundles the same plugin ID. The update reports the retained plugin and path as a warning; update that plugin at its source. Linked path records are excluded from package-update ownership reconciliation, so stale package metadata does not turn link retention into an update failure.

update --all reports and skips orphaned path-source install records so remaining plugins can update. Remove an orphan record with openclaw plugins uninstall <id> when its files are no longer needed.

When you pass a plugin id, OpenClaw starts from its recorded install source. For a multi-entry package, a child id resolves to its package owner and updates every sibling together. If the new package version removes or renames children, OpenClaw removes the retired children's entries, allow/deny policy, exact child load paths, channel config, and memory/context slot selections while preserving retained/new children and unrelated plugins. Stored dist-tags such as `@beta` retain their selected release line.
The narrow exception is a trusted official package completing a catalog-declared plugin id replacement. That update starts from the catalog package selector so the renamed manifest can replace the legacy id.

Verified OpenClaw-owned npm and official ClawHub plugins resume automatic updates when their recorded exact OpenClaw release is no newer than core and their catalog source follows the default release line. The update uses the existing channel and compatibility rules, retains the recorded registry, and saves the default selector only after a successful install or an unchanged-artifact verification. For npm installs, recovery can save the default selector without downloading or reinstalling when the existing version and recorded artifact identity already match the target.

An explicit npm version or tag supplied in the current command remains authoritative. Newer release pins, independently versioned packages, third-party packages, local, Git, marketplace, and custom ClawHub sources keep their existing selectors. An npm registry mirror stays in use while eligible official npm packages receive recovery. If a retained pin has a newer available release, OpenClaw prints an explicit replacement command. ClawHub selector replacement uses `plugins install clawhub:<package> --force` because `plugins update` accepts explicit selector overrides only for npm records.

Older official-plugin syncs could save an exact version without a user request. Those records do not distinguish automatic pins from manual ones, so qualifying older OpenClaw release pins resume automatic updates in both cases. The same recovery applies to targeted updates, `--all`, `openclaw update`, and `openclaw update repair`. A failed replacement keeps the previous install record for retry.

For npm installs, you can also pass an explicit npm package spec with a dist-tag or exact version. OpenClaw resolves that package name back to the tracked plugin record, updates that installed plugin, and records the new npm spec for future id-based updates.

Passing the npm package name without a version or tag also resolves back to the tracked plugin record. Use this when a plugin was pinned to an exact version and you want to move it back to the registry's default release line.
Targeted `openclaw plugins update ` uses the configured update channel when present. Otherwise, recognized official plugins inherit OpenClaw's registry channel. Bulk `openclaw plugins update --all` uses the same registry-channel resolver for official plugins. Moving selectors remain moving even when the downloaded artifact has an exact version; recovered OpenClaw release pins follow that same policy.
`openclaw update` resolves plugin targets from the newly installed core. npm updates on the beta channel select the newer of the package's `beta` and `latest` releases; ClawHub default-line updates try `@beta` and can fall back to the recorded default/latest selector when that release is unavailable. Integrity, compatibility, trust, install-policy, and capability-consent failures do not trigger source fallback. An unavailable plugin update leaves a notice without failing an otherwise successful core update. Explicit selectors retain their meaning, with the managed OpenClaw release-pin recovery described above.
Updates retain the recorded npm or ClawHub source. Older install records do not distinguish automatic ClawHub selection from an explicit `clawhub:` request, so OpenClaw does not silently switch those records to npm. To change an existing plugin deliberately, review and run `openclaw plugins install npm: --force`. Automatic externalization of an image-owned bundled plugin uses npm first and its declared ClawHub source second. Before a live npm update, OpenClaw checks the installed package version against the npm registry metadata. If the installed version and recorded artifact identity already match the resolved target, it avoids downloading or reinstalling. A requested selector change or managed release-pin recovery can still update the plugin index without rewriting `openclaw.json`.
When a stored integrity hash exists and the fetched artifact hash changes, OpenClaw treats that as npm artifact drift. The interactive `openclaw plugins update` command prints the expected and actual hashes and asks for confirmation before proceeding. Non-interactive update helpers fail closed unless the caller supplies an explicit continuation policy.
`plugins update` uses the same warning acknowledgement as install, with `type: '' to update anyway` in an interactive terminal. The policy is re-evaluated, and `block` or a policy failure remains terminal. Community ClawHub-backed plugin updates run the same exact-release trust check as installs before downloading the replacement package. Review outcomes are printed informationally and continue; blocked releases remain non-installable. Official ClawHub packages and bundled OpenClaw plugin sources bypass this release-trust check.

Reload

openclaw plugins reload <ids...>
openclaw plugins reload <ids...> --json
openclaw plugins reload <ids...> --wait

Reload discovered plugins after editing their TypeScript source, imported helpers, or manifest, including plugins selected through plugins.load.paths. The command requires a running Gateway and waits for the replacement to finish without restarting it. Configured enablement is preserved, and unchanged plugins keep their runtime instances. JSON output includes pluginIds, restartRequired, and the applied runtime receipt with its generation and source digests when available. The receipt's selectedEntries names the files the loader selected. CLI and tool output remind you to rebuild compiled output after editing its source; reload does not run the build. Multiple IDs use one Gateway reload request and one applied runtime generation. Repeated IDs are collapsed, and the Gateway resolves package siblings together. The request supports up to 64 distinct IDs.

Busy plugins admit replacement and fence new retained work on the old instance. Existing agent runs keep their original callbacks while new runs wait for the replacement. Before stopping services or channels, replacement waits up to 60 seconds for retained work and in-flight calls to finish. Detailed readiness and Gateway logs show the queued work count and deadline; the command waits for the final applied receipt. Successful publication emits plugins.changed and logs the applied replacement. If work exceeds the budget, the reload fails once and the previous generation resumes serving; unfinished runs are not forcibly disposed. Retry openclaw plugins reload <id> after that work finishes, or use openclaw plugins reload <id> --wait to wait without a deadline for admitted work.

--wait keeps new runs behind the same replacement gate. Press Ctrl+C to cancel the wait; disconnecting its Gateway request also cancels it. Before publication, cancellation restores the previous generation when recovery succeeds, without cancelling admitted runs. Once publication commits, cancellation does not undo it. Service shutdown, resource cleanup, and recovery keep their existing deadlines. Detailed readiness exposes the pending reload; an explicit wait has no drain deadline. Incoming messages retain their channel's existing queue and replay contract; this option does not add durable ingress to channels that lack it. Run this maintenance command outside a turn that itself holds the target plugin: waiting for that turn while it waits for reload cannot make progress.

Replacement requires the previous registration's resource cleanup to finish before its successor acquires those resources. Failed cleanup can prevent replacement and automatic recovery; inspect the reported failure before retrying. The receipt can also include cleanup warnings. Modules and native libraries may remain loaded after their registrations are removed.

Bundled plugins can reload while preserving their enabled or disabled policy. Compiled bundled plugins reuse their process-loaded code when their registrations reload. If the plugin's files changed while its original module remains loaded, the result reports restartRequired: true with a warning, and CLI and tool output explain that a Gateway restart is needed to load edited code. Reload does not rebuild compiled bundled code; source installations also need a build. External captured sources return restartRequired: false after replacement. Reloading unchanged bundled files also returns restartRequired: false; channel and service registrations can be replaced without restarting the Gateway. Reloading a discovered source does not create an install record or grant permission to install, replace, or remove its files.

Reload also works with externally managed config (OPENCLAW_CONFIG_READONLY=1) and in Nix mode (OPENCLAW_NIX_MODE=1), including config composed with $include. It preserves config and installation state. If changed capabilities need new consent, record that acceptance through the deployment owner before reloading.

Changed declared capabilities may require another review. Interactive text output prompts for consent; --json never prompts. Use --accept-capabilities only after reviewing the change, including when combining it with --json. If preparation fails, the error reports whether a replacement was published. A failure after publication can leave the new generation active; inspect the reported state before retrying.