# Skills

> Skills are folders of plain-text instructions the agent can call by name to do a specific task, each with its own instructions and its own limited set of allowed tools.

A skill is a folder of plain-text instructions that teaches the agent how to do a specific task, so you can extend what the agent can do without changing Fermix itself. Each skill is a directory containing a `SKILL.md` file with YAML-style frontmatter (a small settings block at the top of the file, between `---` lines) and a system prompt body (the instructions handed to the model when the skill runs). A skill is not a provider-visible tool: it appears as a named entry in the runtime prompt's skill catalog, and the agent invokes it only through the built-in skill tools (`skill_view` to read it, `skill_run` to delegate to it).

Skills differ from built-in tools in that they carry user-authored instructions and an explicit tool boundary, and they differ from plugins in that they contain no executable code, no manifest, and require no signing. A skill is plain text.

## Discovery roots

The skill registry discovers skills from three roots on startup:

| Root | Path | Trust |
|------|------|-------|
| Bundled | Inside the Fermix release (`priv/skills`) | `:operator` |
| Local | `~/.fermix/skills` | `:operator` |
| Plugin | Skill dirs of enabled plugins | `:guest` |

Paths shown assume the default data directory; the local and plugin roots follow `FERMIX_HOME` if you have moved it (see [Configuration](/docs/configuration)).

Bundled and local skills are operator-trusted because the operator either installed Fermix (bundled) or placed the skill in their own directory (local). Plugin-loaded skills receive `:guest` trust, which restricts them to a read-only surface by default. Any skill path that does not resolve under one of the three known roots also falls back to `:guest`.

On a fresh install, the bundled skills are seeded into `~/.fermix/skills` so they are immediately editable. Seeding runs only when the local skills directory is empty, so an existing install is never overwritten.

A skill that fails to load (bad frontmatter, missing `name`, name collision with an existing capability) is logged and skipped. The remaining skills load normally; discovery errors are never fatal.

## SKILL.md format

Every skill directory must contain a `SKILL.md` file. The file opens with a YAML-style frontmatter block, followed by the skill's system prompt in Markdown.

```markdown
---
name: summarize_emails
description: Summarize unread emails in plain English.
allowed_tools: ["gmail_search_messages", "gmail_get_message"]
provider: anthropic
model: claude-sonnet-4-6
temperature: 0.3
max_iterations: 20
timeout_seconds: 120
---

# What this skill does

Summarize the user's unread emails concisely...
```

Recognized frontmatter keys:

| Key | Required | Description |
|-----|----------|-------------|
| `name` | Yes | Unique skill identifier: letters, digits, underscore, or hyphen, max 64 characters. Must not collide with any registered capability name. |
| `description` | Yes | One-line description shown in `skill_list` output and the runtime prompt catalog. |
| `allowed_tools` | No | JSON array of tool names available to the skill's sub-agent (the separate agent run that executes the skill). `[]` means none; omitting the key inherits the trust-level default. |
| `policy` | No | Explicit capability-class override for the skill's tool surface: any of `read_only`, `read_write`, `exec`, `network`, `external_api`. Desktop control (`gui_control`) can never be granted to a skill. |
| `provider` | No | Provider for the skill's sub-agent run (a configured provider name such as `anthropic` or `openai`). When omitted, the run inherits the provider chain of the turn that invoked it. |
| `model` | No | Model override for the skill's sub-agent run. A skill that pins `provider`/`model` runs only on that route, with no fallback. |
| `temperature` | No | Sampling temperature for the skill's model call. |
| `max_iterations` | No | Iteration cap for the skill's sub-agent loop (default 25). |
| `timeout_seconds` | No | Wall-clock timeout for a `skill_run` call (default 300 seconds). |

