Environment
- OpenClaw 2026.5.2 (8b2a6e5)
- Raspberry Pi 5, Linux arm64, Node 22.22.2
- Single-user gateway, systemd-managed
Symptom
Running openclaw plugins install <pkgB> after a prior openclaw plugins install <pkgA> removes pkgA's on-disk directory. The install record for pkgA remains in ~/.openclaw/plugins/installs.json, but ~/.openclaw/npm/node_modules/@openclaw/<pkgA> is gone. The gateway then can't load pkgA and emits Config warnings: plugins.entries.<pkgA>: plugin not found: <pkgA> (stale config entry ignored; remove it from plugins config). The same wipe happens on openclaw doctor --fix.
This makes it impossible to have more than one externally-installed @openclaw/* plugin via the CLI — each install resets to a single-plugin state.
Reproduction
Starting from a clean ~/.openclaw/npm/node_modules/@openclaw/ directory:
$ openclaw plugins install @openclaw/discord
Installed plugin: discord
$ ls ~/.openclaw/npm/node_modules/@openclaw/
discord
$ openclaw plugins install @openclaw/acpx@beta
Installed plugin: acpx
$ ls ~/.openclaw/npm/node_modules/@openclaw/
acpx # <-- discord is gone
$ openclaw doctor --fix
Updated ~/.openclaw/openclaw.json
$ ls ~/.openclaw/npm/node_modules/@openclaw/
discord # <-- acpx is gone
$ cat ~/.openclaw/plugins/installs.json | jq '.installRecords | keys'
[
"acpx",
"discord" # <-- both records still tracked, but only one on disk
]
Likely root cause
~/.openclaw/npm/ has no package.json. openclaw plugins install appears to invoke npm install <pkg> (or equivalent) into that directory. With no package.json to anchor a dependency tree, npm treats every package other than the one you're installing as extraneous and removes it. Each subsequent install/repair therefore yields a single-package node_modules. openclaw doctor --fix repeats the same pattern when reconciling the install records.
Workaround
Manually maintain a package.json at ~/.openclaw/npm/ that lists every installed @openclaw/* plugin as a dependency, then run npm install directly:
$ cat > ~/.openclaw/npm/package.json << 'EOF'
{
"name": "openclaw-plugins-install-root",
"version": "0.0.0",
"private": true,
"dependencies": {
"@openclaw/discord": "2026.5.2",
"@openclaw/acpx": "2026.5.2-beta.2"
}
}
EOF
$ cd ~/.openclaw/npm && npm install
$ openclaw plugins enable acpx
$ systemctl --user restart openclaw-gateway.service
After this, both packages coexist and the gateway boots with the full plugin set. The workaround obviously breaks the next time anything calls openclaw plugins install or openclaw doctor --fix, since they presumably overwrite or ignore this package.json.
Suggested fix directions
- Have
openclaw plugins install maintain a package.json (or equivalent dep manifest) in ~/.openclaw/npm/ that reflects all rows in installs.json before running the npm operation, so the targeted package is added but the others stay in the dep tree.
- Or invoke npm with
--no-package-lock and --prefer-offline against a synthesized dep tree that includes every previously-installed plugin, so npm doesn't see anything as extraneous.
- Or stop using a shared
~/.openclaw/npm/node_modules/ for multi-plugin installs, and instead install each plugin into its own directory keyed off the install record.
Related issues
Environment
Symptom
Running
openclaw plugins install <pkgB>after a prioropenclaw plugins install <pkgA>removespkgA's on-disk directory. The install record forpkgAremains in~/.openclaw/plugins/installs.json, but~/.openclaw/npm/node_modules/@openclaw/<pkgA>is gone. The gateway then can't loadpkgAand emitsConfig warnings: plugins.entries.<pkgA>: plugin not found: <pkgA> (stale config entry ignored; remove it from plugins config). The same wipe happens onopenclaw doctor --fix.This makes it impossible to have more than one externally-installed
@openclaw/*plugin via the CLI — each install resets to a single-plugin state.Reproduction
Starting from a clean
~/.openclaw/npm/node_modules/@openclaw/directory:Likely root cause
~/.openclaw/npm/has nopackage.json.openclaw plugins installappears to invokenpm install <pkg>(or equivalent) into that directory. With nopackage.jsonto anchor a dependency tree, npm treats every package other than the one you're installing as extraneous and removes it. Each subsequent install/repair therefore yields a single-package node_modules.openclaw doctor --fixrepeats the same pattern when reconciling the install records.Workaround
Manually maintain a
package.jsonat~/.openclaw/npm/that lists every installed@openclaw/*plugin as a dependency, then runnpm installdirectly:After this, both packages coexist and the gateway boots with the full plugin set. The workaround obviously breaks the next time anything calls
openclaw plugins installoropenclaw doctor --fix, since they presumably overwrite or ignore thispackage.json.Suggested fix directions
openclaw plugins installmaintain apackage.json(or equivalent dep manifest) in~/.openclaw/npm/that reflects all rows ininstalls.jsonbefore running the npm operation, so the targeted package is added but the others stay in the dep tree.--no-package-lockand--prefer-offlineagainst a synthesized dep tree that includes every previously-installed plugin, so npm doesn't see anything as extraneous.~/.openclaw/npm/node_modules/for multi-plugin installs, and instead install each plugin into its own directory keyed off the install record.Related issues
openclaw updateclearsplugins.installsinopenclaw.json. Related but different code path.@openclaw/diffs. Same family of issues (post-install package directory missing).