# Skill mechanics

The skill-specific branch of [`writing-for-agents`](SKILL.md): what changes when the document is a
skill. Everything else about writing it is the universal reference in `SKILL.md`.

## Where a skill lives

A personal skill lives **once**, at `~/.agents/skills/<name>/`, with Claude Code pointed at it by a
symlink:

```bash
ln -s ../../.agents/skills/<name> ~/.claude/skills/<name>
```

`~/.agents/skills/` is the cross-runtime home: Codex, Copilot CLI, and Gemini CLI read it directly.
Writing a second copy into `~/.claude/skills/` gives you two files that drift, and the drift is
silent because each harness only ever reads its own. One home, one symlink per harness that needs it.

A skill that only makes sense inside one repo belongs in that repo, at `<repo>/.claude/skills/`.

## Frontmatter

```yaml
---
name: writing-for-agents          # letters, numbers, hyphens only; matches the directory name
description: Use when ...          # the skill's top-level context pointer
disable-model-invocation: true     # Claude Code only; omit unless the skill is user-invoked
---
```

The whole frontmatter block caps at 1024 characters, so the description is the budget. Write it in
the third person: it is injected into the system prompt, not read as a reply.

The description is a context pointer, so every pointer rule in `SKILL.md` applies to it in full: name
the material and its trigger branches, front-load the leading word, one trigger per branch, and never
summarize the process.

## Codex metadata

Each skill also carries `agents/openai.yaml` beside its `SKILL.md`, holding Codex's skill-picker
metadata and, for a user-invoked skill, its half of the invocation setting:

```yaml
interface:
  display_name: Writing for Agents
  short_description: Reference for writing skills, AGENTS.md/CLAUDE.md, and pointed-at docs.
policy:
  allow_implicit_invocation: false   # user-invoked only; omit for model-invoked skills
```

**Invocation is set in two places, and they must agree.** `disable-model-invocation: true` governs
Claude Code; `policy.allow_implicit_invocation: false` governs Codex. A skill is user-invoked in both
harnesses or neither. Setting only the Claude Code half leaves the skill quietly model-invocable in
Codex, which is the same drift as two copies of the file, one field wide.

## Invocation

Two choices, trading the two loads:

| | Model-invoked | User-invoked |
|---|---|---|
| Who can fire it | The agent, you, or another skill | Only you, typing `/name` |
| Claude Code | Omit `disable-model-invocation` | `disable-model-invocation: true` |
| Codex | Omit the `policy` block | `policy.allow_implicit_invocation: false` |
| Description | Model-facing, carries trigger branches | Human-facing one-liner, triggers stripped |
| Cost | Permanent context load | Zero context load, paid in cognitive load |

Model-invocation always *includes* your reach: a description only ever adds agent discovery, it never
removes yours. So the question is only whether the agent must reach the skill on its own, or another
skill must. If it only ever fires by hand, make it user-invoked and pay no context load.

A model-invoked skill whose content is all reference is also the one home for shared reference:
several skills can invoke it, so the material lives in one place.

Shared reference that two *user-invoked* skills both need can live in neither, since with no
descriptions neither can fire the other. Push it to a plain file outside the skill system and point
at it from both.

## Calling one skill from another

Write the dependency as an explicit instruction to call the tool, not a bare slash-name left for the
model to interpret:

> Call the Skill tool with "grilling".

The tool takes one skill per call. A step needing two is two calls, and saying "call it with X and Y"
reads as a single call taking both. Say instead:

> Call the Skill tool twice, for "grilling" and "domain-modeling".

This only works on **model-invoked** skills. A user-invoked skill can never be reached this way. When
a step's precondition is a user-invoked skill, phrase it as an instruction for the human: "tell the
user to run `/ticket`", never as a tool call.

Router prose that just names skills for a human to pick from is not invoking anything, so it keeps
`/name` labels as plain text.

## Splitting by invocation

The invocation cut, alongside the branch and sequence cuts in `SKILL.md`: split off a model-invoked
skill when you have a distinct leading word that should trigger it on its own, a word you actually
use in your prompts, or when another skill must reach it. You pay context load for the new
always-loaded description, so that independent reach has to be worth it.

## Router skills

When user-invoked skills multiply past what you can remember, that piled-up cognitive load is cured
by a **router skill**: one user-invoked skill naming the others and when to reach for each, so you
have one name to remember instead of many. It can only hint, never fire them, since user-invoked
skills have no description for anything but you to reach.

Write the router when you notice yourself forgetting a skill exists, not before. A router over three
skills is furniture.

## Done when

- The skill exists once under `~/.agents/skills/`, with a symlink from `~/.claude/skills/`.
- `name` matches the directory and uses only letters, numbers, and hyphens.
- The description names the material and its triggers, in the third person, under the 1024-character
  frontmatter cap.
- The invocation choice is deliberate: model-invoked because the agent or another skill must reach
  it, user-invoked otherwise.
- The invocation choice is written in both harnesses' fields, or in neither.
- Every cross-skill dependency is a named Skill tool call to a model-invoked skill, or an instruction
  for the human where the target is user-invoked.
