Agent Skills

A skill is a directory containing a SKILL.md file: frontmatter plus Markdown instructions. MiniBot implements the agentskills.io format, so skills written for other agent tools generally work here and vice versa.

Skills exist because of progressive disclosure. Only each skill’s name and description are visible to the model up front; the full instructions load into context only when the model calls activate_skill. That lets an instance carry dozens of skills without paying for all of them on every turn.

Enabling

[tools.skills]
enabled = true

That attaches list_skills and activate_skill, and loads the skills bundled with MiniBot. Everything below is optional tuning.

The SKILL.md format

---
name: my-skill
description: One or two sentences saying WHEN to use this skill.
---

# My Skill

Full instructions here...

Field

Required

Notes

name

yes

Must match the directory name. Use lowercase and hyphens for portability.

description

in practice

The only part of the skill the model sees before activating it.

compatibility

no

What the skill needs to run — “Requires bash and git”, say. activate_skill returns it, and the model is told to report a missing tool instead of improvising around it.

Other fields in the spec — license, metadata, allowed-tools — are accepted and ignored, so they are safe to keep for portability but do nothing here. A skill is on while its directory is in a discovery path, and off once it is removed (bundled skills are switched off with native_disabled).

Warning

MiniBot’s frontmatter parser is simpler than the spec. It reads flat key: value pairs and block scalars (| and >) for name, description and compatibility; nested keys, list items and every other key are skipped, so it is not real YAML.

Keep values on a single line where you can. An empty body is the silent failure to avoid: the skill is dropped entirely, with no error the user will see.

Writing a description that triggers

The description carries the whole activation decision, so write it to answer when should I reach for this, not what is this. Name the situations it applies to, including ones where the user never says the domain out loud. A description above 300 characters is logged at info level; the spec’s hard limit is 1024.

Weak:   PR review helper.
Better: Review a pull request diff for behavioural bugs and regression risk. Use when
        asked to review a PR, a diff, or changes on a branch.

Discovery

Skills load from three sources. When tools.skills.paths is empty (the default), MiniBot scans these locations in priority order:

Priority

Source

Path

1 (highest)

project

tools.skills.write_path (default ~/.minibot/skills/)

2

project

./.minibot/skills/

3

project

./.agents/skills/

4

user

~/.minibot/skills/

5

user

~/.agents/skills/

6 (lowest)

native

skills bundled inside the MiniBot package

When two skills share a name, the higher-priority one wins and the other is skipped with a warning in the logs. That is the supported way to override a skill rather than replace its file — write your own with the same name in a project path, and it shadows the bundled one.

Setting paths to a non-empty list replaces entries 2 to 5. write_path and the bundled skills are independent of it, so configuring paths never silently drops them. Skills kept anywhere else — ~/.claude/skills, say — are picked up by listing that directory in paths.

Bundled skills

MiniBot ships skills inside the package so a fresh install is not empty. They are on the lowest tier, so anything you write wins over them.

[tools.skills]
native = true                        # the whole bundled tier
native_disabled = ["create-skill"]   # or drop individual ones

Nobody edits files inside an installed package, so native_disabled is the switch.

Currently bundled:

  • create-skill — how to author a skill: building it from the task you just completed rather than from general knowledge, writing a description that triggers, and the places this parser is stricter than the spec.

  • install-skill — the preview, confirm, install, verify procedure for install_skill. Hidden unless install = true (see below).

  • minibot-docs — answers questions about how MiniBot works from the documentation bundled in the package (the read_docs tool, which it enables), and routes questions about the running instance to the get_settings tool instead of answering them from the docs. It falls back to the published site through http_request only when the bundled docs are missing.

  • create-agent — how to author a specialist agent: using the management tools rather than a file write, reading the ceiling from get_settings before granting anything, and what each validation error means. Hidden unless [orchestration.agent_management] write = true, because without it the tools it describes do not exist. See Multi-Agent Orchestration.

Where the agent writes new skills

tools.skills.write_path (default ~/.minibot/skills) is where the agent creates or installs skills, and it is added as the highest-priority discovery path so a skill written mid-conversation is found on the next list_skills call, with no restart. With the Docker Compose file, ~/.minibot is a mounted volume, so skills written there survive a rebuild.

Whether the agent can actually write there depends on which file-writing tools are enabled. list_skills reports the answer as write_dir_access:

Value

