Skip to the content.

Publishing & updates

← Back to index

There is no registry and no repository manifest. A plugin is published the moment its repository is reachable over https:// with a valid plugin.json, main.ts and a current plugin.sig at the root. Users install it by pasting the repository URL into the Plugins tab; the bridge clones the default branch and compiles it.

What to push

plugin.json        the manifest
plugin.sig         the signature over everything else (see Signing)
main.ts            default-exports definePlugin({...})
src/**             optional, imported from main.ts
README.md          optional

A repository without a valid plugin.sig cannot be installed or updated. Sign every release and commit the signature; see Signing plugins for the one-off key and the GitHub Actions step.

Nothing is built on your side and there is no dist/ to commit. The bridge imports main.ts as TypeScript straight from the clone, so what users run is what is in your default branch. Any dependency must be committed into the repository — the bridge runs no package manager — and it is scanned by the source policy like your own code.

Run the template’s npm run check before pushing. Its ESLint config flags most policy rules locally, and a repository that fails the policy or the manifest schema is refused at install with the file, line and rule, which is a poor first impression. The plugin system’s protocol check is worth running too: it catches an action, event, argument or selector VRCNext does not have.

Supported repository URLs

Any https:// git remote the bridge can clone anonymously: GitHub, a self-hosted Gitea or Forgejo, GitLab. No shorthand, no /tree/<branch> suffix — the bridge clones the remote’s default branch, depth 1. To ship from a specific branch, make it the default branch of that repository.

How updates reach users

Nothing is automatic. The manager checks for updates when the user opens it or presses the button: the bridge fetches each clone’s origin and reports how many commits it is behind, with a changelog of commit summaries (up to 50; a clone is shallow, so a count of 50 means “at least”). The user presses Update (or Update all), confirms on the desktop — one prompt per plugin — and the bridge clones afresh, re-validates the manifest and the policy, swaps the new tree in only if it passes, rebuilds, and the page offers Reload. There is never a merge, and a failed validation leaves the old tree exactly as it was.

Consequences:

apiVersion

apiVersion is checked before activation. If the host’s @vrcnext/plugin-api version does not satisfy your range, the plugin is refused with a message naming both versions. Only exact versions, ^, ~ and comparator lists (>=0.2.0 <0.4.0) are accepted — see plugin.json. Widen the range only when you have actually tested against the newer API.

Updating the host itself

The host is compiled into the bundle from sources the installer placed under ~/.vrcnext-plugins/host/. Re-running the installer is an upgrade: it replaces the bridge, the pinned esbuild and the host sources, keeps your plugins, state and token, and rebuilds. The page does not check for host releases on its own.

← Using TSX · Security model →