Add a skill¶
A skill is a directory holding a SKILL.md file: YAML frontmatter plus markdown instructions for a
repeatable procedure. The assistant sees a catalogue of every skill's name and description, and loads a
skill's full instructions on demand. A skill can also ship runnable scripts, each of which becomes a
callable tool.
Skills are the one capability the assistant keeps for itself rather than delegating, so this guide is shorter than it looks: there is one directory, and three ways to put something in it.
Two things named skills, and one named per skill¶
skills is the authoring toolset. It carries author_skill and add_skill_script, and only the
entry agent (the one [assistant].agent names) can hold it:
Declaring skills on any other agent is a startup error, because a spawned worker is a plain AIMU
Agent rather than a SkillAgent, so there is nothing for skill injection to hook. The registry marks
the toolset entry_point_only, so you find that out at startup rather than through a worker that quietly
has no skills.
Drop skills and the assistant can no longer write skills, but it can still use the ones already in
the directory: the entry agent is a SkillAgent either way, so the catalogue and activate_skill come
from AIMU rather than from this toolset.
Each individual skill is also a name in the toolset namespace, so you can give one skill to one agent:
[agents.reporter]
description = "Builds and mails reports."
tools = ["markdown-to-pdf", "email-report", "fs", "compute", "time"]
A skill name sits beside web and an MCP server's name and does not say which kind it is. kokua
--list-toolsets shows every skill on disk under a skill: group, and a name that is not there fails at
startup listing the ones that are.
Give a script-carrying skill an agent that can run scripts. A worker declaring a skill gets that
skill's {skill}__{stem} script tools and activate_skill through the registry, and the skill's own
instructions usually tell it to run something -- so fs and compute belong in the same tools list.
One rule worth knowing: an agent holding the skills authoring toolset sees every skill on disk,
not just the ones it declares. Scoping an author's catalogue would hide the skill it just wrote, and
add_skill_script promises the script is callable in the same turn. A non-authoring agent's catalogue is
scoped to its declaration.
Where Kokua looks¶
Only $KOKUA_HOME/data/skills/ (by default ~/.kokua/data/skills/, or <data_dir>/skills if you
set [paths] data_dir).
This is worth stating plainly because AIMU's SkillManager defaults to scanning four search paths
(.agents/skills/, .claude/skills/, and their ~ equivalents). Kokua passes skill_dirs explicitly
(registry/context.py), so those defaults do not apply here. A
skill in ~/.claude/skills/ is invisible to Kokua. This follows from the principle that all state lives
under one directory you own; nothing is read from your working directory.
The SKILL.md format¶
---
name: weekly-digest
description: Compile the week's notes into a digest and email it.
---
# Weekly digest
1. Read the documents saved this week.
2. Group them by project, newest first.
3. Draft the digest in Markdown, then delegate the send to the report-writer agent.
name and description are required. name must be a kebab-case slug: lowercase words joined by
hyphens, never underscores or spaces. A malformed SKILL.md raises SkillLoadError rather than being
skipped silently, so a typo fails loudly at startup. See AIMU's
use skills for the optional frontmatter fields.
description carries more weight than its length suggests: it is the only part of a skill in the
catalogue, so it is the whole basis on which the model decides whether to load the skill at all. Write
it as a trigger ("when you need to ..."), not a title.
Four ways to add one¶
Install one Kokua ships¶
The repository carries a few skills in its own skills/ directory, outside the package:
kokua skills list # what is bundled, with each description
kokua skills install markdown-to-pdf # copy it into your skills folder
kokua skills install # all of them
They land in the skills folder your config resolves, so [paths].data_dir and $KOKUA_HOME are
honoured. An existing skill of the same name is left alone unless you pass --force, so a local edit
survives a reinstall. dice-roller is the smallest complete example: copy it as a starting point.
These ship with the repository rather than the wheel, so a pip install kokua has no copy of them and
the command says where to get one.
Write the directory by hand¶
One SkillManager is shared by every conversation, so a skill authored in one conversation is usable in
all of them. The flip side is that the manager caches its catalogue and only re-scans the directory when
something refreshes it, which author_skill and add_skill_script do and a hand-written directory cannot:
restart Kokua after adding a skill by hand. Starting a new conversation is not enough, since the new
agent reads the same cached catalogue.
Ask the assistant to write it¶
The entry agent has an author_skill tool, and the guidance the skills toolset carries into its prompt
tells it to reach for that tool when you teach it a repeatable procedure worth remembering. So the
shortest path is a sentence:
"That worked. Save it as a skill called
weekly-digestso you can do it the same way next Friday."
author_skill(name, description, body) writes the SKILL.md and refreshes the manager, so the skill is
usable in the same conversation. It will not overwrite an existing skill; to revise one, either edit
the file by hand or delete the directory first. It is not gated for approval, since it only writes
markdown.
Attach a script¶
add_skill_script(skill_name, filename, content) writes scripts/<filename> (a .py or .sh file)
into a skill that already exists, then reloads the agent's skills so the new tool is callable in the same
turn.
- The tool it creates is named
{skill_name}__{stem}, with both halves lowercased and every run of other characters collapsed to_, socollect_notes.pyinsideweekly-digestbecomesweekly_digest__collect_notes. Note the hyphen becomes an underscore; the__stays the only separator. - Because names collapse, two scripts in one skill can collide and only the first is registered:
collect_notes.pywithcollect_notes.sh(same stem), andcollect-notes.pywithcollect_notes.py(same slug). Give each script a distinct stem. - To fix a broken script, reuse the exact same filename. That overwrites in place and the tool keeps its name. A different filename creates a second script and leaves the broken one callable.
- The skill must exist first. Calling it for an unknown skill returns the list of skills that do exist.
- It is gated by default (
[security] confirm_tools), so each call waits for youry/Nin the terminal or Allow/Deny in the web UI.
Scripts run as real subprocesses with your user's privileges and no sandbox. Their stdout becomes the tool result. The catalogue lists script tool names inline, so the model can call one directly without loading the skill's instructions first.
Who gets skills, and who does not¶
The entry agent is an AIMU SkillAgent; every agent it spawns is a plain Agent, which is why the
skills authoring toolset cannot be declared on one. A worker can still hold an individual skill: its
script tools and activate_skill arrive through the registry rather than from SkillAgent. This
has a practical consequence for how you write a skill:
Write the procedure from the entry agent's point of view, as a plan it carries out with the tools it
declares plus delegation. In the shipped config that agent holds only cross-cutting toolsets, so a skill
body saying "search the web for X, then write the file" describes work it cannot do. "Delegate the lookup
to researcher, then have coder write the file" describes work it can. Naming the agent you expect is
the single most useful thing a skill body can do. If you have edited [agents.*] to give the entry agent
domain toolsets of its own, write to what you gave it.
Skill scripts are the exception, and a deliberate one: a {skill}__{stem} tool is mounted on the entry
agent, so a script is one way to give it a concrete capability of its own without touching the core or
installing a toolset.
Security¶
Skills are executable capability you accumulate over time, in a directory the assistant can write to. Two things follow:
add_skill_scriptis gated because it is arbitrary code execution with a delay: the script is written in one turn and may be invoked in any later one, including an unattended scheduled turn. Approving it approves every future call.- Proactive and backgrounded turns auto-deny every gated tool, so the assistant cannot author and run a new script while you are not watching. It can still call scripts that already exist.
Review ~/.kokua/data/skills/*/scripts/ the way you would review anything else on your PATH.
See also¶
- Set up a toolset: how any capability reaches any agent, which is the other half of the picture a skill body needs.
- Add an MCP service: the third source of capability.
- Architecture: how a declaration becomes tools, and the shipped entry agent's full inventory.
- AIMU: use skills for
SkillAgent, the catalogue, and the fullSKILL.mdreference.