Skills
Four loading sources, naming rules, and why descriptions are triggers
Skills are markdown files with name + description frontmatter, surfaced to the agent in the <available_skills> system-prompt section. The agent loads one on demand by read-ing the SKILL.md at the <location> path that section advertises — there is no dedicated skill tool. (The load_skill tool is a separate, subagent-only mechanism for in-memory LoadableSkills; see Subagent skills.) Four sources, each with a different owner:
| Source | Path | Owner | When to add |
|---|---|---|---|
| Bundled | src/skills/<name>/SKILL.md | typeclaw repo | Cross-cutting agent guidance shipped with the CLI. Auto-discovered; no wiring. Use typeclaw- prefix (reserved namespace). |
| User-installed | <agentDir>/.agents/skills/<name>/SKILL.md | end user | Personal skills the user drops in. Existence-gated; wired explicitly. |
| Muscle memory | <agentDir>/memory/skills/<name>/SKILL.md | dreaming subagent | Procedures distilled from sessions. Don't write here from main-agent code. |
| Plugin-contributed | Plugin dir or in-memory PluginSkill[] | plugins | Bundled inside a plugin; both routes converge as ordinary skill dirs. |
Wiring: setupSession in src/agent/index.ts. Default to bundled when adding a new skill.
Footgun:
<agentDir>/skills/(no.agents/) is auto-discovered by upstream but not supported here. Don't use it.
Naming
typeclaw- prefix for bundled. One-segment kebab-case. Sanitizer regex ^[a-z0-9][a-z0-9-_]*$.
Descriptions are triggers, not summaries
The LLM picks skills by description. Name the failure modes, platforms, and verbs that should activate the skill. Vague descriptions = dead weight.
Skills are lazy
Adding one costs zero tokens until loaded. Right home for platform-specific guidance and large runbooks. Do not copy skill content into tool descriptions — those reload into every tool-call prefix, which is exactly the cost model skills avoid.
How the agent loads a skill
The four sources above are all file-based: the upstream DefaultResourceLoader walks additionalSkillPaths (src/agent/index.ts), parses each SKILL.md frontmatter, and renders name + description + an absolute <location> into the <available_skills> block. The system prompt instructs the agent to read the <location> path when a description matches — the body loads only then.
The agent must use the exact <location> path verbatim. It must not construct or guess skill paths (e.g. node_modules/typeclaw/src/skills/<name>/SKILL.md): muscle-memory and user skills live under the agent dir, the bundled path resolves through the installed package, and a guessed path that doesn't exist is the most common skill-load failure. If a skill you expect isn't listed in <available_skills>, it isn't file-based — don't go hunting for its SKILL.md on disk.
Subagent skills (load_skill)
Subagents bypass the file-based resource loader entirely, so the startup discovery path is unavailable to them. A plugin can instead hand a subagent a typed load_skill tool via createLoadSkillTool (src/plugin/load-skill.ts), passing in-memory LoadableSkill objects (name / description / content). The tool's name parameter is a Zod enum of the supplied skill names, so the subagent picks from a fixed menu — it can't read a SKILL.md off disk.
This is distinct from the main-agent flow: load_skill returns a content string the plugin embedded at build time, not a discovered file. The only bundled consumer is the reviewer subagent (src/bundled-plugins/reviewer/), whose code-review and general skills are LoadableSkills — there is no code-review/SKILL.md anywhere in the tree.