Meaning

write_file

The directory is inside [tools.file_storage] root_dir, or allow_outside_root is on. write_dir_filesystem_path carries the path in the form that tool expects.

bash

Out of the write_file tool’s reach, but [tools.bash] is enabled.

unavailable

Neither applies. The agent reports this instead of attempting a write that would fail.

With the defaults in config.example.toml both writers are off, so skills are read-only. The simplest writable setup is to enable [tools.file_storage] and point write_path inside its root:

[tools.file_storage]
enabled = true
root_dir = "./data/files"

[tools.skills]
enabled = true
write_path = "./data/files/skills"

Installing skills

install_skill is a Python counterpart of npx skills add: it downloads skills other people published and installs them into write_path, with no Node.js and no [tools.bash] needed. It is off by default, because an installed skill is third-party instructions the agent will later follow:

[tools.skills]
enabled = true
install = true

Accepted sources, HTTPS only:

Source

Installs

owner/repo

every skill found in the GitHub repo

owner/repo@skill-name, owner/repo/path/to/skill

one skill (@ names a skill, as with npx skills add)

https://github.com/owner/repo/tree/<ref>/<path>

the skill at that path and ref (a blob URL to a SKILL.md works too)

any other https:// URL

a .zip/.tar.gz archive, or a single raw SKILL.md

The tool first returns a preview — each skill’s name, description, compatibility, the start of its instructions, files and a hash, plus every rejected candidate with the reason — and writes nothing. When a skill of the same name is already available, the preview reports it as existing, and installing needs force. The bundled install-skill skill has the agent show the preview to you and wait for confirmation when you did not name the source yourself. Installing requires the preview’s hash as expected_hash, so a source that changed in between is refused. It validates each skill with the same parser the runtime uses, copies it to <write_path>/<name>/, and records it in <write_path>/skills-lock.json in the format the npm skills tool uses. The new skill shows up in list_skills immediately and is never activated automatically.

Limits follow npx skills: 10 MiB download, 25 MiB and 1000 files once extracted. Archive members that would land outside the extraction directory are rejected. Private repositories and non-GitHub git hosts are not supported.

The tools

list_skills

Returns up to 8 skills, ranked against an optional query: exact name match, then name prefix, then substring in the name, then substring in the description, then fuzzy similarity. The response also carries write_dir, write_dir_access, write_dir_filesystem_path, discovery_paths, and a source of project, user or native per match.

activate_skill

Takes the exact name returned by list_skills and returns the full instructions, the skill’s directory, its source, and a list of the other files in that directory — so a skill can point at references/ material the model reads only when it needs it. When the skill declares compatibility, that is returned too.

install_skill

Only with install = true. Previews or installs a published skill — see Installing skills.

The prompt catalog

tools.skills.preload_catalog (default true) embeds a snapshot of skill names and descriptions in the system prompt. With it off, the model is only told that list_skills exists, so it cannot tell whether a relevant skill is available — and delegating to a specialist, whose roster is in the prompt, tends to win by default. list_skills still reads live from disk either way.

Hot reload

Skill files are re-read automatically. The registry fingerprints each SKILL.md by modification time and size, so adding, editing or deleting one takes effect on the next list_skills call — no restart.

This is the opposite of prompt files under prompts/, which are cached for the life of the process, and of specialist definitions in agents/*.md, which are read once at startup.

Configuration reference

[tools.skills]
enabled = true
# Embed a names/descriptions snapshot in the system prompt.
preload_catalog = true
# Replaces the project and user discovery paths; leave empty for the defaults.
paths = []
# Skills bundled inside the package, independent of `paths`.
native = true
native_disabled = []
# Where the agent creates or installs skills; also the top-priority discovery path.
write_path = "~/.minibot/skills"
# Attach install_skill (and show the bundled install-skill skill).
install = false

See Configuration Reference for the full schema.

Troubleshooting

The skill does not appear in list_skills. Check, in this order: the body is empty; the frontmatter block is missing or malformed; there is no name; the file is not at <directory>/SKILL.md; or a higher-priority skill has the same name and is shadowing it. An invalid skill is logged as invalid skill, skipping with the reason.

write_dir_access is unavailable. Enable [tools.bash], or enable [tools.file_storage] and point write_path inside its root_dir.

A bundled skill is not wanted. Add its name to native_disabled, or write your own with the same name in a project path to override it.