Use a plugin index
For: tenant administrators and plugin authors.
Use a plugin index to find and install plugins by name. Each listed version identifies exact source bytes: a Git commit, the SHA-256 of its packed content and the forge's repository ID. The listing also records the agents, tools and hooks found by the engine, their requirements and their capabilities.
The index hosts no plugin code. The edge installs from the listed source through the usual checks, quality gate and rollout.
https://hub.oz0.ai/index.json (coming soon), is listed on every server, but it is not public yet: this release carries no root key for it, so the server never fetches it. Until then, use an index of your own.Install from an index
oz0 plugin install hub:com.example/[email protected]
Resolved hub:com.example/[email protected] (active) in index acme version 6 to git https://git.example.com/acme/team.git at d81ff07....
Installed team 0.1.0 in tenant default, locked to commit d81ff0790fb5deb423d1ab4cfbf530e02821688f.
- A name is a reverse-DNS namespace and the plugin's own name from its
oz0-plugin.yaml, such asio.github.alice/github-tools. - Without
@<version>, the newest active version installs. - The first trusted index that lists the name wins, in the order
index listshows;--index <name>picks one. --refand--pathdo not apply: the listing pins the commit and the folder. Every other flag ofplugin installworks as for a Git URL.
The server refuses an install when:
| Refusal | Why |
|---|---|
| Another commit | The source resolved to a commit other than the listed one. |
| Other content | The commit's folder, the bundle or the OCI artifact holds files whose SHA-256 is not the content the listing's generated part was made from. What index plugins shows a version may do is always what the installed bytes may do. |
| Another repository | The forge says the repository has another ID than the listing names: it was deleted and created again, maybe by someone else. |
| Withdrawn or quarantined | The index's publisher took the version back. An admin can let such versions through with a warning (index trust <name> --allow-withdrawn). |
| Expired index | The server's copy of the index is past its expiry, and it cannot fetch a newer one. |
A listing may also point at a bundle at a URL, pinned by its SHA-256, or an OCI artifact, pinned by its manifest digest; the server fetches it, refuses other bytes, and installs it as it installs an upload or an oci:// reference. For those, the resolution shows the pinned digest where a Git listing shows its commit.
A deprecated version installs with a warning. The installed plugin is an ordinary Git install: plugin list shows its repository and commit, and the audit log records plugin.hub.resolve with the index, its version and the listing.
The plugin remembers its listing, so plugin update <plugin> moves it to the newest active version the index lists, never to an older one; plugin list and the Plugins page say when there is a newer one. See Update.
See what a plugin may do
oz0 index plugins
PLUGIN VERSION STATUS INDEX SHELL WRITE UNCHECKED CLASHES SOURCE
com.example/team 0.1.0 active acme 0 0 1 - https://git.example.com/acme/team.git@d81ff07...
--json prints each version's listing as the index carries it. What a listing says about a plugin comes from its code and manifest, never from what its authors write. The index keeps of each version what a server reads (what an install shows, the facts and facets, the licence, the digests, the README excerpt and the docs' digests); the rest of the version's listing, marked detail below, is a detail document the index pins by its SHA-256 and size. Servers never fetch it: the hub's plugin pages show it, and plugin inspect --json of the source prints the whole listing.
| Part | What it holds |
|---|---|
| Contents (detail) | Agents with their models, tools and contracts, flows, MCP servers, hooks, skills (with a digest of each skill's files) and harnesses. When the plugin carries a measured listing, each server's functions with their schemas, annotations and an estimate of the tokens each definition costs, and each agent's capability card and the tokens of all its tools |
| Requirements | The oz0 versions, platforms, secrets, the node labels each agent needs, models, and sandbox tier 1 when a webhook flow reaches an agent with a shell |
| Permissions | Shell and write tools of harness agents, egress hosts, secrets and unchecked processes, which an install shows; in the detail, remote MCP servers, packages and which are unpinned, hooks and what they see, flows that outside events start, approvals |
| Unchecked | Processes the engine cannot see into: every MCP server, since inspecting runs no plugin code (a measured listing shows what a server listed on its author's test node, and the first node's snapshot still decides), and harnesses it does not know |
| Evals | Whether its quality gate runs evals, how many cases, and a plugin test report of exactly these files when the index's publisher attached one; the suites themselves in the detail |
| Licence and digests | The licence license: declares, each licence file with what its text reads as, and a status: agree, unrecognised, mismatch, missing or undeclared (the licence checks); the SHA-256 of its content and of its manifest |
| Docs | The README.md, each image it shows from the package (with its type and pixel size), the licence files and the graph of the plugin's parts, each by path, size and SHA-256, and how many Mermaid diagrams the README holds: the files a hub's site shows the README from (the README is the documentation) |
| Uses | The plugins its uses: names, each resolved to its listing in the index, and on the plugin the listings whose versions use it (used_by, at most 200) |
| SBOM | The digest of its SBOM, which inspect writes from its lockfiles, and how many packages it lists; their package URLs in the detail |
| Facts | Its kind (connector, capability, policy or set, or unknown when its manifest says none), the harnesses it provides and how each agent runs, what it asks of models (aliases, the vendors of the models its agents name, whether every agent can run on a local model, MCP sampling), its connections and the hosts it reaches, and each function's type and default |
| Facets | What the facts give for search, such as any-model or harness:codex, and the trust facets the index adds |
| README | The excerpt: the first section of its README.md, reduced to safe Markdown, with the file's digest. The hub's page shows the whole file, from Docs |
Find a plugin by what it needs
oz0 hub search --models any-model --kind connector --connects github
PLUGIN VERSION INDEX KIND MODELS HARNESS CONNECTS TRUST SUMMARY
com.example/gh-desk 1.4.0 acme connector any-model - api.github.com,github publisher-proven,custody GitHub for agents
FACET PLUGINS
any-model 1
kind:connector 1
...
oz0 hub search filters the trusted indexes' plugins by their facets: facts the engine computed from each version's code and manifest, never what its authors write. The server filters and counts, so a search reads only what matches. A plugin matches any value of a flag and every flag given, and after the plugins comes, for each facet, how many plugins the search would hold with that facet added. The text matches the name and the summary; --json prints every page with the counts.
The console's Install dialog has the same search under From an index: filters with their counts, the README excerpt under About, and Choose, which fills the source with the plugin's newest installable version.
| Flag | Facets |
|---|---|
--models | any-model (no agent names a vendor's model or runs at a remote provider), needs:<vendor> (an agent names that vendor's model), local-capable (every agent can run on a local model, and the plugin reaches no host, connection or remote tool), sampling (a server asks for model calls through MCP sampling) |
--harness | The harnesses the plugin provides, and those its agents run on |
--kind | connector, capability, policy, set, or unknown when the manifest says none |
--connects | A connection's name, or a host of its egress list and remote tools |
--platform | An OS of its requires.platforms, any when it names none, and tier-1 when its sessions need sandbox tier 1 |
--function | read, write, sends-out, destructive or unknown: a type at least one of its functions has, in the tool policy's words (what its calls do) |
--permission | shell, write, unchecked, network, secrets, hooks, outside-input, approvals or uses: what the plugin may do on a node, the parts of its permissions that are not empty |
--trust | verified (one of the project's verified plugins, which only the project's own index can say), publisher-proven (the index proved the publisher owns the namespace), custody (the index recorded who published the version, tied to its repository's forge ID), no-advisories (its SBOM is known, and no package in it has an advisory the index carries) |
--tag | A tag its authors give it |
tested:open-models is kept for a measured run that shows a plugin works on open models; nothing sets it yet, since an alias says what a plugin asks for, not that a model does the job.
The trust facets are the index's, signed beside each version's custody, and never part of what inspect computed: index sign refuses a listing whose computed part claims one, and the server and the console read them only from the version, so an index cannot make a plugin look verified by writing it into the listing. For the same reason they ignore tested:open-models in a listing.
Each function in a listing has a type, from its annotations (Read, Write, Sends out, Destructive, or Unknown when it declares nothing), and its default before any rule of yours: what the default tool policy does with it, or Ask, set by the plugin for a function its requires_approval names, which no switch lowers. The Install screen and the hub's plugin page show the same.
Each type at least one function has is a facet too, function:<type>: so oz0 hub search --function read finds plugins with a function that only reads, and --function destructive,sends-out those that may delete something or send something out of the tenant. The console's hub picker shows these types under Permissions, in the tool policy's words, and what the plugin may do on a node (--permission) under May do. A listing inspected before function facets existed has none, so a search by them does not find it until it is inspected again.
A listing's README excerpt is the first section of the plugin's README.md: what follows its title, up to the next heading. Search and the console's Install dialog show it; a hub's plugin page shows the whole README from the files under Docs.
Inspect reduces it to paragraphs, emphasis, code, lists and links to http, https and mailto addresses, at most 2,000 characters. Raw HTML, images, relative links, tables and headings are left out, and an address left as text is escaped so that a renderer with GitHub's automatic links cannot read it as a link, so a CommonMark or GitHub-flavoured reader shows it without running or loading anything.
Related tasks
- Read index version records: Interpret version states, SBOMs and install conflicts.
- Manage plugin indexes: Configure trusted indexes or publish an index of your own.
Previous section links
- Section: advisories
- Section: keys
- Section: listings
- Section: manage the indexes a cluster reads
- Section: offline
- Section: plugins that cannot be installed together
- Section: run an index of your own
- Section: sboms
- Section: the index
- Section: version states