Where skills live
Each skill is a directory containing aSKILL.md:
XYNTHIS_SKILLS_DIR to point somewhere else. A filesystem skill with the same name as a built-in shadows it, so you can override any default by writing your own copy. To get the built-ins onto disk where you can edit or delete them:
xynthis skills list, show <name>, and where inspect the library; xynthis skills search "<query>" runs the same matcher the agent uses, which is the fastest way to debug why a skill did or didn’t fire.
SKILL.md format
YAML frontmatter, then the body:name and description are required for matching. The other fields are optional:
activation_hints: exact phrases that should fire this skill. The strongest matching signal short of the user naming the skill.avoid_when: phrases that suppress the skill entirely, even if everything else matches. Case-insensitive substring match.scripts: executable files the skill exposes (see below).
activation-hints, avoid-when) are accepted too, and unknown frontmatter fields are ignored rather than rejected.
How activation works
At turn start, every skill’s description is scored against your input. Four signals add up:| Signal | Points |
|---|---|
| Shared meaningful word (≥3 chars, stopwords stripped) | 1 each |
| Shared two-word phrase | 3 each |
| Quoted trigger phrase from the description found in the input | 6 each |
activation_hints phrase found in the input | 8 each |
avoid_when hit removes the skill from consideration outright.
A top score of 6 or more is a strong match: the skill’s full body is injected into the prompt automatically, capped at 6,000 characters. Weaker matches are listed by name only, and the agent loads a body on demand with its skill tool.
Executable scripts
Skills can ship scripts, not just prose. Eachscripts entry maps an id to a file inside the skill’s directory; the agent lists them with skill(action="scripts") and runs one with skill(action="run"), passing arguments verbatim; there is no shell interpretation. If interpreter is set, the file runs as <interpreter> <file> <args>; otherwise it is executed directly, so it needs a shebang and the executable bit.
Script execution is bounded on purpose: the resolved script path is canonicalized and must stay inside the skill directory (.. escapes are rejected), runs time out after 60 seconds by default with a hard cap of 300, and output returned to the agent is capped at 8,000 bytes of stdout and 2,000 of stderr. Long-running work belongs in the agent loop, not a skill script.
Scripts can call back into the tool plane: xynthis tool recall --args '{"query": "..."}' dispatches any registered tool directly, and the running script gets the binary path in XYNTHIS_TOOL_BIN.
Auto-promotion: lessons become skills
Xynthis learns execution lessons as it works: failure-and-recovery records that climb a confidence ladder as they are re-confirmed. A lesson reaches durable only after being confirmed at least 4 times across at least 3 sessions with verification evidence. Durable lessons are exactly what a skill should be, so the agent (or you) can distill them:~/.xynthis/skills/<name>/SKILL.md, and never overwrites a skill that already exists on disk: hand-authored files win. A log at ~/.xynthis/skills_promoted.json records promoted lesson ids so repeat runs are no-ops.