anomalyco / anomalyco/opencode

opencode plugin <name> --global serves a stale previously-resolved version after the package publishes a new one (v1.18.31)

Open
#49,970 1 comment 0 reactions 0 assignees View on GitHub

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.