- discovery/frontmatter contract incl. the bare->/| subset limit - bundled table with upstream provenance and adaptation rules - install target semantics, sidecar shape, maintenance workflow - wired in AGENTS.md, README layout; drift test in BundledSkillsTests
6.8 KiB
skills.md
The skill system and the bundled default skills: discovery contract, frontmatter subset, the six shipped skills with their upstream provenance and tai adaptations, install semantics, and maintenance.
The system
Skills are directories containing a SKILL.md file with name plus
description frontmatter, optionally with scripts/, references/, and
assets/ alongside (the open Agent Skills layout). Discovery
(discover_skills) scans four roots and the most tai-specific one wins a
name collision: ~/.claude/skills and <project>/.claude/skills /
<project>/.agents/skills first (external, read-only interop), then
~/.tai/skills and <project>/.tai/skills (managed).
load_skill returns the body plus a provenance note plus the absolute
paths of the top-level entries under scripts/, references/, and
assets/ (skill_extra_files, not recursive: a nested directory shows up
as its own path and the agent descends from there). Descriptions ride the
system-prompt catalog truncated to 300 characters; bodies load on demand.
Frontmatter is a deliberate subset, not YAML (parse_skill_front): one
key: value per line, double-quoted values have their outer quotes
stripped, unknown keys are ignored, and only bare > (fold with spaces)
and | (join with newlines) continue a value onto indented lines.
Chomping variants (>-, |-, >+, |+) do NOT parse: a >-
description reads back as the literal string ">-" and the folded lines
are dropped. Shipped skills must use single-line descriptions.
Missing skills with a SKILL_BLUEPRINTS entry are researched and built on
first load_skill (bot-creator, api-client, web-researcher,
pdf-forms, data-wrangler, home-sysadmin); anything else is an
"unknown skill" error listing what exists.
Bundled skills
Six skills ship inside tai.py itself (BUNDLED_SKILLS, 21 files) so a
bare copy installs them anywhere. Upstream provenance per skill lives in
BUNDLED_SKILL_UPSTREAM and is copied into each installed sidecar.
| Skill | Files | Upstream | Status |
|---|---|---|---|
deep-research |
6 (SKILL.md, 4 references/, UPSTREAM.md) |
author's Muse user skill (itself from wanqingying/debian-railway, see UPSTREAM.md) |
adapted |
seriousdevelopment |
10 (SKILL.md, CHANGELOG.md, 8 assets/templates/) |
author's Muse user skill v1.7.1 | verbatim |
git |
2 (SKILL.md, scripts/workspace-recovery.sh) |
Muse's bundled set | adapted |
plan |
1 (SKILL.md) |
Muse's bundled set | adapted |
requirements-clarification |
1 (SKILL.md) |
Muse's bundled set | adapted |
taste |
1 (SKILL.md) |
Muse's bundled set | one word |
seriousdevelopment is byte-identical to upstream: it carries no host
references and no em dashes. Everything else changed only where the host
leaks through; the method prose is untouched.
Adaptation rules
Each rule below was applied everywhere its token appeared, and
BundledSkillsTests.test_embedded_content_guards fails if any of them
regresses:
| Upstream token | Tai equivalent | Why |
|---|---|---|
read_skill |
load_skill |
tai's loader is named load_skill |
request_user_input / request_user_input_async (+ auto_resolution_ms) |
ask_user (question plus options, blocks; unavailable to workers and autonomous mode, decide and state the assumption there) |
tai's only question tool blocks and has no async form |
subagent / Task / explore workers, wait-call mechanics |
fork (task plus timeout up to one hour) / poll (up to two minutes per call, loop until done); workers get 12 steps, no questions, nesting depth 2, 8 live max |
tai's orchestration primitives and their real caps |
curl recipes, curl commands |
web_fetch GET with the same URL and headers |
tai forbids curl and wget via shell; every recipe is a plain GET so nothing is lost (auth_secret covers the token case) |
webfetch / websearch |
web_fetch / web_search |
tai's tool names |
/plan, /skill plan |
prose request or load_skill |
tai has no slash-command skill routes |
>- folded description |
single-line description | the frontmatter subset (above) |
| em dash (U+2014) | hyphen | project prose rule, no exceptions |
Two judgment calls beyond mechanical mapping:
gitgot an "Authorization in tai" paragraph: its never-commit rule would otherwise veto the user's standing auto-commit rule, so history writes follow the session's approval setting while the recovery snapshot, lock discipline, and named-files rules still apply as written. The<git-skill-dir>placeholder became<recovery>, bound to the absolute script path from the bundled-files list.deep-researchbriefs still hand workers literal URLs even though tai workers could read the skill directory: inline URLs keep briefs self-contained under the 12-step budget.
Install target
skills is the twelfth INSTALL_TARGETS entry, implemented by
op_skills on top of write_bundled_skill / remove_bundled_skill,
included in bare ./tai.py --install and refreshable via the install
tool or /install. All six land in home scope (~/.tai/skills); project scope
never receives bundled skills. After any non-status action through the
tool, the live session re-runs discovery so the skills are usable without
a restart.
| Action | Semantics |
|---|---|
install |
writes missing skills only; a present SKILL.md means "already present", never an overwrite |
upgrade |
rewrites files that are missing or already equal; differing files are kept untouched and named loudly (kept modified) |
reinstall |
force-rewrites every tracked file, including user edits; user-added extra files still survive |
uninstall |
removes tracked files that still match (plus orphan sidecars); user-modified and user-added files stay, named loudly, with their sidecar |
status |
one line: skills: P/6 bundled present, plus missing: and modified: lists when non-empty |
The .installs/<name>.json sidecar records source: tai-bundled,
mode: bundled, scope: home, the upstream locator, the
bundled_version that wrote it, per-file sha8 files, and
installed_at. load_skill renders this as [installed bundled, home scope, from tai-bundled]. The sidecar is rewritten only when a write
leaves zero kept files, so user edits are never re-baselined as
pristine behind their back.
Maintenance
The embedded copies ARE the source: fix typos and drift directly in
BUNDLED_SKILLS, never by re-copying upstream over them (re-copying
would silently drop the adaptations above). To pull a new upstream
version of one skill: diff upstream against the embedded copy, re-apply
the adaptation rules to the new text, re-embed, and confirm the guard
test plus a fresh install round-trip. Raw strings keep backslashes
byte-exact, so no embedded file may contain a triple-double-quote or
end in a backslash; the guard test enforces the quote half.