Unrecognized keys are ignored, but `trust:` is not one of them: a `trust:` line is rejected — the skill fails validation and is skipped at discovery, with a warning in the log naming it. Trust comes only from where the skill lives on disk (see [Trust and tool boundaries](#trust-and-tool-boundaries)); it can never be declared in frontmatter.

When a skill run times out, the external commands it spawned are terminated with it: each command Fermix runs is placed in its own OS process group, and Fermix kills the whole group — the command and every process it started — on timeout, on crash, and on daemon shutdown. A skill that shells out to `python` or `node` cannot leave orphaned subprocesses running.

The body after the closing `---` is the system prompt. It is passed verbatim as the sub-agent's system message when the skill is dispatched via `skill_run`. Keep the body under 64 KB (65,536 bytes): `skill_view` refuses to load anything larger, so the agent could no longer read the skill. Split long reference material into separate files inside the skill directory and point to them from the body.

## Bundled skills

Fermix ships two bundled skills:

| Name | Description |
|------|-------------|
| `self-knowledge` | Describes Fermix's own capabilities, agent loop, providers, channels, jobs, memory, sandbox, plugins, and configuration surfaces. |
| `browser-guidance` | Operating guidance for the `browser` tool: tool routing, the operating loop, action semantics, tab and ref hygiene, and stop conditions. |

Both are seeded into `~/.fermix/skills` on a fresh install, so you can inspect or edit them locally.

## Skill tools

Five built-in tools expose the skill surface to the agent:

| Tool | Description |
|------|-------------|
| `skill_list` | List installed skills with their names and descriptions. |
| `skill_view` | Show a skill's full system prompt and metadata. |
| `skill_run` | Run a skill by name as a bounded sub-agent. Recursion depth is capped at 4. Every run writes a journal entry (a small record of how the run ended) under `~/.fermix/journals/`. |
| `skill_create` | Scaffold a new skill under `~/.fermix/skills` with a starter `SKILL.md` and an eval directory (evals are optional test cases that check the skill behaves as intended). |
| `skill_reload` | Re-scan all skill directories and refresh the running agent in place, reporting added, removed, and changed skill names plus any load errors. No daemon restart required (the daemon is the long-running Fermix background process). |

The CLI also provides `fermix skills list`, `fermix skills view NAME`, and `fermix skills reload`, each accepting `--json` for machine-readable output.

## Creating a skill

Use `skill_create` from any chat channel or `fermix ask`:

```json
{
  "name": "summarize_emails",
  "description": "Summarize unread emails in plain English."
}
```

`skill_create` accepts only `name` and `description`. It scaffolds `~/.fermix/skills/summarize_emails/SKILL.md` (with `allowed_tools: []` and a placeholder body) and a starter `evals/evals.json` file. Edit the SKILL.md to add your system prompt and adjust `allowed_tools`. You can also create the directory and `SKILL.md` manually without the tool.

After creating or editing a skill, run `skill_reload` (or `fermix skills reload` from the CLI) to pick up the change without restarting the daemon. The reload result doubles as validation: it lists added, removed, and changed skills plus a load error for any skill whose file failed to parse.

## Picking up changes

Skill file changes do not apply automatically. To apply them:

1. Edit `~/.fermix/skills/<name>/SKILL.md`.
2. Run `skill_reload` (in chat) or `fermix skills reload` (CLI) to refresh the registry in place.
3. Check the reload output: it reports added, removed, and changed skill names, and a load error for any skill that failed to parse (bad frontmatter, missing `name`, name collision).

If you prefer a full restart: `fermix restart`. The registry re-scans all roots on restart and re-registers skills from scratch. A skill that collides with an existing capability name is skipped on every load attempt until the collision is resolved.

## Trust and tool boundaries

The `allowed_tools` key is the primary confinement mechanism. It narrows the set of capabilities the skill's sub-agent may call:

- `[]`: the skill cannot call any tools.
- `["browser", "web_fetch"]`: the skill can only call those two tools.
- Omitted: the skill inherits the trust-level default for its root (operator or guest).

Plugin skills load at `:guest` trust regardless of what `allowed_tools` specifies. A guest skill that names a tool outside the guest surface is rejected at run time, not silently granted. You cannot widen a plugin skill's trust by editing its `SKILL.md` — the registry stamps trust from the skill's on-disk location, never from its frontmatter.

Skill *trust* classifies where the skill file came from and bounds what its sub-agent may touch. It is separate from *sender* trust on a channel: skills are an operator surface, so a guest sender (someone authorized to chat but who is not the owner) sees no skill catalog and cannot run skills at all. See [Ingress and trust](/docs/ingress-and-trust).

When a skill is bound to a scheduled job via `skill_name`, the job's own `allowed_tools` policy is intersected with the skill's. Neither side can widen past the other.

## Plugin skills

Plugins can ship their own skills inside the plugin package. A plugin's skills are discovered only while the plugin is enabled, and they always load at `:guest` trust. Skills from catalog plugins you install live under the plugin's directory in `~/.fermix/plugins`; the bundled Google Workspace plugins (Gmail, Google Calendar, Google Drive) ship inside Fermix itself, and each carries a skill that documents its tool surface — the agent opens these with `skill_view` when dispatching work through those integrations.

## Related pages

- [Capabilities and tools](/docs/capabilities-and-tools): built-in tools including the skill tools
- [Tool reference](/docs/tool-reference): full schema and failure modes for `skill_create`, `skill_list`, `skill_run`, `skill_view`, and `skill_reload`
- [Scheduled jobs](/docs/scheduled-jobs): binding a skill to a job with `skill_name`
- [MCP](/docs/mcp): MCP tools (registered as `mcp_<server>_<tool>`) available as `allowed_tools` values
