Plugins¶
Plugins are the only extension mechanism in Samuel v2. There are no first-class language, framework, or workflow concepts in the framework itself — everything is a plugin.
Three tiers¶
| Tier | What it is | When to use |
|---|---|---|
| skill | Text + scripts (a SKILL.md plus optional scripts/, references/, assets/) | Static prompts, conventions, idiomatic snippets. The majority of plugins. |
| wasm | A WASM module compiled with TinyGo, sandboxed by wazero. Pure Go runtime — no host deps. | Translators, validators, formatters, anything CPU-bound that needs to be cross-platform and trustworthy. |
| oci | An OCI image run by Podman / Docker, talking to Samuel over a Unix-socket gRPC bridge. | Heavy tools — language servers, headless browsers, GPU workloads, anything with native deps. |
Decision tree: prefer skill if static text suffices. Step up to WASM if the plugin needs compute (parse, walk, render) but can run pure Go. Step up to OCI only when you need native libraries, a specific language runtime, or hardware access.
A fourth pseudo-tier is meta — a plugin with kind = "meta" and a [requires] block that installs other plugins. The samuel-starter pack is the canonical meta plugin.
Lifecycle¶
Every plugin implements four methods (the v2 Plugin interface, ported from v1's Component):
| Method | Called by | Contract |
|---|---|---|
Manifest() | always first | returns parsed samuel-plugin.toml |
Install(ctx, env) | samuel install, samuel init | writes files, returns mutation log |
Check(ctx, env) | samuel doctor | returns healthy/unhealthy + reason |
Uninstall(ctx, env) | samuel uninstall | reverses the mutation log |
The orchestrator replays the mutation log on uninstall — plugins don't need to re-detect what they installed. See RFD 0005.
Capability model¶
Every plugin declares the capabilities it needs in [capabilities]. The install path classifies them as safe-default (no prompt) or risky (interactive prompt unless --yes).
| Capability | Risky? |
|---|---|
filesystem.read:/workspace/** | safe-default |
filesystem.read:/workspace/<specific path> | safe-default |
filesystem.read:<anywhere outside /workspace> | risky |
filesystem.write:** | always risky |
exec | risky |
network.outbound:<host> | risky (host pattern) |
samuel.api | risky |
assistant.invoke | risky |
Non-interactive shells (--non-interactive) fail closed on risky capabilities. See Capabilities.
Where plugins live¶
| Path | Scope |
|---|---|
<project>/.samuel/plugins/<name>/ | project-local (default) |
~/.samuel/plugins/<name>/ | user-global (opt-in) |
~/.samuel/builtins/ | embedded built-ins (ralph, create-skill, sync, generate-agents-md) |
~/.samuel/cache/wasm-compiled/ | wazero compile cache |
~/.samuel/cache/registries/<host>/ | registry index cache, 24h TTL |
samuel.lock¶
The lockfile records what's installed, at what version, with what signature digest, and the mutation log produced by Install. It is machine-managed — never edit it by hand. samuel install, samuel update, and samuel uninstall mutate it under the project file lock. Commit it like you commit go.sum or package-lock.json.
Built-in plugins¶
Four plugins ship inside the binary and are installed by samuel init:
ralph— the methodology runtime (the autonomous loop)sync— the per-folder AGENTS.md walkercreate-skill— interactive scaffolder for new skill pluginsgenerate-agents-md— the template renderer
They live at ~/.samuel/builtins/ with content-hash idempotency: samuel doctor --fix rewrites them when they drift from the binary's embedded copy.