A skill is a markdown file with frontmatter, loaded into context when it is used. Two layouts are recognised:
<dir>/<name>/SKILL.md— the superpowers / Claude Code style<dir>/<name>.md
name and description are read from the frontmatter.
Config
{
"skills": {
"discover": ["claude", "opencode"],
"paths": ["~/.config/opencode/skills", { "path": "./.titah/skills", "as": "team" }],
"always": ["superpowers:using-superpowers"]
}
}
discoverreads the Claude Code (~/.claude) and opencode (~/.config/opencode) skill and plugin registries, so anything already installed there works with zero configuration. Set it to[]in tests, or in any setup that must not touch those directories.pathsadds explicit directories, either as a bare string or as{ path, as }to override the namespace that directory would otherwise get.alwaysnames skill ids loaded in full on every turn, rather than appearing as one catalogue line each. An agent’s ownskills: [...]is the per-agent counterpart and takes the same fully-qualified ids.
Ids and namespaces
A skill’s id is always fully qualified as namespace:name. The bare name alone
is never accepted, since two different sources can define the same name.
The namespace comes from, in order:
- the plugin manifest’s
name(.claude-plugin/plugin.json), if one exists for that directory or its parent; - otherwise the skill directory’s own folder name;
- except when that folder is literally called
skills, which tells you nothing on its own — in that case the parent directory’s name is used instead.
Rule 3 is what turns ~/.config/opencode/skills into the opencode namespace
rather than skills.
Invoking a skill
Type /plugin:skill <message> to run one directly:
/superpowers:brainstorming a new caching layer
The transcript shows the command you typed, not the skill’s full body — the model receives the skill’s instructions followed by your message.
The model can also load a skill on its own, without being asked, through the
skill tool: it passes a fully qualified id as seen in the /skills catalogue,
and the skill’s instructions are inserted into the conversation. This is how a
skill whose description matches the current task gets used without a slash
command.
A skill assigned to an agent through that agent’s skills: [...] is loaded
in full into its system prompt from the start. Every other skill is only
catalogued one line each — loading everything up front would exhaust the context
window before any work begins.
Learned skills
Titah can also write skills on its own. It is off until you turn it on:
{ "skills": { "learn": { "enabled": true, "minTools": 8, "max": 30 } } }
After a turn that finished normally and used at least minTools tool calls,
one call to your smallModel reads a short digest of the turn — the request,
the sequence of tool calls with their outcomes, the final answer, never the
transcript — and decides whether it was a procedure worth keeping. Most turns
are not. When one is, it is written to
~/.config/titah/skills/learned/<name>/SKILL.md, gets the learned: namespace,
and is in the catalogue of your next turn:
Learned a skill: learned:deploy-sims → ~/.config/titah/skills/learned/deploy-sims/SKILL.md
- What it costs. One small-model call per qualifying turn, with a digest of
about 6k tokens at most. Turns that do not qualify — short, failed or
cancelled, stopped at a limit, sub-agents, and every
titah run— cost nothing. - What it may touch. Only files whose frontmatter says
source: titah-learn, identified by their folder. Skills you wrote are never overwritten; delete that line and a learned skill is yours. Names, sizes and common secret shapes are checked before anything reaches disk. - What to watch for. A turn can include text from pages or files it read, so learned skills are labelled auto-written by Titah — verify before following in the catalogue. Read a new one before relying on it; the notice gives the path. Delete its folder to forget it.
- Where to look. Every decision, including “no”, is one line in
~/.config/titah/learn.logwith the tokens it used, andtitah doctorshows whether learning is on, how many skills were learned, and the cap.
A source never scans into another source’s root, so listing
~/.config/titah/skills in skills.paths does not list learned skills twice.
When something is misconfigured
Two situations are tolerated rather than treated as fatal, because a misconfigured skill should not take down a session:
- a duplicate id (same
namespace:namefrom two sources) keeps the first one found and drops the second; - an id in
always, or in an agent’sskills, that resolves to nothing is simply skipped.
Both are silent at the point they happen. But /skills and titah doctor
report the skill count per namespace and — only when there is something to flag —
list every conflict, every configured path that yielded no skills, and every
unresolved id together with where it was configured.
Two things skills do not do
opencode plugins are not supported. opencode has two extension mechanisms that share a folder structure but are not the same thing. Skills are plain markdown, and Titah reads those like any other skill source. Plugins are JavaScript modules written against opencode’s own runtime API — hooks, event handlers — so there is no markdown to load. Titah cannot run them and does not try to.
A skill cannot make Titah do anything by itself. A skill is text inserted into a prompt: instructions, not code. It cannot open a browser, call an API, or perform any action beyond what the model can already do with the tools it has. Any new capability requires a tool, not a skill.