zot skills
A skill is a reusable instruction set written as a single
SKILL.md file with a YAML frontmatter header. Skills may be supplied by
an extension as well as by the normal skill directories. Unless a skill disables
model invocation, zot discovers it at startup and surfaces it to the model
in two ways:
- The system prompt gains a short manifest:
Available skills: ... - code-review — Run a self-review pass...
- A built-in
skill tool lets the model load any one skill's full
body on demand.
The on-demand-load model keeps token usage cheap: only the manifest
goes into every request; the body is fetched as a tool result the
one or two turns the model actually needs it.
Anatomy
---
name: code-review
description: Run a thorough self-review pass on a recent change.
allowed-tools: [read, bash]
permissions:
bash: ["git diff*", "git log*"]
---
# Code review
When asked to review code, ...
Frontmatter fields
| field |
required |
purpose |
name |
optional |
skill identifier; defaults to the normalized relative directory path |
description |
required |
one-line summary shown in the system prompt |
disable-model-invocation |
optional |
when true, hide the skill from the model's startup manifest; invoke it explicitly with /skill:<name> |
allowed-tools |
optional |
list of tool names the skill is meant to use; informational |
permissions |
optional |
per-tool patterns; informational |
allowed-tools and permissions are parsed but not enforced in
this version. They appear in the rendered skill body so the model can
see them and self-regulate. Future versions may enforce.
The body (everything after the second ---) is plain markdown.
There's no template engine; the model sees what you write.
Discovery
zot recursively looks in these directories, in priority order, and registers the
first SKILL.md it finds for each unique name:
| location |
scope |
./.zot/skills/<name>/SKILL.md |
project (native) |
$ZOT_HOME/skills/<name>/SKILL.md |
global (native) |
./.claude/skills/<name>/SKILL.md |
project (claude-compat) |
~/.claude/skills/<name>/SKILL.md |
global (claude-compat) |
./.agents/skills/<name>/SKILL.md |
project (agent-compat) |
~/.agents/skills/<name>/SKILL.md |
global (agent-compat) |
The compat paths are deliberate: a SKILL.md written for an existing
skill ecosystem works in zot unchanged. Drop your existing
.claude/skills/ or .agents/skills/ directories into a project and
zot will pick them up. When no frontmatter name is present, nested path
components are lowercased and normalized to kebab-case and joined with -.
Only files named exactly SKILL.md are read.
Extensions namespace their skills, for example git-tools:writing-git-commits.
Explicit --ext bundles take precedence over environment, project, global, and
compatibility sources. Duplicate names keep the higher-precedence file and
report a diagnostic. --no-ext omits implicit extension bundles;
--no-ext --ext PATH loads only the explicitly named bundle. --no-skill
disables all skills, including extension and built-in skills.
When XDG_STATE_HOME is set on any platform, $ZOT_HOME defaults to
$XDG_STATE_HOME/zot. Otherwise it defaults to ~/Library/Application Support/zot/
on macOS, ~/.local/state/zot on Linux, or %LOCALAPPDATA%\zot on Windows.
Inspecting installed skills
In zot, run /skills. A picker lists every discovered skill with its
description and source path. Press enter on a row to view the full
body inline. Press esc to go back.
Invoking skills
For normal skills, the system prompt tells the model the skill names and
short descriptions. When a request matches, the model calls the skill tool
to load the full instructions on demand.
To force a specific skill, invoke it as a slash command. Typing /skill: opens a filtered list of discovered user skills. Use the arrow keys to select one, tab to complete its name, or enter to invoke the highlighted skill.
/skill:code-review
/skill:code-review focus on security issues
By default, suggestions match case-insensitive name prefixes and are sorted
alphabetically. Enable fuzzy skill suggestions in /settings to match
characters in order anywhere in a skill name: /skill:review and /skill:crv
can both find code-review. Results are ranked by relevance, with alphabetical
tie-breaking, and matching characters are shown in bold, including in the
selected row. Only names are searched, not descriptions or the /skill: prefix.
An empty query still lists skills alphabetically; an exact name shows only that
skill. Other slash-command suggestions and exact skill lookup during invocation
are unchanged. Complete a fuzzy query before adding request text.
The setting takes effect immediately and persists as fuzzy_skill_suggest in
$ZOT_HOME/config.json. Missing or false preserves the default prefix behavior.
You can turn it off at any time. Bold emphasis depends on terminal support.
zot expands the command into a user message containing the complete skill
body, its directory for resolving relative references, and any text following
the command as the request. This bypasses model-side skill selection.
Set disable-model-invocation: true in a skill's frontmatter when it should
only run after explicit user invocation. The skill remains visible in
/skills and available through /skill:<name>, but its name and description
are omitted from the model's startup context.
Writing good skills
- Be procedural. Number steps. Tell the model what to do in what
order. Skills are habits, not knowledge dumps.
- Be precise about boundaries. "Stop after step 4" is more
effective than "don't go too far".
- Trim aggressively. A 200-line skill bloats every turn the
model uses it. Aim for 20–80 lines.
- One skill per behaviour. Don't pack three workflows into one
SKILL.md; the model picks one path. Two separate skills work better.
- Lead with the trigger. First paragraph should make it
obvious when to use the skill so the model self-selects correctly.
Examples
See examples/skills/ for starter skills:
code-review/ — self-review pass on a recent diff
test-fix/ — diagnose + minimally fix a failing test
recursive/ — nested path-derived naming and explicit-name discovery
Comparison to other discovery layouts
| ecosystem |
path |
zot reads it? |
| (native) |
.zot/skills/<name>/SKILL.md |
yes |
| (claude-style) |
.claude/skills/<name>/SKILL.md |
yes |
| (agent-style) |
.agents/skills/<name>/SKILL.md |
yes |
Cross-pollination is intentional: pick whichever convention you're
already using and zot tags along.
source
1# zot skills
2
3A skill is a reusable instruction set written as a single
4`SKILL.md` file with a YAML frontmatter header. Skills may be supplied by
5an extension as well as by the normal skill directories. Unless a skill disables
6model invocation, zot discovers it at startup and surfaces it to the model
7in two ways:
8
91. The system prompt gains a short manifest:
10 `Available skills: ... - code-review — Run a self-review pass...`
112. A built-in `skill` tool lets the model load any one skill's full
12 body on demand.
13
14The on-demand-load model keeps token usage cheap: only the manifest
15goes into every request; the body is fetched as a tool result the
16one or two turns the model actually needs it.
17
18## Anatomy
19
20```markdown
21---
22name: code-review
23description: Run a thorough self-review pass on a recent change.
24allowed-tools: [read, bash]
25permissions:
26 bash: ["git diff*", "git log*"]
27---
28
29# Code review
30
31When asked to review code, ...
32```
33
34### Frontmatter fields
35
36| field | required | purpose |
37|---|---|---|
38| `name` | optional | skill identifier; defaults to the normalized relative directory path |
39| `description` | required | one-line summary shown in the system prompt |
40| `disable-model-invocation` | optional | when `true`, hide the skill from the model's startup manifest; invoke it explicitly with `/skill:<name>` |
41| `allowed-tools` | optional | list of tool names the skill is meant to use; informational |
42| `permissions` | optional | per-tool patterns; informational |
43
44`allowed-tools` and `permissions` are **parsed but not enforced** in
45this version. They appear in the rendered skill body so the model can
46see them and self-regulate. Future versions may enforce.
47
48The body (everything after the second `---`) is plain markdown.
49There's no template engine; the model sees what you write.
50
51## Discovery
52
53zot recursively looks in these directories, in priority order, and registers the
54first `SKILL.md` it finds for each unique name:
55
56| location | scope |
57|---|---|
58| `./.zot/skills/<name>/SKILL.md` | project (native) |
59| `$ZOT_HOME/skills/<name>/SKILL.md` | global (native) |
60| `./.claude/skills/<name>/SKILL.md` | project (claude-compat) |
61| `~/.claude/skills/<name>/SKILL.md` | global (claude-compat) |
62| `./.agents/skills/<name>/SKILL.md` | project (agent-compat) |
63| `~/.agents/skills/<name>/SKILL.md` | global (agent-compat) |
64
65The compat paths are deliberate: a `SKILL.md` written for an existing
66skill ecosystem works in zot unchanged. Drop your existing
67`.claude/skills/` or `.agents/skills/` directories into a project and
68zot will pick them up. When no frontmatter `name` is present, nested path
69components are lowercased and normalized to kebab-case and joined with `-`.
70Only files named exactly `SKILL.md` are read.
71
72Extensions namespace their skills, for example `git-tools:writing-git-commits`.
73Explicit `--ext` bundles take precedence over environment, project, global, and
74compatibility sources. Duplicate names keep the higher-precedence file and
75report a diagnostic. `--no-ext` omits implicit extension bundles;
76`--no-ext --ext PATH` loads only the explicitly named bundle. `--no-skill`
77disables all skills, including extension and built-in skills.
78
79When `XDG_STATE_HOME` is set on any platform, `$ZOT_HOME` defaults to
80`$XDG_STATE_HOME/zot`. Otherwise it defaults to `~/Library/Application Support/zot/`
81on macOS, `~/.local/state/zot` on Linux, or `%LOCALAPPDATA%\zot` on Windows.
82
83## Inspecting installed skills
84
85In zot, run `/skills`. A picker lists every discovered skill with its
86description and source path. Press enter on a row to view the full
87body inline. Press esc to go back.
88
89## Invoking skills
90
91For normal skills, the system prompt tells the model the skill names and
92short descriptions. When a request matches, the model calls the `skill` tool
93to load the full instructions on demand.
94
95To force a specific skill, invoke it as a slash command. Typing `/skill:` opens a filtered list of discovered user skills. Use the arrow keys to select one, `tab` to complete its name, or `enter` to invoke the highlighted skill.
96
97```text
98/skill:code-review
99/skill:code-review focus on security issues
100```
101
102By default, suggestions match case-insensitive name prefixes and are sorted
103alphabetically. Enable **fuzzy skill suggestions** in `/settings` to match
104characters in order anywhere in a skill name: `/skill:review` and `/skill:crv`
105can both find `code-review`. Results are ranked by relevance, with alphabetical
106tie-breaking, and matching characters are shown in bold, including in the
107selected row. Only names are searched, not descriptions or the `/skill:` prefix.
108An empty query still lists skills alphabetically; an exact name shows only that
109skill. Other slash-command suggestions and exact skill lookup during invocation
110are unchanged. Complete a fuzzy query before adding request text.
111
112The setting takes effect immediately and persists as `fuzzy_skill_suggest` in
113`$ZOT_HOME/config.json`. Missing or `false` preserves the default prefix behavior.
114You can turn it off at any time. Bold emphasis depends on terminal support.
115
116zot expands the command into a user message containing the complete skill
117body, its directory for resolving relative references, and any text following
118the command as the request. This bypasses model-side skill selection.
119
120Set `disable-model-invocation: true` in a skill's frontmatter when it should
121only run after explicit user invocation. The skill remains visible in
122`/skills` and available through `/skill:<name>`, but its name and description
123are omitted from the model's startup context.
124
125## Writing good skills
126
127- **Be procedural.** Number steps. Tell the model what to do in what
128 order. Skills are habits, not knowledge dumps.
129- **Be precise about boundaries.** "Stop after step 4" is more
130 effective than "don't go too far".
131- **Trim aggressively.** A 200-line skill bloats every turn the
132 model uses it. Aim for 20–80 lines.
133- **One skill per behaviour.** Don't pack three workflows into one
134 SKILL.md; the model picks one path. Two separate skills work better.
135- **Lead with the trigger.** First paragraph should make it
136 obvious *when* to use the skill so the model self-selects correctly.
137
138## Examples
139
140See `examples/skills/` for starter skills:
141
142- `code-review/` — self-review pass on a recent diff
143- `test-fix/` — diagnose + minimally fix a failing test
144- `recursive/` — nested path-derived naming and explicit-name discovery
145
146## Comparison to other discovery layouts
147
148| ecosystem | path | zot reads it? |
149|---|---|---|
150| (native) | `.zot/skills/<name>/SKILL.md` | yes |
151| (claude-style) | `.claude/skills/<name>/SKILL.md` | yes |
152| (agent-style) | `.agents/skills/<name>/SKILL.md` | yes |
153
154Cross-pollination is intentional: pick whichever convention you're
155already using and zot tags along.