Skills, rules, and commands
Skills
Two layouts:
- Flat:
skills/yaml-validator.md - Nested, for skills with attached resources:
skills/yaml-validator/SKILL.mdnext toskills/yaml-validator/schema.yaml
---
name: yaml-validator
description: Validate YAML against a schema.
---
# YAML Validator
1. Read target file
2. Parse YAML and compare against `schema.yaml`
3. Report violations as `path: message`
| Field | Required | Default | Description |
|---|---|---|---|
name | no | dir or filename | Skill identifier and output directory. Some targets restrict the format. |
description | no | empty | One-liner the model uses to decide whether to invoke the skill. |
model | no | unset | Claude Code model for the rest of the turn. Scalar or per-target map; x-claude.model wins. |
effort | no | unset | Claude Code effort for the rest of the turn. Scalar or per-target map; x-claude.effort wins. |
Other targets omit skill model and effort and report a coverage note when a value resolves for them. Use {claude: opus} to choose a model only for Claude. Global sync uses the same renderers; shared global directories omit target overrides.
Only SKILL.md and flat skills/*.md parse as skills. Every other file in a nested skill directory is a bundled asset (scripts, templates, fixtures, extra *.md). Assets copy verbatim to the same relative path under each target's skills dir. Import and sync preserve executable bits.
Most targets write <dir>/<name>/SKILL.md with assets. Several share .agents/skills/, so identical bytes write once. Targets with no skill surface flatten it to a skill-<name>.md rule and raise a coverage note, since assets cannot follow. Set outputs.<target>.emit-skills-as-commands: true to also emit a slash command. Each target page gives the exact directory.
disable-model-invocation support by target
Only the targets listed were checked. Setting it keeps a skill out of automatic model invocation; the user can still invoke it. Omitting it leaves each target's default, which is model-invocable everywhere below.
| Target | Behavior |
|---|---|
| Claude Code, Cursor | Written to SKILL.md |
| Codex | Written as allow_implicit_invocation: false to agents/openai.yaml. An explicit value in x-codex.policy or a bundled agents/openai.yaml wins |
| Crush | Dropped with a note. Set x-crush.disable-model-invocation |
| Factory | Dropped with a note. Set x-factory.disable-model-invocation |
Crush and Factory skills land in the shared .agents/skills/ tree, so emitting the key would hand it to targets with no such field. Use the x- key: a manual-only skill turning model-invocable is a safety boundary.
OpenHands' triggers is unrelated: it injects a skill on a keyword. Devin spells this restriction triggers: [user].
Rules
---
name: conventional-commits
description: Always use Conventional Commits format.
globs: "**/*"
alwaysApply: true
---
Use `feat:`, `fix:`, `docs:`, etc. Subject under 72 chars.
| Field | Required | Default | Description |
|---|---|---|---|
name | no | filename | Rule identifier. |
description | no | empty | Short summary. |
scope | no | project-wide | Project-relative directory and its descendants. Source-layout scope wins. A scope inside node_modules is refused. See scoped context. |
globs | no | target-dependent; new rule seeds **/* | Project-relative patterns, as a comma-separated string ("*.go,*.mod") or a list. A comma inside a brace set does not separate patterns, so "src/**/*.{ts,tsx}" is one pattern. With scope, the selector must stay inside the directory. new rule --scope omits it. |
paths | no | unset | File patterns, as a string or list. Scoped rules accept it with or instead of globs; see selector limits. |
alwaysApply | no | target-dependent; new rule seeds true | Requests unconditional activation. With scope, only inside the directory. new rule --scope omits it. |
Commands
Markdown with optional YAML frontmatter. Each spec becomes one native slash command.
---
name: deploy
description: Deploy the app to staging.
argument-hint: <env>
---
Deploy the app to {{env}}.
| Field | Required | Default | Description |
|---|---|---|---|
name | no | filename | Command identifier and slash name, such as /deploy. |
description | no | empty | One-liner shown in slash-command pickers. |
argument-hint | no | empty | Hint shown after the command, on Claude Code, Augment, and Factory. |
Any other frontmatter passes through. Put target-specific keys under x-<target>, for example x-claude.allowed-tools. Codex emits commands only when outputs.codex.commands-dir is set. Targets without a command surface log a warning and skip.