Writing a Skill Bundle
A skill bundle is the one plugin kind that ships no WebAssembly at all. It is
a directory of markdown skills, packaged and distributed through the plugin
machinery: same manifest, same discovery, same signature policy, same
zeroclaw plugin install. Use it when the capability you are adding is
instructions, prompts, and workflows rather than code, and you want plugin
distribution semantics (signing, registry install, versioning) instead of
loose files in a skills directory.
This guide is checked against the validation path in
crates/zeroclaw-plugins/src/host.rs (validate_skill_bundle,
validate_skill_md_frontmatter) and the loader in
crates/zeroclaw-runtime/src/skills/mod.rs.
For what a skill itself is and how agents use them, read Skills first. This page covers only the bundle packaging.
Layout
A skill-only plugin omits wasm_path and carries a skills/ directory in
agentskills.io format:
my-toolkit/
manifest.toml # capabilities = skill only, no wasm_path
README.md # optional bundle-level overview
skills/
design-review/
SKILL.md
scripts/ # optional
references/ # optional
code-review/
SKILL.md
data-analysis/
SKILL.md
references/
Validation: what discovery enforces
The host validates the bundle shape at discovery and install, and rejects the
whole plugin on the first failure (validate_skill_bundle in host.rs).
The exact rules:
skills/must exist and be a directory.- It must contain at least one subdirectory. An empty
skills/is an invalid manifest, not an empty bundle. - Every subdirectory must contain a
SKILL.md. - Every
SKILL.mdmust open with YAML frontmatter (a---fence on line one, terminated by a closing---), and that frontmatter must declare non-emptynameanddescriptionkeys.
The frontmatter check runs at discovery time on purpose: a bundle whose
skills omit name or description fails when the plugin loads, not when an
agent first invokes the skill mid-conversation.
A valid skill header:
---
name: design-review
description: Structured design review workflow for architecture proposals.
---
# Design Review
...instructions...
Namespacing
Loaded bundle skills register under plugin-qualified IDs:
plugin:<plugin-name>/<skill-name>, e.g. plugin:my-toolkit/design-review
(namespace_plugin_skill in skills/mod.rs). Each skill also receives a
plugin:<plugin-name> tag. This prevents collisions with user-authored
skills and between bundles: two bundles can both ship a code-review skill
and coexist.
The namespacing interacts with skill precedence: in the agent’s effective-skill resolution, same-name skills from different sources are deduplicated by precedence and the losers are recorded as shadowed. The plugin qualifier keeps your bundle out of that fight entirely unless another copy of the same bundle name is in play.
Scripts
A skill may carry a scripts/ directory. Whether script-bearing skills load
is governed by the operator’s skills.allow_scripts setting, which the
plugin-skill loader passes through unchanged (discover_plugin_skills in
skills/mod.rs): a bundle skill with scripts is subject to exactly the same
audit-and-drop rules as a workspace skill. Do not assume your scripts run
just because the bundle installed.
Manifest
The manifest is the file named manifest.toml in the plugin directory. Its
fields are the serde surface of PluginManifest in
crates/zeroclaw-plugins/src/lib.rs, which is the source of truth:
| Field | Required | Meaning |
|---|---|---|
name | yes | Unique canonical package slug and operator config key. Use 1–128 lowercase ASCII characters; start and end with [a-z0-9], with only [a-z0-9._-] between. Discovery rejects invalid or duplicate names. |
version | yes | Version string, e.g. 0.1.0. |
description | no | Human-readable description shown by zeroclaw plugin list. |
author | no | Author name or organization. |
wasm_path | for WASM capabilities | Component file name, relative to the plugin directory. Required unless the only capability is skill. Discovery skips the plugin if the named file does not exist. |
capabilities | yes, non-empty | What the plugin is: any of tool, channel, memory, observer, skill (PluginCapability, serialized snake_case). |
permissions | no | Host services the code may reach: http_client, config_read, file_read, file_write, memory_read, memory_write (PluginPermission). Only the first two are enforced today; the rest are accepted but inert. |
signature | no | Base64url Ed25519 signature over the canonical manifest bytes. Set when signing for distribution. |
publisher_key | no | Hex-encoded Ed25519 public key of the signer. |
Declare only the permissions the code actually uses. An undeclared permission is a host surface the component cannot reach; an unnecessary declared one is attack surface you asked for and audit burden for whoever reviews your plugin.
For a skill bundle: capabilities containing exactly skill, no
wasm_path, and typically no permissions at all; the bundle is data, and
the permission set gates host functions that markdown never calls.
A mixed-capability plugin (say tool + skill) is legal: it must then carry
a valid wasm_path for the tool world and a valid skills/ bundle, and
both validations run.
Install and verify
Each plugin lives in its own subdirectory of the plugins directory (default
~/.zeroclaw/plugins/, resolved through plugins.plugins_dir), holding the
manifest and the component named to match the manifest’s wasm_path:
~/.zeroclaw/plugins/
└── my-plugin/
├── manifest.toml
└── my-plugin.wasm
Install from a local directory (this validates the manifest shape and runs the signature policy before copying anything):
zeroclaw plugin install ./my-plugin/
Enable the plugin system and confirm discovery:
zeroclaw config set plugins.enabled true
zeroclaw plugin list
zeroclaw plugin info my-plugin
A plugin missing from zeroclaw plugin list was skipped at discovery: check
the startup log for the skip warning (malformed manifest, missing wasm_path
file, or signature policy rejection).
After discovery, the skills appear namespaced in the skills surfaces (the
skills list, the dashboard) as plugin:<your-bundle>/<skill>. Ask the agent
to use one to confirm end to end.
Next
- Distributing plugins: a skill bundle is the simplest thing to publish, and the signing story is identical to WASM plugins.