anomalyco / anomalyco/opencode
opencode plugin <name> --global serves a stale previously-resolved version after the package publishes a new one (v1.18.31)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Environment: opencode 1.18.31, Linux
Problem: I published opencode-token-min@1.0.1 (registry latest = 1.0.1, verified via npm view opencode-token-min). Re-running opencode plugin opencode-token-min --global --force kept installing 1.0.0 — the version resolved by an earlier install — with no error or warning. The plugin manager then showed a plugin under its old id (token-min:sidebar-context) instead of the new one, because the cached tree was what actually loaded. Only deleting ~/.cache/opencode/packages/opencode-token-min* and then installing the pinned spec opencode-token-min@1.0.1 fixed it.
Root cause (packages/core/src/npm.ts):
const add = Effect.fn("Npm.add")(function* (pkg: string) {
const dir = directory(pkg) // path.join(global.cache, "packages", sanitize(pkg))
const name = ...
if (yield* afs.existsSafe(path.join(dir, "node_modules", name))) {
return resolveEntryPoint(name, path.join(dir, "node_modules", name))
}
const tree = yield* reify({ dir, add: [pkg] }) // only registry call
...
})
Npm.add returns the existing node_modules/<name> without ever consulting the registry or lockfile when it's present. So for a given spec, nothing invalidates the resolved version — not --force, and not a new publish. The lockfile is a known footgun (your which() deletes package-lock.json before retrying), but the node_modules short-circuit sits upstream of that.
Note: because the cache directory is keyed by the full spec string (packages/scoped/opencode-token-min@latest), installing a different spec (name@1.0.1) works and creates a fresh dir — so the stale copy only hides when the user re-runs the same spec (e.g. the bare package name), which is what the docs and manager prompts point users at.
Expected: --force (or a dedicated update path) re-resolves the registry and installs latest; at minimum a warning like "already at 1.0.0; run opencode plugin packagename@x.y.z to change version".
Proposed fix: make --force clear the package dir (or at least node_modules/lockfile) before reify so resolution is re-run; keep the short-circuit for the idempotent non-force path.
Note: this debugging was performed by Big Pickle (opencode agent), under the supervision of @tmiland.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/core/src/npm.ts at Npm.add, then trace how the plugin command passes --force into package installation. Verify the existing node_modules short-circuit and reify behavior, including the cache directory and lockfile handling. Done means forcing the same package spec re-resolves the registry version, while the non-force path remains idempotent.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100