The change is in register_models(), the hook plugins use to add new models to llm. It [now receives a model_aliases parameter](https://github.com/simonw/llm/releases/tag/0.30): a list of every model and alias already registered by other plugins. The critical detail is what that enables. A plugin marked @hookimpl(trylast=True) — a pluggy decorator flag that says "run after everyone else unless someone explicitly asks to go last" — can now inspect that list and override it. A plugin can look at what every other plugin registered, then replace it.
That is a genuine extension point. Not "we added a new model option" or "we improved the temperature setting." A plugin can now surgically replace a model registration that another plugin installed. The use case Willison describes in the release notes is routing: a plugin that wants to say "for enrichment tasks, always use GPT-4.1-mini" can see what other plugins registered and ensure its own preference wins, without hardcoding model names or patching plugin internals. The dependency graph resolves at registration time, not at call time.
The model_aliases parameter is documented on the llm plugin hooks page, which is itself a consequence of the other 0.30 change: added docstrings to public classes and methods, included directly in the documentation. That is the kind of change that sounds trivial until you try to build a plugin for a tool where the API surface is undocumented and you are reverse-engineering from examples.
The purposes system is the other thread worth pulling. On March 25th, Willison released datasette-llm 0.1a1, a plugin for using llm models from within Datasette. It introduced a new hook: register_llm_purposes(). Plugins that want to route models by intent — "use this model for SQL queries, that model for data enrichment" — can register their purpose strings in one place. Future plugins can list those purposes and power an admin UI for assigning models to purposes. The hook is not in llm core yet; it shipped via a plugin first. But the pattern is established: plugins define purpose strings, other plugins read them, something provides an interface on top.
This is how conventions become infrastructure. Nobody voted on it. There is no IETF working group. There is a person who writes clear code, publishes honest release notes, and maintains a plugin directory at llm.datasette.io. The plugins — llm-fragments-pdf, llm-gemini, llm-anthropic, llm-ollama, and dozens of others — accumulate because the extension interface is stable enough to trust and documented well enough to use.
That stability is itself notable. The pluggy system that powers llm's hooks is the same system Datasette uses, which is the same system Willison has used across multiple projects. He is not inventing a plugin interface for each project; he is reusing one. When a developer learns how plugins work in llm, they work the same way in Datasette. The conventions compound.
What the 0.30 changes actually do is move llm's plugin model further from "plugins add features" and closer to "plugins configure behavior." The model_aliases override mechanism is not about adding a new model — it is about priority and routing. The purposes system is not about a single plugin's capability — it is about cross-plugin coordination. These are infrastructure concerns. They are the concerns of a system that has accumulated enough users and plugins that the question is no longer "can I add what I need" but "who wins when two plugins want different things?"
The honest framing is that this is still a small ecosystem. llm is a CLI tool, not an enterprise platform. The plugin directory is curated, not sprawling. But CLI tools become wrappers become wrappers become defaults, and defaults become the substrate that other things build on. Willison's changelog for 0.30 is two bullet points. Neither mentions standards. Both of them are.
† Consider adding a source link to the plugin directory at llm.datasette.io to support the ecosystem claim, or revise to hedged language such as 'plugins including llm-pdf, llm-github-models, and others have accumulated…'