-
Notifications
You must be signed in to change notification settings - Fork 132
docs: rewrite first-package tutorial, fix anatomy hallucination #866
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,117 +1,280 @@ | ||
| --- | ||
| title: "Your First Package" | ||
| description: "Create, publish, and install your first APM package in minutes." | ||
| description: "Build a real APM package with a skill and an agent, install it, and ship it as a plugin." | ||
| sidebar: | ||
| order: 3 | ||
| --- | ||
|
|
||
| This tutorial walks you through creating an APM package from scratch, publishing it, and installing it in another project. | ||
| In about ten minutes you will scaffold an APM package, add a skill that | ||
| auto-activates inside Copilot or Claude, add a custom agent that pairs with | ||
| it, install both into a project, and ship the result as a plugin. No prompts, | ||
| no `cat <<EOF`, no compile step you do not need. | ||
|
|
||
| If you want the conceptual map first, read [Anatomy of an APM Package](../../introduction/anatomy-of-an-apm-package/). | ||
| Otherwise, start here. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - APM installed ([Installation guide](/apm/getting-started/installation/)) | ||
| - A GitHub account and a repository to publish to | ||
| - APM installed -- see [Installation](/apm/getting-started/installation/). | ||
| - A GitHub account and an empty repo for publishing (step 5). | ||
| - A runtime where you can try the result: GitHub Copilot, Claude Code, or | ||
| Cursor. | ||
|
|
||
| ## 1. Scaffold the Package | ||
| ## 1. Scaffold | ||
|
|
||
| ```bash | ||
| apm init my-coding-standards | ||
| cd my-coding-standards | ||
| apm init -y team-skills | ||
| cd team-skills | ||
| ``` | ||
|
|
||
| This creates: | ||
| `apm init` creates exactly one file -- the manifest. The `.apm/` source tree | ||
| is yours to author. | ||
|
|
||
| ``` | ||
| my-coding-standards/ | ||
| └── apm.yml # Package manifest | ||
| team-skills/ | ||
| +-- apm.yml | ||
| ``` | ||
|
|
||
| Open `apm.yml` and give it a real description. The rest of the manifest is | ||
| already correct: | ||
|
|
||
| **`apm.yml`** | ||
|
|
||
| ```yaml | ||
| name: team-skills | ||
| version: 1.0.0 | ||
| description: Skills and agents for our team's review workflow | ||
| author: your-handle | ||
| dependencies: | ||
| apm: [] | ||
| mcp: [] | ||
| scripts: {} | ||
| ``` | ||
|
|
||
| > **Note:** By default, `apm init` creates only `apm.yml`. The directory structure below is what you build manually in the following steps. See [Anatomy of an APM Package](../../introduction/anatomy-of-an-apm-package/) for what `.apm/` is and why files live there. | ||
| ## 2. Add a skill | ||
|
|
||
| ## 2. Add an Instruction | ||
| A **skill** is a chunk of expertise that the runtime activates automatically | ||
| based on its `description`. No slash command, no manual selection: the agent | ||
| sees the description, decides the skill is relevant, and pulls it in. That | ||
| auto-activation is what separates skills from prompts. | ||
|
|
||
| Create a coding standard that applies to all Python files: | ||
| Create one for drafting pull-request descriptions: | ||
|
|
||
| ```bash | ||
| cat > .apm/instructions/python.instructions.md << 'EOF' | ||
| **`.apm/skills/pr-description/SKILL.md`** | ||
|
|
||
| ```markdown | ||
| --- | ||
| applyTo: "**/*.py" | ||
| name: pr-description | ||
| description: >- | ||
| Activate when the user asks for a pull-request description, a summary of | ||
| uncommitted changes, or release notes. Use when preparing to open a PR or | ||
| when the user says "draft a PR description for me". | ||
| --- | ||
| # Python Standards | ||
| - Use type hints for all function parameters and return values | ||
| - Follow PEP 8 style guidelines | ||
| - Write docstrings for all public functions | ||
| - Prefer `pathlib.Path` over `os.path` | ||
| EOF | ||
| # PR Description Skill | ||
|
|
||
| Produce a PR description with these sections, in order: | ||
|
|
||
| ## Summary | ||
|
|
||
| One sentence. What changes and why. No file lists, no implementation detail. | ||
|
|
||
| ## Motivation | ||
|
|
||
| Two to four sentences. The problem this solves or the capability it adds. | ||
| Link to the issue or design doc if one exists. | ||
|
|
||
| ## Changes | ||
|
|
||
| Bullet list grouped by area (e.g. "API", "Tests", "Docs"). One bullet per | ||
| logical change, not per file. | ||
|
|
||
| ## Risk and rollback | ||
|
|
||
| Note any breaking changes, migrations required, or feature flags. | ||
| Mention how to revert if something breaks. | ||
|
|
||
| ## Testing | ||
|
|
||
| How you verified the change. Commands run, environments tested. | ||
| ``` | ||
|
|
||
| ## 3. Add a Prompt | ||
| The frontmatter `description` is a contract with the runtime: write it as | ||
| "activate when ...". The body is the operating manual the agent reads when | ||
| the skill fires. | ||
|
|
||
| Create a reusable slash command: | ||
| > Want to inspect a real one? The skill that governs this CLI's own | ||
| > architecture decisions lives at | ||
| > [`.apm/skills/python-architecture/SKILL.md`](https://github.com/microsoft/apm/blob/main/.apm/skills/python-architecture/SKILL.md) | ||
| > in this repo. Same shape, different concern. | ||
|
|
||
| ```bash | ||
| cat > .apm/prompts/security-audit.prompt.md << 'EOF' | ||
| See the [Skills guide](/apm/guides/skills/) for the full schema. | ||
|
|
||
| ## 3. Add a custom agent | ||
|
|
||
| A **custom agent** (`.agent.md`) is a named expert your runtime can invoke | ||
| directly. While skills auto-activate based on context, agents are summoned | ||
| on demand -- typically with `@agent-name`. | ||
|
|
||
| Pair the skill with a reviewer agent that critiques the diff before the PR | ||
| goes out: | ||
|
|
||
| **`.apm/agents/team-reviewer.agent.md`** | ||
|
|
||
| ```markdown | ||
| --- | ||
| description: Run a security audit on the current file | ||
| name: team-reviewer | ||
| description: Senior reviewer that critiques diffs against team standards before PR submission. | ||
| --- | ||
| Review this code for common security issues: | ||
| 1. Input validation and sanitization | ||
| 2. Authentication and authorization checks | ||
| 3. Sensitive data exposure | ||
| 4. SQL injection and XSS vulnerabilities | ||
| Provide specific line numbers and suggested fixes. | ||
| EOF | ||
| # Team Reviewer | ||
|
|
||
| You are a senior engineer reviewing a teammate's diff before it becomes | ||
| a pull request. Your job is to catch the things that waste reviewer | ||
| time downstream. | ||
|
|
||
| ## What to check, in order | ||
|
|
||
| 1. **Correctness.** Does the code do what its commit message claims? | ||
| Spot logic errors, off-by-ones, unhandled error paths. | ||
| 2. **Tests.** Are the changed code paths covered? Are new public APIs | ||
| exercised by at least one test? Flag missing coverage explicitly. | ||
| 3. **Naming and clarity.** Are names accurate? Would a new contributor | ||
| understand this in six months? | ||
| 4. **Surface area.** Does this change export anything new? If yes, is | ||
| that intentional and documented? | ||
|
|
||
| ## Output format | ||
|
|
||
| Group findings by severity: **Blocking**, **Should fix**, **Nit**. | ||
| For each finding, cite the file and line. End with a one-line verdict: | ||
| "Ready to ship", "Address blockers then ship", or "Needs another pass". | ||
|
|
||
| Do not rewrite the code yourself. Point and explain. | ||
| ``` | ||
|
|
||
| ## 4. Update the Manifest | ||
| > A real example: this repo's documentation agent lives at | ||
| > [`.apm/agents/doc-writer.agent.md`](https://github.com/microsoft/apm/blob/main/.apm/agents/doc-writer.agent.md). | ||
|
|
||
| Edit `apm.yml` to describe your package: | ||
| See the [Agent Workflows guide](/apm/guides/agent-workflows/) for more. | ||
|
|
||
| ```yaml | ||
| name: my-coding-standards | ||
| version: 1.0.0 | ||
| description: Team coding standards and security prompts | ||
| ## 4. Deploy and use | ||
|
|
||
| Run install with no arguments. APM treats your repo as the package and | ||
| deploys its `.apm/` content into the runtime directories your tools read: | ||
|
|
||
| ```bash | ||
| apm install | ||
| ``` | ||
|
|
||
| ## 5. Publish | ||
| Output: | ||
|
|
||
| ``` | ||
| [+] <project root> (local) | ||
| |-- 1 agent integrated -> .github/agents/ | ||
| |-- 1 skill(s) integrated -> .github/skills/ | ||
| [i] Added apm_modules/ to .gitignore | ||
| ``` | ||
|
|
||
| Your tree now has source on the left and runtime-ready output on the right: | ||
|
|
||
| ``` | ||
| team-skills/ | ||
| +-- .apm/ # source you edit | ||
| | +-- skills/ | ||
| | | +-- pr-description/SKILL.md | ||
| | +-- agents/ | ||
| | +-- team-reviewer.agent.md | ||
| +-- .github/ # generated by apm install | ||
| | +-- skills/ | ||
| | | +-- pr-description/SKILL.md | ||
| | +-- agents/ | ||
| | +-- team-reviewer.agent.md | ||
| +-- apm.yml | ||
| +-- apm.lock.yaml | ||
| ``` | ||
|
|
||
| Push to a git repository: | ||
| `apm install` auto-detects which runtimes you have. The example above shows | ||
| `.github/` because Copilot is the default fallback. If `.claude/`, `.cursor/`, | ||
| or `.opencode/` exists in the project, they get populated too. To target | ||
| explicitly, see the [Compilation guide](/apm/guides/compilation/). | ||
|
|
||
| > **What about `apm compile`?** Compile is a different concern: it | ||
| > generates merged `AGENTS.md` / `CLAUDE.md` files for tools that read a | ||
| > single top-level context document (Codex, Gemini, plain `agents`-protocol | ||
| > hosts). Copilot, Claude Code, and Cursor read the per-skill directories | ||
| > directly -- no compile step needed. | ||
|
|
||
| Now open Copilot or Claude in this project. Ask "draft a PR description for | ||
| my last commit". The `pr-description` skill activates on its own. To get the | ||
| review pass, type `@team-reviewer review my staged changes`. | ||
|
|
||
| ## 5. Publish as a package | ||
|
|
||
| Push to GitHub: | ||
|
|
||
| ```bash | ||
| git init | ||
| git add . | ||
| git commit -m "Initial APM package" | ||
| git remote add origin https://github.com/you/my-coding-standards.git | ||
| git add apm.yml .apm/ | ||
| git commit -m "Initial team-skills package" | ||
| git remote add origin https://github.com/your-handle/team-skills.git | ||
| git push -u origin main | ||
|
Comment on lines
214
to
219
|
||
| ``` | ||
|
|
||
| ## 6. Install in Another Project | ||
| In any other project's `apm.yml`: | ||
|
|
||
| In any project: | ||
|
|
||
| ```bash | ||
| apm install you/my-coding-standards | ||
| ```yaml | ||
| dependencies: | ||
| apm: | ||
| - your-handle/team-skills | ||
| ``` | ||
|
|
||
| APM automatically: | ||
| - Downloads the package to `apm_modules/` | ||
| - Copies instructions to `.github/instructions/` | ||
| - Copies prompts to `.github/prompts/` | ||
| - Updates `apm.yml` with the dependency | ||
| Then `apm install` -- consumers get the same skill and agent in their | ||
| runtime dirs, with version pinning recorded in `apm.lock.yaml`. | ||
|
|
||
| ## 7. Optional: Compile for Other Tools | ||
| For a real published package to read, see | ||
| [`microsoft/apm-sample-package`](https://github.com/microsoft/apm-sample-package) | ||
| (install with `apm install microsoft/apm-sample-package#v1.0.0`). | ||
|
|
||
| If you use tools beyond GitHub Copilot, Claude, Cursor, and OpenCode (which read deployed primitives natively), generate compiled instruction files: | ||
| ## 6. Ship as a plugin (optional) | ||
|
|
||
| The same package can ship as a standalone plugin -- no APM required for | ||
| consumers. This lets you target plugin-aware hosts (Copilot CLI plugins, | ||
| the broader plugin ecosystem) with the primitives you already authored. | ||
|
|
||
| ```bash | ||
| apm compile | ||
| apm pack --format plugin | ||
| ``` | ||
|
|
||
| Output: | ||
|
|
||
| ``` | ||
| build/team-skills-1.0.0/ | ||
| +-- plugin.json # synthesized from apm.yml | ||
| +-- agents/ | ||
| | +-- team-reviewer.agent.md | ||
| +-- skills/ | ||
| +-- pr-description/SKILL.md | ||
| ``` | ||
|
|
||
| No `apm.yml`, no `apm_modules/`, no `.apm/`. Just primitives in | ||
| plugin-native layout. | ||
|
|
||
| If you know up front that you want to ship a plugin, you can scaffold with | ||
| `apm init --plugin team-skills`, which adds `plugin.json` next to `apm.yml` | ||
| from day one. APM still gives you dependency management, the lockfile, and | ||
| audit while you author; pack produces the plugin bundle when you ship. | ||
|
|
||
| This produces `AGENTS.md` (for Codex, Gemini) and `CLAUDE.md` for tools that need a single instructions file. Copilot, Claude, and Cursor users can skip this step — OpenCode users need `apm compile` only if their packages include instructions (OpenCode reads `AGENTS.md` for those). | ||
| For the full reference, see the [Pack & Distribute guide](/apm/guides/pack-distribute/) | ||
| and the [Plugin authoring guide](/apm/guides/plugins/). | ||
|
|
||
| ## Next Steps | ||
| ## Next steps | ||
|
|
||
| - Add [skills](/apm/guides/skills/) to your package | ||
| - Set up [dependencies](/apm/guides/dependencies/) on other packages | ||
| - Distribute as a standalone plugin — see [Plugin authoring](../../guides/plugins/#plugin-authoring) and [Pack & Distribute](../../guides/pack-distribute/) | ||
| - Explore the [CLI reference](/apm/reference/cli-commands/) for more commands | ||
| - [Anatomy of an APM Package](/apm/introduction/anatomy-of-an-apm-package/) | ||
| -- the full mental model: `.apm/` vs `apm_modules/` vs `.github/`. | ||
| - [Skills guide](/apm/guides/skills/) -- bundled resources, sub-skills, | ||
| activation tuning. | ||
| - [Agent Workflows guide](/apm/guides/agent-workflows/) -- chaining agents, | ||
| GitHub Agentic Workflows integration. | ||
| - [Dependencies guide](/apm/guides/dependencies/) -- depend on other APM | ||
| packages, file-level imports, version pinning. | ||
| - [`apm audit`](/apm/reference/cli-commands/) -- scan dependencies for | ||
| policy violations before they ship. | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -41,33 +41,42 @@ APM separates two concerns that those folders conflate: | |||||||||||||
| ### A concrete example: this repo | ||||||||||||||
|
|
||||||||||||||
| The `microsoft/apm` repository (the one shipping the CLI you are reading docs | ||||||||||||||
| for) dogfoods this layout. It contains both source and compiled output side by | ||||||||||||||
| side: | ||||||||||||||
| for) dogfoods this layout. It contains both source and compiled output side | ||||||||||||||
| by side: | ||||||||||||||
|
|
||||||||||||||
| ``` | ||||||||||||||
| microsoft/apm/ | ||||||||||||||
| +-- apm.yml | ||||||||||||||
| +-- .apm/ | ||||||||||||||
| | +-- skills/ | ||||||||||||||
| | | +-- writing-skills/ | ||||||||||||||
| | | +-- python-architecture/ | ||||||||||||||
| | | +-- SKILL.md | ||||||||||||||
| | +-- instructions/ | ||||||||||||||
| | +-- agents/ | ||||||||||||||
| | | +-- doc-writer.agent.md | ||||||||||||||
| | +-- instructions/ | ||||||||||||||
| +-- .github/ | ||||||||||||||
| | +-- skills/ | ||||||||||||||
| | | +-- writing-skills/ | ||||||||||||||
| | | +-- SKILL.md (compiled from .apm/, byte-identical) | ||||||||||||||
| | +-- instructions/ | ||||||||||||||
| | | +-- python-architecture/ | ||||||||||||||
| | | +-- SKILL.md (deployed from .apm/ by apm install) | ||||||||||||||
| | +-- agents/ | ||||||||||||||
| | | +-- doc-writer.agent.md | ||||||||||||||
| | +-- instructions/ | ||||||||||||||
| +-- src/ | ||||||||||||||
| +-- tests/ | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| The file under `.apm/skills/writing-skills/SKILL.md` is the source. The file | ||||||||||||||
| under `.github/skills/writing-skills/SKILL.md` is the compiled artifact that | ||||||||||||||
| the in-repo Copilot agent actually loads while we work on the CLI. Same | ||||||||||||||
| content today, but only one of them is authoritative -- and only one of them | ||||||||||||||
| gets shipped when this repo is consumed as an APM package. | ||||||||||||||
| The source files under `.apm/` are authoritative. You can inspect them on | ||||||||||||||
| GitHub: | ||||||||||||||
| [`.apm/skills/python-architecture/SKILL.md`](https://github.com/microsoft/apm/blob/main/.apm/skills/python-architecture/SKILL.md) | ||||||||||||||
| and | ||||||||||||||
| [`.apm/agents/doc-writer.agent.md`](https://github.com/microsoft/apm/blob/main/.apm/agents/doc-writer.agent.md). | ||||||||||||||
| Their counterparts under `.github/` are the deployed copies the in-repo | ||||||||||||||
| Copilot agent actually loads while we work on the CLI. | ||||||||||||||
|
|
||||||||||||||
| For simple primitives the deployed file is byte-identical to the source. | ||||||||||||||
| The deploy step can also augment files for runtime-specific concerns (e.g. | ||||||||||||||
| adding diagnostic guidance for a particular target), so treat `.github/` | ||||||||||||||
| as build output: never edit it by hand, always re-deploy from `.apm/`. | ||||||||||||||
|
Comment on lines
+77
to
+79
|
||||||||||||||
| The deploy step can also augment files for runtime-specific concerns (e.g. | |
| adding diagnostic guidance for a particular target), so treat `.github/` | |
| as build output: never edit it by hand, always re-deploy from `.apm/`. | |
| For some targets, APM generates runtime-specific formats from the source, so | |
| treat `.github/` as build output: never edit it by hand, always re-deploy | |
| from `.apm/`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documented
apm installoutput snippet does not match the current CLI output formatting.download_complete()emits" [+] <project root> (local)"(indented) and the integration logger currently prints"{n} agents integrated"(plural label), so"1 agent integrated"will not appear. Suggest updating this block to either match the exact strings produced by the CLI or wording it as illustrative output (so readers are not looking for exact lines).