A plugin adds a provider, a client, or a gateway catalog entry to the anypick
you already have installed. It is the answer to “we run our own model endpoint
internally” and “we wrote our own coding agent” without forking the CLI.
Install one
anypick plugin add ./acme-provider # recorded, disabled, digest pinned
anypick plugin list
anypick plugin enable acme-provider # prompts — this is the trust decisionadd never enables. Between the two commands the plugin exists in AnyPick’s
registry and does not run.
off acme-provider 1.0.0 82aae3b7898d
/Users/you/src/acme-providerThe short hex is a SHA-256 digest of the whole plugin package (manifest and every shipped file under the directory), pinned when you added it. AnyPick recomputes it and compares before importing the entry module, so code — including helpers the entry imports — that changed since you approved it never executes.
When the code changes
Pull a new version, or rebuild during development, and the plugin stops loading:
fail acme-provider 1.0.0 82aae3b7898d
Plugin acme-provider has changed since you trusted it.
→ anypick plugin trust acme-providerNothing else breaks — the rest of AnyPick works normally, and anypick doctor
reports the refusal. Review the diff, then re-pin:
anypick plugin trust acme-providerThis is intentional friction, not a cache miss. The digest is what you approved.
Turning plugins off
anypick plugin disable acme-provider # keep it installed, stop loading it
anypick plugin remove acme-provider # uninstall
ANYPICK_NO_PLUGINS=1 anypick doctor # skip every plugin for one runThe environment variable is the fast way to tell a plugin bug from a AnyPick bug.
Writing one
A plugin is a directory with a anypick.plugin.json and an ESM entry module:
{
"name": "acme-provider",
"version": "1.0.0",
"apiVersion": 1,
"main": "dist/index.mjs"
}export default {
activate(ctx) {
ctx.registerProvider(new AcmeProvider());
},
};activate is synchronous and runs during startup, in the same window where
AnyPick’s built-in providers register and immediately before the registries are
sealed. Register everything there; the context is not usable afterwards.
ctx is deliberately narrow — registerProvider, registerClient,
registerCatalogProvider, and nothing else. There is no database handle, no
store, and no data root, so a plugin extends the composition graph without
receiving a general capability to read the accounts that graph manages.
main must resolve inside the plugin directory; an absolute path or one that
escapes with ../ is refused. apiVersion is checked against the version this
AnyPick build supports, so a mismatched plugin is refused with a version message
rather than a stack trace.
The Provider, ClientAdapter, and CatalogProvider interfaces are exported
from the package root, and the contributor guide covers what a good provider
implements — particularly its model policy, which is what keeps your provider
from inheriting another vendor’s model ids.