0013 Skills On Disk Layout
ADR 0013: Skills on-disk layout
Date: 2026-05-27 Status: Accepted Deciders: Construct·Engineer
Context
Skills live under skills/\<category>/\<name>.md as plain markdown files. As
Construct has expanded to support multiple agent runtimes (Claude Code, Codex,
OpenCode, Copilot), a cross-tool standard has emerged: the SKILL.md directory
format. In this format a skill is a directory \<name>/ that contains a
SKILL.md file and may contain additional artifacts (scripts, fixtures, tests).
Two problems existed before this decision:
- Skills were only synced to
.claude/skills/duringconstruct sync. Codex agents at$HOME/.agents/had no access to the same skills. - The flat
\<name>.mdform prevents a skill from bundling any supporting files alongside its documentation.
Decision
Source of truth stays at skills/
The canonical skill files are skills/\<cat>/\<name>.md (existing) or
skills/\<cat>/\<name>/SKILL.md (new directory form). Neither .claude/skills/
nor .agents/skills/ is a source of truth. Both are derived sync targets and
must never be hand-edited.
SKILL.md is the cross-tool standard
New skills should use the directory form (skills/\<cat>/\<name>/SKILL.md).
Existing flat files (skills/\<cat>/\<name>.md) remain valid for one minor
release. The migration script scripts/migrate-skills-to-skill-md.mjs
converts them on demand with --apply.
Both .claude/skills/ and .agents/skills/ are sync targets
construct sync writes each skill to:
~/.claude/skills/\<cat>/\<name>/SKILL.md~/.agents/skills/\<cat>/\<name>/SKILL.md
Both targets receive identical content prepended with a # Generated by construct sync header. The header is the canonical marker that a file was
produced by sync and should not be edited in place.
Loader falls back to flat form for one minor release
lib/mcp/tools/skills.mjs resolves a skill id by checking candidates in order:
skills/\<path>.md(existing flat form)skills/\<path>/SKILL.md(new directory form)
The first path that exists wins. This fallback is removed in the next minor release after the migration script has been run.
This decision does not relocate the source of truth
Skills stay under skills/ in the Construct repository. Moving source files to
.claude/skills/ or .agents/skills/ would invert the sync direction and
break the "derived targets are never hand-edited" invariant.
Consequences
Positive
- Skills are available to all supported runtimes after a single
construct sync - The directory form lets a skill bundle scripts or fixtures alongside its docs
- A single migration script handles the cut-over safely and idempotently
- The fallback loader means no agent breaks on the first day of rollout
Negative
- Two on-disk representations exist during the transition window
audit-skills.mjsandvalidators/skills.mjsmust eventually be updated to understand the directory form (tracked as a follow-up)
Mitigation
scripts/migrate-skills-to-skill-md.mjs --dry-runmakes the transition scope visible before any files are touched- The fallback in the loader is explicitly temporary; its removal is a named gate in the next minor release
- Sync targets are gitignored in user home directories and regenerated on
every
construct sync, so a bad write is always recoverable