Files
tai/skills.md
T
retoor 789f5206c4 docs: skills.md contract for the skill system and bundled set
- 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
2026-10-18 13:51:44 +02:00

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:

  • git got 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-research briefs 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.