Bind a plugin to an event

bind, unbind, grants, filters, and what enforcing mode blocks.

Written By Dustin

Last updated 29 minutes ago

tovio plugin bind <id> --event pre-snapshot --mode advisorytovio plugin bind <id> --event pre-land --mode enforcing --requiredtovio plugin unbind <id> --event pre-landtovio plugin bindings

A bind is refused if the plugin's manifest does not declare the event, or if the event is unknown — TVO-PLUGIN-004. By default the binding is pinned to the installed version, which is what you want for anything enforcing.

The full bind surface

FlagWhat it does
--eventThe lifecycle event. Required.
--mode advisory|enforcingWhether the plugin can gate at all. Required.
--requiredAn enforcing binding also blocks when the plugin errors, skips, or reports unsupported — not only on fail.
--paths <glob>Fire only for matching changed paths. Repeatable; empty means all.
--branches <glob>Fire only on matching lanes or refs. Repeatable; empty means all.
--grant <cap>Grant one capability on this binding. Repeatable.
--grant-read-path <glob>Grant a clear read path glob — the read_clear_paths capability. Repeatable.

Marking an advisory binding required is recorded but changes nothing: advisory never blocks.

The capability intersection

A plugin gets the intersection of what its manifest requests and what the binding grants — never more. Asking for something outside that intersection is TVO-PLUGIN-005.

This means the binding is where you actually control a plugin. A manifest requesting network access does not get it unless the binding grants it too, and a binding cannot widen a manifest that never asked. Both halves must say yes.

One capability is not flag-grantable at all. Passing --grant read_protected_plaintext is refused with TVO-PLUGIN-013 and nothing is written — that capability needs a five-condition approval chain, not one token on a command line. The refusal is on purpose: silently dropping the request would look like it had been granted.

Advisory first

Run it advisory for a while. An enforcing plugin that misfires blocks everyone's work, and a plugin that has never run against real content has not been tested.

Timeouts and limits

Plugins run under a fuel budget, a wall-clock deadline, and a memory ceiling. A runaway guest is terminated with TVO-PLUGIN-007 rather than hanging your commit.

Output is validated

Output failing schema validation is coerced to errorTVO-PLUGIN-008 — never to a pass. A result claiming a different plugin id or event than the one that ran is treated the same way.

Seeing what is bound

tovio plugin bindingstovio explain plugin --event pre-land

bindings lists the local binding store, and labels every row LOCAL — a local binding is not a repository, organisation, or Forge policy gate. explain plugin reconstructs what would run for an event, read-only, without executing anything.

On a Forge

A local binding is one person's choice on one machine, which is why every row is labelled LOCAL. Server-side enforcement is a separate mechanism: an organisation allow and deny policy decides which plugins may back an enforcing gate at all, and a proposal transition naming a denied plugin is refused with TVO-PLUGIN-014.