What You’ll Build
This guide walks through creating a new capability from scratch. By the end, you’ll have a working capability that Wolffish discovers, loads, and makes available to the LLM.Wolffish can do all of this itself. The built-in
skills capability lets Wolffish list, search, toggle, delete, and author its own capabilities at runtime — so “do this every time” can become a reusable skill without you touching the filesystem. This guide is for when you’d rather build one by hand.Prefer to let Wolffish build it? → Self-Authoring Skills
Ask in plain language and Wolffish authors, tests, and loads the capability itself — create → test → edit → verify, all in one turn. Includes a complete copy-paste example. Everything below is the manual path, for when you want to build one by hand.
Installing a Capability
You don’t have to touch the filesystem. The quickest way to add a capability is to drop it onto Settings → Cellebrum — or click the import field to browse. Three shapes are accepted:A single SKILL.md
A markdown procedure with YAML frontmatter (name, description, optional triggers). Imported as a pure skill — no tools to install.
A capability folder
A folder with a
SKILL.md plus an optional plugin/ (index.mjs) and package.json. The full capability — tools and all.A .zip archive
The same folder, zipped (e.g. macOS Compress). It’s unpacked to a temp dir, validated, then added.
name, invalid YAML, a plugin/ with no entry file, a duplicate name…) in a code block, so you can fix it and re-drop.
To remove an imported capability, click the trash icon next to it and confirm — that cleanly deletes its folder from brain/cerebellum/. Official and built-in capabilities have no delete button and can’t be removed this way.
Try It Now: Example Capabilities
Want to see the import flow before building your own? Download this bundle of three tiny, ready-to-run capabilities, then drop the.zip onto Settings → Cellebrum. All three import at once — validated and loaded on the spot, no terminal and no code to write.
Download example capabilities (.zip)
coin-flip, dice-roller, and color-mixer — three self-contained capabilities you can import in a single drop and see live in action.| Capability | What it does | Try saying |
|---|---|---|
coin-flip | Flips a fair coin | ”Flip a coin” |
dice-roller | Rolls dice with any number of sides | ”Roll 2d20” |
color-mixer | Converts colors between formats | ”Convert #ff5733 to RGB” |
brain/cerebellum/ to see exactly how a small capability is wired — they’re the same shape as the weather example below.
Step 1: Create the Folder
Step 2: Write the SKILL.md
CreateSKILL.md with YAML frontmatter and markdown instructions:
Step 3: Write the Plugin (Optional)
If your capability needs custom code, createplugin/index.mjs:
Step 4: Add Safety Patterns (If Needed)
If your tool can perform dangerous operations, add patterns to the SKILL.md frontmatter:Step 5: Test It
Send a message that matches your triggers. Check:- Context debug file (
brain/prefrontal/.debug/) — Is your SKILL.md included in the context? - Event log (
brain/corpus/) — Istool.calledfired with your tool name? - Task log (
brain/motor/tasks/) — Does the task file show successful execution?
A Real, Working Example: a Weather Capability
The walkthrough above used placeholders. Here is a complete capability you can copy-paste today that works immediately — it calls the free Open-Meteo API, which needs no API key and no signup. It demonstrates the whole pattern end to end: a real tool schema, two chained network calls (geocode a place name → fetch its current weather), input validation, graceful error handling, and a clean natural-language result.Folder layout
Built-in capabilities are dot-prefixed (
.shell, .web-search) so they stay hidden from a casual ls. Your own capabilities don’t need the dot — weather is fine and easier to find. Both are discovered the same way.SKILL.md
plugin/index.mjs
Why there are no danger_patterns
weather_get only reads public data over HTTPS — it can’t delete, spend, or overwrite anything. Read-only tools like this need no safety patterns. Reserve danger_patterns / confirm_patterns for tools that can actually cause harm (see Safety Patterns).
Try it
Restart Wolffish so the cerebellum loads the new folder, then ask:“What’s the weather in Tokyo?”You should see the agent call
weather_get and reply with something like “Weather in Tokyo, Tokyo, Japan: partly cloudy, 22.4°C, humidity 61%, wind 9.3 km/h.” Trace the call in brain/corpus/<today>.log.md to confirm the arguments and output.
Pure Skill vs Plugin: When to Use Which
Use a pure skill when your capability can be accomplished with existing tools (likeshell_exec or file_read), or when you want to shape agent behaviour without adding new tools. The SKILL.md instructions are injected into a <skills> section in the prompt when triggered.
Use a plugin when you need custom logic that can’t be expressed as shell commands or file operations — API calls, data processing, custom protocols, etc.
Always-On Pure Skills
Some pure skills should apply to every message — planning discipline, output formatting, safety constraints. Use the wildcard trigger"*":
Capability Checklist
Before shipping your capability:- SKILL.md has accurate triggers (test with different phrasings)
- Tool parameter descriptions are clear (the LLM reads them)
- Danger patterns cover all destructive operations
- Confirm patterns cover risky-but-legitimate operations
- Plugin handles errors gracefully (returns
ToolResultwithsuccess: false) - The markdown body has clear, specific instructions
- Tested with both cloud and local models
Packaging for Import and Sharing
Whether someone adds your capability as a folder or a.zip, the importer runs the same checks. Meeting them keeps your capability clean, portable, and safe to share:
- Exactly one
SKILL.md. The importer finds it at the root or up to three folders deep, so a zip of a folder (my-skill/SKILL.md) just works. Zero or more than oneSKILL.mdis rejected. - Valid frontmatter. It must begin with a
---block that parses as YAML and has a non-emptyname. Optional fields are shape-checked when present:triggersandrequiresmust be lists of strings, and every entry intoolsneeds aname. See the SKILL.md Reference. - Something to load. A SKILL.md with an empty body and no tools does nothing, and is rejected — give it a body, tools, or both.
- A plugin needs an entry file. If you ship a
plugin/folder, it must containindex.mjs,index.js, orindex.cjs. Declaringtoolsin a folder/zip with noplugin/is rejected — the tools would have nothing to run. - A unique name. The
namecan’t collide with a capability you already have (bundled or imported). The on-disk folder name is derived fromnameby slugifying it (My Cool Skill→my-cool-skill). - Junk is stripped automatically.
node_modules/,.git/,.DS_Store, and__MACOSX/are skipped on import — don’t bother removing them first, and leavenode_modules/out of your zip to keep it small. - Size limits.
SKILL.md≤ 1 MB, total payload ≤ 50 MB, ≤ 5000 files. Zips are extracted with path-traversal protection. - Dependencies install lazily. Anything in
requires(system tools) or yourpackage.json(npm packages) installs the first time the capability runs, not at import — so importing stays fast and offline-safe.