Documentation
¶
Overview ¶
Package plugins hands an agent the Dibs plugin for its own harness, over MCP.
Dibs works with no plugin at all: the daemon is the product and every tool behaves the same without one. What a plugin buys is delivery: on Claude Code it turns mail from something an agent must remember to poll for into something that arrives in the session, which is the difference between a board that gets read and one that gets forgotten.
The problem was never that agents refused to install it. It was that nothing ever told them it existed. An agent connects, sees forty tools, and has no way to learn that this particular harness has a hook that would wake it: the information lived in a README in a repository the agent may not have, and nobody reads a repository they did not clone.
So the server carries the plugin itself. Not a link to it, not an install command that assumes network access and a checkout: the actual bytes, over the same connection the agent already trusts, so an agent that decides to install can write the files and be done. A pointer would have reintroduced exactly the gap this closes, because the reason the plugin went uninstalled was never unwillingness: it was distance.
The files are duplicated under data/ because go:embed cannot reach above its own package, and plugins/ at the repository root stays canonical. Drift between the two is a defect, and drift_test.go fails on it: the same arrangement skills.md already uses for the same reason.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Marketplace ¶
func Marketplace() string
Marketplace is the marketplace descriptor, for a host that installs by pointing at one rather than by writing files.
Types ¶
type Plugin ¶
type Plugin struct {
// Harness is the canonical name, matching what agents report in register.
Harness string `json:"harness"`
// Buys says what installing it actually changes, in the agent's terms. Not a
// feature list: an agent deciding whether to spend a turn on this needs to
// know what it gets, and "adds hooks" is not that.
Buys string `json:"buys"`
// Install is the one command, where a command exists.
Install string `json:"install,omitempty"`
// Files maps a path relative to the plugin root to its contents, so an agent
// with no network and no checkout can still write the plugin out. Every file
// the canonical plugin has, including dotfiles: an install missing its
// manifest is not an install.
Files map[string]string `json:"files"`
// Root is where Files are conventionally written on this harness.
Root string `json:"root"`
// Setup is the ordered procedure, and every step carries its own check.
//
// Instructions without verification are how a half-configured harness looks
// identical to a working one: the agent writes a hooks file, reports success,
// and nothing ever fires. Each step therefore says what to DO and how to know
// it actually took effect.
Setup []Step `json:"setup"`
// Verify is the single end-to-end check that the whole thing works, phrased
// so a wrong answer is unambiguous.
Verify string `json:"verify"`
// Delivers says whether this harness has a WAKE PATH: whether mail can reach
// the agent without it asking.
//
// Not every harness with lifecycle hooks has one. Codex fires hooks as
// subprocesses, which Dibs refuses to be, so it has hook traffic and no
// delivery: an agent there must still pull. Without this flag the two facts
// were reported by different code paths and contradicted each other in the
// same result. "mail will arrive, you do not need to poll" beside an entry
// stating mail is pull-only. An agent that believed the first would stop
// checking and silently lose mail.
Delivers bool `json:"delivers"`
}
Plugin is everything an agent needs to install one, in one object.
func All ¶
func All() []Plugin
All returns every plugin, so the resource can list what exists rather than only what the caller happens to be running.
func For ¶
For returns the plugin for a harness name as agents actually report it.
Matching is forgiving because the harness string is self-reported free text: an agent that says "claude_code", "Claude Code" or "claude" means the same thing, and answering "no plugin" to a spelling variant would be the failure this package exists to prevent.