CodeMem uses one shared semantic version stream across its npm packages.
- npm:
codemem(CLI) - npm:
@codemem/opencode-plugin(OpenCode plugin) - npm:
@codemem/pi-extension(pi coding-agent extension)
- Release tags
vX.Y.Zrepresent the product version. - npm packages publish the same
X.Y.Z. - GitHub Release notes are shared per version.
Keep notable changes in the root CHANGELOG.md, following Keep a Changelog: collect pending entries under Unreleased, group them by Added, Changed, Deprecated, Removed, Fixed, or Security, and move them under a dated version heading in the release PR. Omit empty categories, link versions to tag comparisons, and include compatibility or migration details when needed. Do not create per-version release-note documents or copy release announcements into the changelog.
GitHub release announcements remain separate. The release workflow uses GitHub's generated PR list, contributor credits, and comparison link, configured by .github/release.yml; a human summary can be added to the GitHub release after publication. The comparison link shows the changes between tags, not a curated changelog. Retrying an older tag does not require changelog tooling in that tagged checkout.
Version bumps are prepared on main. A maintenance version bump is prepared through a PR into the matching release/X.Y branch and touches these files:
packages/core/package.json(version)packages/embeddings/package.json(version)packages/cli/package.json(version)packages/opencode-plugin/package.json(version)packages/pi-extension/package.json(version)packages/mcp-server/package.json(version)packages/viewer-server/package.json(version)packages/core/src/index.ts(VERSIONexport)packages/core/src/index.test.ts(version assertion)packages/cli/.opencode/plugins/codemem.js(PINNED_BACKEND_VERSION)packages/opencode-plugin/.opencode/lib/runtime.js(PINNED_BACKEND_VERSION).claude-plugin/marketplace.json(marketplace metadata version and codemem plugin entry version)plugins/claude/.claude-plugin/plugin.json(Claude plugin metadata version and exact MCP--packagepins forcodememand@codemem/embeddings)plugins/codex/.codex-plugin/plugin.json(Codex plugin metadata version; also pins thenpx -y codemem@<version>fallback used by Codex hook scripts)plugins/codex/.mcp.json(exact MCP--packagepins forcodememand@codemem/embeddings)
Both checked-in MCP launchers use the shared release version for both packages, including
prereleases. Plugin metadata alone does not select an npm version: unversioned package specs
resolve the registry's latest tag, which may still point to the previous stable release.
The release helper checks these four pins and repairs unversioned specs even when the
manifest already has the target version. It changes only the package specs in launcher
arguments; the plain codemem mcp executable, timeouts, and unrelated arguments stay intact.
Malformed launchers fail validation before any managed files are written. These pins apply
only to the shipped Claude and Codex launchers, not user CLI setup or global configuration.
Use the release version helper to verify or apply the bump:
pnpm run release:version -- checkpnpm run release:version -- set X.Y.Z
Regenerate release artifacts before opening the release PR:
pnpm install(lockfile and generated artifacts when applicable)pnpm build(viewer UI bundle/assets)
Keep .opencode/.npmrc pinned to the public npm registry:
registry=https://registry.npmjs.org/
npm sets latest on a package's first-ever version regardless of --tag. A new package whose debut is a prerelease therefore exposes that prerelease to untagged installs (npm install <pkg>).
The release workflow cannot fix this automatically: OIDC trusted publishing grants publish only, not dist-tag mutation. Instead, a post-publish step runs scripts/release-latest-guard.mjs in verify mode and reports any package whose latest points at a prerelease. Attempt the cleanup from a machine with an npm login:
node scripts/release-latest-guard.mjs --apply <package>The guard only removes; it never adds or moves latest, so an established package's stable latest is untouched. npm may reject removal when the prerelease is the package's only latest version; in that case, keep prerelease installs on explicit channel tags until the first stable release moves latest. The verify step is continue-on-error while any package is still dirty; flip it to a hard gate once the guard reports clean.
Before creating or pushing a release tag, run:
pnpm run release:preflight-tagThis verifies release tagging safety in two contexts:
- local preflight accepts a clean
maincheckout only whenHEADequals the freshly fetchedorigin/mainHEAD. It also accepts a cleanrelease/X.Ycheckout only whenHEADequals the freshly fetchedorigin/release/X.YHEAD and the package and tag versions share thatX.Yseries. - CI tag workflow accepts a tagged commit that is reachable from remote
main, or from the exact remote branchrelease/X.Ymatching theRELEASE_TAGmajor/minor series. The branch may have advanced since the tag was pushed. WhenRELEASE_TAGis supplied, its version must equal the core package version at the tagged commit.
Cached remote-tracking refs do not authorize a missing remote branch. Feature branches, unmerged commits, stale branch heads, and release branches for another version series fail preflight. The maintenance branch name is exact: use release/0.47, not release/0.47.0.
For a stable release, merge the release PR into main, verify that HEAD is the merged release commit, and then tag it. For a maintenance release, prepare aligned versions in a PR targeting the matching release/X.Y branch. After the PR passes CI and merges, update that branch locally, run preflight, and tag the merged commit.
After a successful stable vX.Y.0 publication, the workflow creates release/X.Y at the tagged commit when that branch is absent. It never moves an existing branch and does not create branches for patch or prerelease publications. This automation starts with the updated workflow. It does not apply retroactively to existing branches, including the separately created release/0.47 branch.
When a higher stable version is already tagged, an older maintenance release publishes under the npm tag maintenance-X.Y and is not marked Latest on GitHub. For example, after v0.48.0 is tagged, v0.47.4 publishes under maintenance-0.47 so it does not move npm's latest backward. Install that maintenance version explicitly or use its series tag.
Run stable releases one at a time across version series. Finish the newer stable release before tagging an older maintenance release so its workflow sees the newer tag when choosing an npm channel.
Stable publication requires the tagged checkout to contain the history-aware dist-tag helper. A retry of an older stable tag without that helper stops before publishing packages. Prepare a new maintenance release with the updated tooling rather than moving an existing tag.
codemem update check derives the release channel from the installed version and queries the fixed
public npm registry endpoint for the matching dist-tag: alpha uses alpha, beta uses beta, release
candidates use rc, and a stable version uses latest. Registry responses, status output, guidance,
and cache records must
match that channel. Results are cached locally for six hours; use --refresh to bypass a fresh cache
and --json for the additive automation contract. Existing stable-only cache records remain valid
for stable installations, but no cache or in-process result is reused across channels. If a refresh
fails, a previously validated same-channel cache may be returned as stale guidance. A running process
backs off failed registry checks for 15 minutes, while --refresh bypasses that backoff.
codemem update check remains informational. It detects a semver-qualified
mise/installs/npm-codemem/<version>/ layout from the resolved CLI entry path, or the equivalent
layout beneath a normalized MISE_DATA_DIR, and reports
mise use -g npm:codemem@<exact-version> for that installation kind. It also recognizes canonical
pnpm global virtual-store entries from resolved paths and reports the exact paired
pnpm add -g codemem@<exact-version> @codemem/embeddings@<exact-version> command. Those path markers
do not prove pnpm package ownership.
codemem update install separately requires fresh validated status. Proven npm-global installations
retain the 24-hour first-seen delay and install exact matching codemem and
@codemem/embeddings versions with an argv-only npm command. Before mutation, proven mise
installations compare bounded machine-readable active and global source records and require current
install-path ownership. A recognized user-level ~/.config/mise.toml source may migrate when the
bounded global query succeeds with an empty result. The matching source must resolve within the user's home directory; system,
unresolved, and ambiguous custom paths fail closed. Matching evidence authorizes codemem to
execute the exact reported mise use -g command without a shell, inherited environment, and pinned
public default and @codemem registries; Linux also sets ONNXRUNTIME_NODE_INSTALL=skip. This writes
the exact release into the primary global config, so a declaration may move from user conf.d or ~/.config/mise.toml to
config.toml. Mise verification re-reads bounded global state, requires an exact target version or
requested_version value, and runs mise exec -- codemem version outside the invoking project;
npm-global verification uses the active CLI.
For pnpm-global installations, the explicit installer uses bounded, no-shell pnpm root -g,
pnpm bin -g, and pnpm list -g --depth 0 --json calls from a neutral directory immediately
before mutation. It requires pnpm root -g to equal the list root (pnpm 12) or its node_modules
directory (pnpm 9–11), the canonical registered Codemem package to remain under that list root, and that package
to own the resolved JavaScript entry. It then installs exact matching paired packages using public default and scoped registry flags
and verifies exact registered package versions plus the specific pnpm-bin launcher. The updater never runs a build-approval command;
pnpm 9 still runs install scripts by default, while newer releases apply their configured build-script policy.
Bare codemem update remains non-mutating. Installing an alpha, beta, or release candidate is
explicit opt-in, so the
existing auto-update policy may install a delayed eligible update within that installed channel.
Installation refuses pinned, cross-channel, unsupported-prerelease, downgrade, development, stale,
Docker, and unknown states. The npm-global updater always installs exact matching codemem and
@codemem/embeddings versions. The npm operation runs the packages' installation scripts for native
CPU dependencies, just as a manual global install does.
Mise remains ineligible for background auto-update because its command changes declarative global
tool configuration; only a direct user install command may authorize that change, and a local source
that overrides the global source is refused with manual global-update guidance. pnpm-global is also
never eligible for plugin background auto-install; it supports notifications and the direct
codemem update install path only.
Release discovery compares the running product version with the latest release on its channel. It is separate from the compatibility-floor check below: discovering a newer release does not change whether the current CLI satisfies the plugin's minimum supported version.
The OpenCode 1 plugin performs a runtime CLI version check and warns if the local CLI is below
CODEMEM_MIN_VERSION (default 0.9.20).
The compatibility reaction is controlled by CODEMEM_BACKEND_UPDATE_POLICY:
notify(default): warn with an upgrade hintauto: attempt a best-effort same-channel update for eligible npm runners and delayed releases, then re-checkoff: suppress compatibility toasts
This check enforces a minimum supported CLI version. It does not query the npm registry or report the latest available release, and its existing policy and update behavior are unchanged by release discovery.
Codemem 0.45 raises the minimum supported OpenCode 1 host to 1.18.29. The
@codemem/opencode-plugin package records this floor through
engines.opencode, which OpenCode checks when loading npm plugins, and CI runs
the V1 plugin suite against that exact SDK release. The packed-artifact smoke
also installs OpenCode 1.18.30 and requires the dual entrypoint to complete the
host's non-pure startup path. The package default export changes from a callable
V1 plugin function to the documented dual-host object; named V1 exports remain
available for integrations that invoke the function directly.
This is a breaking host-compatibility change from Codemem 0.44; upgrade OpenCode
before installing the 0.45 plugin.
Dependabot continues to propose SDK updates, but accepting one requires updating
all checked-in SDK pins together. The published dependency and both nested
runtime manifests use the same exact SDK version; that version can be newer
than the supported host floor. CI explicitly installs the minimum SDK with
--no-save and keeps the minimum host gate and engines.opencode fixed at
1.18.29 until the documented compatibility floor changes. The ignored
.opencode/package.json is only a local contributor runtime and is not a release
pin. Refresh it when testing the minimum host locally:
npm install --prefix .opencode --save-exact @opencode-ai/plugin@1.18.29The same 0.45 package also runs on OpenCode 2 through its setup() entrypoint.
Codemem validates that path against the exact stable @opencode/cli@2.0.24 and
@opencode/plugin@2.0.24 releases and labels its OpenCode 2 integration beta.
codemem setup --opencode-only keeps writing the singular plugin key because
OpenCode 1 requires it and OpenCode 2 translates it. Required CI gates run only
against the 1.18.29 floor and the exact 2.0.24 pin; any compatibility run against
a newer or moving OpenCode release is advisory and never blocks a Codemem change
until the pin moves in its own reviewed PR. Rollback is a host-edge change:
disable the V2 path with CODEMEM_PLUGIN_IGNORE=1 or return to OpenCode 1
without any database migration.
The OpenCode 2 contract separately pins matching @opencode/cli@2.0.24 and
@opencode/plugin@2.0.24 packages. The workspace
allows the CLI package's postinstall because it installs the matching platform
binary used by the packed-host smoke test. The 2.0.24 postinstall is byte-identical
to the independently reviewed 2.0.2 script. It selects an exact optional platform package, detects AVX2 support with
sysctl on macOS or PowerShell on Windows, and hard-links or copies its binary.
If the optional package is absent, it installs that exact package in a temporary
directory before copying and verifying the binary. Re-review the postinstall
whenever the exact pin changes. Update both revisions together and rerun the
executable checks documented in the OpenCode 2 contract;
do not replace these pins with a moving tag or semver range.
The approved minimum-release-age exception covers only the exact OpenCode 2.0.24
packages listed in pnpm-workspace.yaml. Remove those exceptions once the
versions clear the configured release-age window.
Override for testing:
export CODEMEM_MIN_VERSION=0.9.20Codemem requires Pi 1.1.0 or newer, below 2.0. The @codemem/pi-extension
package records this floor as its declared host peer
(@earendil-works/pi-coding-agent >=1.1.0 <2). This is a breaking
host-compatibility change from the previous >=0.84.1 <1 peer: Pi 0.x hosts
must upgrade before installing. pi update replaces the Pi host;
pi update --extensions only reconciles installed packages. A Nix installation
cannot update itself with pi update; use the official installer flow or
nix profile upgrade pi. Native tools stay the setup default with 15 memory_*
tools, and the explicit native and mcp-adapter modes are unchanged.
codememis the CLI package on npm.@codemem/opencode-pluginis the OpenCode plugin identifier.