--- source_keys: - apm-cli-installed-source - apm-docs-llms-full --- # Authoring an apm instruction Reached from `SKILL.md` Step 1 for an instruction. Run the Gate, then write against the checklist, then return to `SKILL.md` Step 3. ## Gate An instruction is a scoped rule: it applies when the agent touches files matching its `applyTo` glob. On Claude it deploys to `.claude/rules/.md` with `applyTo` renamed to `paths:`. - **A rule for this repo alone** → it belongs in the repo's AGENTS.md, which is the single always-on source. Stop and hand to `agentsmd-author`. - **No file pattern fits** → an instruction without `applyTo` is always-on in every session of every repo that installs this package, and `apm compile` can fold it into the global sections of `AGENTS.md` and `CLAUDE.md` (CLAUDE.md is skipped when `.claude/rules/` is populated, AGENTS.md when `.github/instructions/` is, unless `--force-instructions`). Say exactly that to the user and continue only on an explicit yes. Legitimate when a package deliberately ships guidance to its consumers; never a default. - **Procedure the agent follows step by step** → a skill. Stop and hand to `skill-author`. - **A rule scoped to a file pattern** → continue. ## Checklist Copy `assets/templates/name.instructions.md.template` and drop `.template` only on the final path. Must: 1. The path is `.apm/instructions/.instructions.md`, directly in that directory, not a symlink or hardlink. 2. `description` is a non-empty string. Only `apm compile` warns when it is missing; `apm install` deploys it silently. 3. The body is non-empty after trimming whitespace. apm deploys an empty rule silently. 4. `applyTo` is a non-empty glob or comma-separated list — top-level commas only as separators, alternation inside `{}` (`"**/*.{ts,tsx}"`), braces and brackets balanced — or absent after the Gate's explicit yes. An empty `applyTo: ""` is neither. 5. The stem is unique across the package and its dependencies: a `.claude/rules/.md` collision is silently overwritten. Should: 6. Write `applyTo` as a scalar string, not a YAML list. Copilot receives the source verbatim, and its handling of a list is unverified. 7. Keep frontmatter to `description` and `applyTo`, plus optional `author` and `version`. No target consumes other keys, and Claude drops them. 8. Put any rationale Claude needs in the body. `description` never reaches Claude — it survives for Copilot and as index text in Cursor rules and compiled AGENTS.md/CLAUDE.md. 9. Keep relative markdown links resolvable from the source file. 10. Check the glob against the tree: one that matches nothing here fires only in consumer repos that have such files, and one broader than the rule's real scope spends context on every file it touches.