Skip to content

Compile your package

apm compile reads your instructions primitives from .apm/ (plus any unpacked under apm_modules/) and writes the per-harness root context files each agent harness reads at startup. It does not fetch packages, does not resolve dependencies, does not write the lockfile, and does not deploy other primitive types.

Terminal window
apm compile

Concretely, that command rolls your instructions/*.instructions.md (see Instructions) into the native rules surface each target expects:

  • AGENTS.md — the cross-harness root context file. Copilot, Codex, OpenCode, and Windsurf read it directly; Kiro primarily uses the .kiro/steering/ files that compile also emits.
  • CLAUDE.md — Claude Code’s root context file.
  • GEMINI.md — Gemini CLI’s root context file.
  • per-harness rules trees that mirror each instruction’s applyTo: glob: .github/instructions/, .claude/rules/, .cursor/rules/*.mdc, .windsurf/rules/, .kiro/steering/.

Other primitive types — prompts, skills, agents, hooks, commands — are NOT compiled by this command. They are deployed by apm install directly into the harness directories that consume them (.github/prompts/, .agents/skills/, .claude/commands/, etc.). For the full reach map, see Primitives and targets. For the place compile takes in the broader flow, see Lifecycle.

edit .apm/instructions/ -> apm compile -> inspect AGENTS.md -> repeat

You will run this loop while writing or refining instructions. Three flags speed it up:

Terminal window
apm compile --watch # re-run on every change
apm compile --validate # check frontmatter and structure; emit nothing
apm compile --dry-run # print placement decisions without writing files

--validate is the fastest signal that an instruction parses. --dry-run shows you exactly which root-context tree (AGENTS.md, CLAUDE.md, …) would be written where. --watch is the tight inner loop while you edit prose.

To preview a script that wraps a .prompt.md file, use apm preview instead. apm compile builds the root context files; apm preview shows the rewritten command line your script will execute.

By default apm compile detects targets from your workspace (see detection cascade below). Override it with --target (-t):

Terminal window
apm compile --target claude
apm compile --target copilot,cursor # comma-separated
apm compile --all # every canonical target

Accepted values: copilot, claude, cursor, opencode, codex, gemini, antigravity, windsurf, kiro, agent-skills, all. The agent-skills slug is a no-op for compile (skills are deployed by apm install); it is accepted in target lists for symmetry only. Unknown slugs are rejected before any work runs.

Experimental targets (hermes, openclaw, copilot-cowork, copilot-app) are deployment targets for apm install --target <flag> once enabled via apm experimental enable <flag>, and are excluded from --all. apm compile does not emit harness-specific output for them: Hermes and the other agents-family harnesses read the standard AGENTS.md your normal apm compile flow already produces. See Hermes Agent.

When you omit --target, APM resolves which targets to build in this order:

  1. Explicit --target <slug> flag.
  2. The targets: field in your apm.yml.
  3. Auto-detect: any harness root directory (.github/, .claude/, .cursor/, .codex/, .gemini/, .opencode/, .windsurf/, .kiro/) that already exists.
  4. Fallback: minimal — writes a single AGENTS.md and skips per- harness rules folders.

Pin targets: in apm.yml if you want the same compile output on every machine. Full rules and the per-target output map live in Primitives and targets.

Per target, with the rules shape on disk after compile:

TargetRoot context filePer-rule outputCompile required?
copilotAGENTS.md.github/instructions/<name>.instructions.md (preserves applyTo)No — Copilot reads the per-rule files natively; deduplicates with .github/instructions/ (see below)
claudeCLAUDE.md.claude/rules/<name>.mdYes — deduplicates with .claude/rules/ (see below)
cursor.cursor/rules/<name>.mdcYes — .mdc is Cursor’s rules format
codexAGENTS.md (folded)none — compile-only, no per-file deployYes — folded into AGENTS.md
geminiGEMINI.md (folded)none — compile-only, no per-file deployYes — folded into GEMINI.md
antigravityAGENTS.md (folded).agents/rules/<name>.mdYes — folded into AGENTS.md
opencodeAGENTS.md (folded)none — compile-only, no per-file deployYes — folded into AGENTS.md
windsurf.windsurf/rules/<name>.mdYes — compiled to Windsurf rules
kiroAGENTS.md (fallback).kiro/steering/<name>.mdYes — compiled to Kiro steering
You want to…Run
Iterate on instructions in .apm/instructions/apm compile
Deploy prompts, skills, agents, hooks, commands, MCPapm install (see Install packages)
Add a dependency or refresh apm_modules/apm install
Verify deployed bytes match the lockfileapm audit

apm install runs compile internally as part of its integrate phase, so a normal apm install on a clean checkout already produces correct AGENTS.md / CLAUDE.md / GEMINI.md output. Reach for apm compile directly when you are iterating on instructions and do not want install’s side effects.

By default apm compile overwrites AGENTS.md entirely. If your team keeps hand-written content in AGENTS.md alongside APM-managed rules, use managed-section mode to update only the APM-owned block while leaving everything else untouched.

For the full apm.yml key reference for compilation.agents_md, see the compilation.agents_md section in the manifest schema.

1. Add markers to AGENTS.md:

<!-- apm:start -->
<!-- apm will insert content here -->
<!-- apm:end -->

2. Enable the mode in apm.yml:

compilation:
agents_md:
mode: managed_section
start_marker: "<!-- apm:start -->"
end_marker: "<!-- apm:end -->"

The default markers are <!-- apm:start --> and <!-- apm:end -->, so you can omit start_marker and end_marker if you use those verbatim.

Constraints:

  • The target file must already exist: if it does not, APM raises a clear error (“does not exist yet”) instead of a confusing “markers not found”. Use mode: full for the first run to create the file, then switch to managed_section.
  • Both markers must be present in the file exactly once (missing or duplicate markers raise a loud error so no content is silently lost).
  • The start marker must appear before the end marker; reversed order raises a loud error.
  • start_marker and end_marker must be distinct non-empty strings.
  • Content outside the markers is preserved verbatim across every compile run for the root AGENTS.md; only the block between the markers is replaced.
  • In distributed compile mode, subdirectory AGENTS.md files remain fully APM-owned and are overwritten on each run.

Install a package once globally and root-context tools on your machine can pick up its instructions without per-project setup. For user-scope instructions, use the --global or -g flag:

Terminal window
apm compile --global
apm compile -g --dry-run

This reads global instructions from ~/.apm/apm_modules/ (instructions without applyTo: frontmatter) and writes user-scope root context files for root-context targets:

  • ~/.claude/CLAUDE.md (or $CLAUDE_CONFIG_DIR/CLAUDE.md)
  • ~/.codex/AGENTS.md
  • ~/.config/opencode/AGENTS.md
  • ~/.copilot/AGENTS.md
  • ~/.cursor/AGENTS.md
  • ~/.gemini/GEMINI.md

When a root file exists but contains no APM marker, it is treated as hand-authored and never overwritten. Use --dry-run to preview what would be written without modifying files.

  • Compilation is explicit. apm install -g (see Install packages) does not write root context files; it prints a one-line hint pointing at apm compile -g when global instructions land on a root-context-only target.
  • --global cannot be combined with project-output flags such as --target, --all, --watch, --root, or --output.
  • Compiled output is security-scanned before it is written. Critical findings stop the write and make apm compile -g exit non-zero.
  • Skills-only packages (no global instructions) do not write root files.
  • Confusing compile’s scope. Compile only handles instructions (and optionally a single agent to prepend via --chatmode). If you edit a prompt, skill, agent, hook, or command, apm compile will not redeploy it — run apm install for that.
  • Forgetting --target on a clean workspace. With no harness folder present and no targets: in apm.yml, the cascade falls back to minimal and writes only AGENTS.md. The CLI prints a hint, but the easy fix is to either create the harness folder or pin targets: in your manifest.
  • Stale AGENTS.md after deleting an instruction. Compile leaves previous output in place by default. Pass --clean to remove orphaned files generated by earlier runs. When compiling for the claude target, --clean also removes a stale APM-generated CLAUDE.md when deduplication suppresses CLAUDE.md entirely: all instructions already live in .claude/rules/, and no constitution or dependency content keeps CLAUDE.md active. Hand-authored CLAUDE.md files (those without the <!-- Generated by APM CLI --> marker) are never deleted.
  • Hand-edited primitives skip the security scan. apm compile does not run the install-time hidden-Unicode scan. After hand-edits, run apm audit before publishing. See drift and secure-by-default.
  • Zero-output success. If compile reports success but writes no files, your project either has no instructions, or every requested target was rejected. The CLI surfaces this as a warning — check targets: and the contents of .apm/instructions/.

Once your instructions compile cleanly into the harnesses you care about, package the result with apm pack and share it via a marketplace.