OpenCode provider plugin (@brainervirus/opencode-commandcode). Ships a bundled model catalog (models.json) extracted from the minified command-code npm CLI. CI does the extracting — never hand-edit models.json, manifest.json, or _version.txt.
Layout: src/ = runtime plugin + catalog engine (product, release-gated). scripts/ = CI tooling (not published, not release-gated). tests/unit/ = the only suite bun run check runs.
bun run check— the CI gate:oxlint --deny-warnings+oxfmt --check+bun test tests/unit/+tsc --noEmit. Run before every PR.- Single file:
bun test tests/unit/catalog.test.ts - Refresh catalog locally (writes
models.json,_version.txt,manifest.json):bun run sync -- --remote
On 2026-09-02 this repo published 42 accidental npm versions (0.7.5→0.7.46) from an infinite loop. The rules below exist to prevent that. Do not relax them.
- Releases are path-gated (
scripts/analyze-release-scope.ts): a commit counts only if it touches a product path —plugin.ts,index.ts,models.json,manifest.json,_version.txt, orsrc/. CI/docs/tests/scripts-only merges never release. - Only
fix|feat|perfcommit subjects can cut a release.chorenever releases — not evenchore(scope). The post-release automation commitschore(release): sync manifests to vXtouchingpackage.json+manifest.json(both product paths): making anychorereleasable turns each release into the trigger for the next one — release → sync PR → merge → release → … - The intended release path for catalog updates is the automation's
fix(catalog): sync command-code@Xcommit (patch). Do not rename it tochore(catalog). package.json/manifest.jsonversion fields are written by automation only; don't bump them in feature PRs.
- It slices balanced
{…}spans around the anchorSONNET_4_6:{id:"claude-sonnet-4-6"and evals them with string bindings collected from the 12k chars before the anchor (extractStringBindings). - Minified identifier names are not stable across
command-codereleases. 1.40.x introduced$-prefixed vars ($R="vercel-ai-gateway");\bregex boundaries never fire before$(not a word char) — use(?<![A-Za-z0-9_$])lookbehind instead. Same for alias resolution. - Symptom of a new bundle shape:
Could not evaluate model catalog— every candidate span threw and errors were swallowed. To debug: download the tarball (https://registry.npmjs.org/command-code/-/command-code-<v>.tgz, bundle isdist/cli.mjs), eval candidates manually with the same context, and surface the real ReferenceError (usually a missing binding, e.g.$R is not defined). - Every extraction fix ships with a regression test in
tests/unit/catalog.test.tswhose fixture mirrors the new minified shape.isModelCatalogrequires ≥2 model entries — single-model fixtures fail.
catalog-sync.yml: every 6h + manual dispatch. Extractscommand-code@latest, opens afix(catalog)PR (branchchore/catalog-sync) that auto-merges when the fivecheck *jobs pass. On extraction failure it opens/updates a catalog-break issue — labelscatalog-breakandautomationmust exist on the repo (recreate withgh label createif missing).release.yml: semantic-release on every push tomain(npm publish + tag + GitHub Release), then opens thechore(release): sync manifestsPR which also auto-merges.mainis protected (5 required checks). Never push tomain— open a PR and let auto-merge handle it.workflow_dispatchalways runs a workflow frommain, never a PR head. Dispatching does not test your branch.- Secrets:
NPMJS(npm Automation token, mapped toNPM_TOKEN/NODE_AUTH_TOKEN— a login token fails withEOTP),RELEASE_SYNC_TOKEN(PAT; PRs opened withGITHUB_TOKENdo not trigger CI runs on their branch).