Skills
A skill is a SKILL.md file of specialized instructions for a kind of task — a debugging workflow, a release checklist, a code-review procedure. Skills are not code; they are prompt material, discovered from the filesystem and surfaced to the model so it can pull in detailed guidance only when a task matches.
Brute implements the Agent Skills specification and its three-stage progressive-disclosure lifecycle.
The file format
A skill is a directory whose SKILL.md has YAML frontmatter and a markdown body:
---
name: debugging
description: Systematic debugging workflow for isolating and fixing bugs
---
When debugging, follow these steps...
name: 1–64 chars, lowercase letters/digits/hyphens, and must match the parent directory name (defaults to the directory name if omitted).description: required, 1–1024 chars.- Optional:
license,compatibility,metadata,allowed-tools.
A skill that violates a rule is skipped with a stderr warning — never raised. Unexpected fields are dropped with a warning but the skill still loads, so real-world skills carrying vendor extensions still work.
Discovery
Brute::Skill.all(cwd:) scans two roots, in priority order:
<cwd>/.brute/skills/**/SKILL.md— project-local~/.config/brute/skills/**/SKILL.md— global (per-user)
.brute/skills/
debugging/SKILL.md
release-checklist/SKILL.md
When two skills share a name, first found wins, so a project-local skill overrides a same-named global one.
The three stages
1. Names and descriptions in the system prompt. Brute::Prompts::Skills injects only each skill’s name and description — not the body — so the prompt stays small no matter how many skills exist:
<available_skills>
<skill>
<name>debugging</name>
<description>Systematic debugging workflow for isolating and fixing bugs</description>
</skill>
</available_skills>
This is part of the default system-prompt stack for the anthropic, openai, google, and default providers. The ollama stack omits it to keep prompts lean for small local models.
2. Loading the body via the skill tool. When the model decides a skill applies, it calls the skill tool (Brute::Tools::SkillLoad) with the name. The tool returns the full SKILL.md body plus the skill’s base directory and a sample of its bundled files:
<skill name="debugging">
# Skill: debugging
When debugging, follow these steps...
Base directory for this skill: /project/.brute/skills/debugging
Bundled files (sampled, up to 10):
references/checklist.md
scripts/bisect.sh
</skill>
3. Bundled resources through existing tools. Skills can ship scripts/, references/, and assets/. There is no separate skill runtime — the model reads and runs them by relative path through the agent’s ordinary read and shell tools.
An unknown skill name returns a tool-error string listing the available names; it never raises.
Using skills in your own agent
Prompts::Skills is just another prompt module, so custom agents opt in by appending it when building a system prompt:
sp = Brute::SystemPrompt.build do |prompt, ctx|
prompt << Brute::Prompts::Identity.call(ctx)
prompt << Brute::Prompts::Skills.call(ctx) # scans ctx[:cwd] for skills
end
Brute.agent.use(Brute::Middleware::SystemPrompt, system_prompt: sp)
The skill tool takes a matching cwd: at construction — point both the prompt and the tool at the same root, or the prompt advertises skills the tool can’t load. Brute::Tools::ALL includes it with the default Dir.pwd.
A skill’s body is also available programmatically: Brute::Skill.get("debugging").content.