Chapter 13 · Two-Layer Skill System and Custom Extensions
Chapter goals: Understand the two-layer layout difference between
.agents/skills/internal skills andskills/public skills, master the SKILL.md structure规范, and tour thebin/toolbelt to lay the foundation for writing custom skills.
13.1 Two-Layer Layout: Why Skills Are Split
Open the FirstMate repo and you'll find skills stored in two different directories:
firstmate/
├── .agents/skills/ # Agent-loaded internal skills (~20)
│ ├── afk/SKILL.md
│ ├── ahoy/SKILL.md
│ ├── bearings/SKILL.md
│ ├── stow/SKILL.md
│ ├── secondmate-provisioning/SKILL.md
│ └── ...
└── skills/ # Public, installer-facing standalone skills
└── stow/SKILL.md # Currently the only oneThis split is not arbitrary组织 — it is determined by audience:
.agents/skills/: loaded by the firstmate itself. Each assumes "a live firstmate home exists" — without this context they are meaningless,甚至 actively misleading. For example, thesecondmate-provisioningskill references paths, tools, and vocabulary that only make sense inside a firstmate home.skills/: public, independently-installable skills, designed to work in any project without依赖 any firstmate私有 paths, tools, or vocabulary.
An interesting detail: the stow "twin" design. .agents/skills/stow and skills/stow are two deliberately independent files with零 shared code. The official maintenance comment reads: keep them independent — each evolves without拖拽 the other. The internal version writes the firstmate home's operational记忆 and cascades to secondmates; the public version routes through a three-level rule chain: explicit instruction → local convention → private .stow-notes.md fallback — toany project.
13.2 metadata.internal: true — Invisible to Installers
Comparing the two stow frontmatters reveals the关键差异:
# .agents/skills/stow/SKILL.md (internal version)
---
name: stow
description: Sweep the current session for uncaptured durable knowledge...
user-invocable: true
metadata:
internal: true # ← internal flag
---# skills/stow/SKILL.md (public version)
---
name: stow
description: Sweep the current conversation for durable knowledge...
user-invocable: true # ← no metadata.internal
---The purpose of metadata.internal: true: it causes installers like npx skills add to skip the skill during discovery — internal skills should not be installed elsewhere. Meanwhile, it is完全 inert to the firstmate's own skill loader (frontmatter metadata is inert to the loader): loading and trigger points proceed normally.
This is the两层的 safety mechanism: visibility is determined by audience; loading behavior is determined by trigger points.
13.3 SKILL.md Anatomy and Trigger Points
Each skill's核心 is a SKILL.md file with three parts:
---
name: bearings # Globally unique skill name
description: Generate a concise four-section chat digest...
user-invocable: true # Whether可被用户直接调用
metadata:
internal: true # Only carried by internal skills
---
<!-- Maintainer注释区 -->
# bearings
Body: methodology, steps, boundary constraints…
The agent loads the full text and follows executionwhen the trigger点 hits.Two trigger点 categories:
- User invocation (
user-invocable: true): the captain types/ahoy,$stowetc.; - Agent-only reference: skills without the user-invocable mark (e.g.,
ask-user-authority,captain-hold-lifecycle,diagnostic-reasoning,harness-adaptersetc.) are named and loaded按需 by AGENTS.md at specific程序节点.
13.4 Methodology for Writing Custom Skills for FirstMate
Based on the structure above, the思路 for adding a custom skill to firstmate is clear:
1. Judge the audience:
- Depends on FM_HOME/state/projects等 firstmate context?
→ Place in .agents/skills/ and加 metadata.internal: true
- Usable in any project?
→ Consider a standalone skill under skills/
2. Write SKILL.md:
- name unique; description clearly states when totrigger
- Body writes executable methodology, not空泛 description
3. Explicitly write边界:
- Internal skills can onlypersist through FirstMate's既有所有权 and写入边界
4. Test: the repo自带行为测试运行器 fm-test-run.sh可验证One important discipline from official maintenance comments: public skills must remain standalone — no私有 project paths, tool assumptions, or environment branch logic.
13.5 bin/ Toolbelt Tour
Skills负责 "知道怎么做"; the dozens of scripts under bin/负责 "真正去做". The official docs/scripts.md gives a full清单; here we认识 the core batch by职能:
Session lifecycle
├── fm-session-start.sh # Composes lock/bootstrap/wake-drain into a single ordered digest
├── fm-bootstrap.sh # Toolchain self-check + install approved missing tools
├── fm-teardown.sh # Owner of the landed-work完整性测试 (Hard Rule 3)
└── fm-send.sh # Send messages to tasks; fail closed if FM_HOME is不明确
Task dispatch and briefs
├── fm-spawn.sh # Spawn crewmates/scouts/batches/secondmates
├── fm-brief.sh # Scaffold ship/scout/charter briefs (--mode explicitly specified)
└── fm-captain-hold.sh # Suspend task waiting for captain decision; record answer; gate completion
Supervision engine
├── fm-watch.sh # Singleton-safe常驻 watcher (Chapter 11)
├── fm-turnend-guard.sh # No-turn-ends-blind判定谓词 (Chapter 11)
└── fm-guard.sh # Pull-style mid-course warnings
Config and merge
├── fm-config-push.sh # Push declared inheritance materials to local/remote secondmates
├── fm-merge-local.sh # Captain-approved fast-forward merge for local-only projects
└── fm-project-mode.sh # Parse project delivery posture from data/projects.mdTwo使用要点 worth单独强调:
First, fm-send.sh's fail-closed design: if FM_HOME is不明确, the send直接失败 rather than guessing the target — this prevents a steer from silently landing in the wrong home. It is the "multi-home isolation"原则 reflected at the script层.
Second, read the header before using: docs/scripts.md gives only a one-line用途概括 per script; the script's own头部注释is the权威描述 of its behavior, flags, and contract. The official反复强调 read the header before first use.
Also note fm-decision-hold.sh's特殊性: it is a one-release兼容垫片 (shim) that映射 the retired decision command to fm-captain-hold.sh —说明这套工具带本身也在演进; when encountering an old command, check for a shimfirst.
13.6 Chapter Summary
- Two-layer skill system:
.agents/skills/for内部 skills that依赖 the firstmate home context;skills/for零-dependency public skills; metadata.internal: truemakes内部 skills invisible to installers like skills.sh, while不affecting the firstmate's own loader (frontmatter metadata is inert to the loader);- SKILL.md = frontmatter (name/description/user-invocable/metadata) + methodology body; trigger points分 user slash-calls and AGENTS.md-named agent-only loads;
- Writing custom skills: judge audience first, then位置; public skills必须 standalone; internal skills must走既有写入边界;
bin/is the execution toolbelt: fm-send.sh's FM_HOME fail-closed and "read the header before using" are the two most important使用纪律.
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. Why do skills in .agents/skills/ carry metadata.internal: true?
2. What determines whether a skill is user-invocable or agent-only?
3. What is the key difference between .agents/skills/stow and skills/stow?
4. What does fm-send.sh do if FM_HOME is not set?
🛠️ Hands-On Exercises
- List all skill directories under
.agents/skills/; check each frontmatter formetadata.internal: trueanduser-invocable: true; organize into a two-column table (user-invocable / agent-only) and对照 Chapter 12's five built-in skills. - Compare-read the bodies of
.agents/skills/stow/SKILL.mdandskills/stow/SKILL.md; find at least threebehavioral differences caused by different audiences; write a short comment explaining why the官方坚持零共享代码. - Pick three
bin/fm-*.shscripts you care about (建议含 fm-send.sh); read each header注释; summarize the usage contract (parameters, env requirements, failure behavior) in your own words; corroborate against the one-line概括 in docs/scripts.md.
Two-layer skills understood. Next, Secondmate: persistent isolated deputy and charter.