Dependabot can now bump your agent skills. Gate those pull requests like code
Version updates for apm.yml landed on 3 November 2026. Here's the config, what the pull request changes, and a CI check that fails on tampered skill files.

A skill is a Markdown file that tells your coding agent what to do, and the agent follows it with your permissions. When that file lives in someone else’s repository and your project pins it, whoever can move that pin can change what your agent does on every developer’s machine. Until this week nothing nudged you to keep the pin current, or to look at what changed when you did.
On 3 November 2026 GitHub announced that Dependabot version updates now support Agent Package Manager
(APM). Dependabot opens pull requests for the git dependencies listed in apm.yml and regenerates apm.lock.yaml when one exists. Support is generally available on github.com for all plans, with GitHub Enterprise Server 3.24 to follow.
That’s convenient, and it creates a new kind of pull request: one that changes instructions, not code. This piece covers the setup, what the diff contains, and a check that makes the review mechanical. The technique (pin, diff, scan for hidden characters, re-verify hashes in CI) is the same for any agent that reads instruction files from disk, but the Dependabot part is specific to APM.
What APM is, in two paragraphs
APM
is an MIT-licensed dependency manager for agent configuration, maintained under the microsoft organisation on GitHub. A project declares skills, prompts, agents, instructions, hooks and MCP servers in apm.yml, and apm install deploys them into the layout each agent expects. The project documentation lists Copilot, Claude Code, Cursor, Codex, Gemini, Windsurf and Kiro among its targets.
The apm.lock.yaml file is the part that matters for review. It records where each dependency was resolved from, plus content hashes for what was deployed. That makes a skill update visible as a hash change in a diff, which is exactly what a reviewer wants.
name: payments-api
version: 1.0.0
targets:
- claude
dependencies:
apm:
- your-org/agent-skills/skills/review-csharp#v1.0.0
mcp: []
The #v1.0.0 suffix pins a git ref. A tag is better than a branch name here, because a branch moves under you without any pull request.
Turn on Dependabot for it
Add an apm entry to .github/dependabot.yml, point it at the directory holding apm.yml, and give it a schedule. The ecosystem value in the supported ecosystems table
is apm.
version: 2
updates:
- package-ecosystem: "apm"
directory: "/"
schedule:
interval: "weekly"
This is documented configuration and wasn’t run here, since it needs a repository with Dependabot enabled. Three limits from the docs and the changelog are worth knowing before you rely on it:
- Version updates only. The table marks security updates as not supported, so a malicious or vulnerable skill won’t be flagged by Dependabot alerts.
- Git dependencies only. Private repositories are supported, and private registries are supported for git only.
- It updates what
apm.ymldeclares. A skill copied into.claude/skills/by hand isn’t tracked by anything.
The second point is the one to read twice. Dependabot will tell you a newer version of a skill exists. It won’t tell you whether that version is safe.
What a skill update actually changes
An update pull request touches apm.yml (the ref), apm.lock.yaml (resolved commit and hashes) and the deployed files, if you commit them. The deployed files are the thing to read. Everything else is bookkeeping.
To see what the lockfile records, the example below installs a local skill and prints the lockfile entry. A local path stands in for a git repository, because the sandbox couldn’t reach GitHub-hosted packages. The skill is two lines:
---
name: review-csharp
description: Review C# diffs for missing authorisation and unbounded queries.
---
Check every new endpoint for an authorisation attribute. Flag any query without a Take().
After pip install apm-cli (version 0.35.0) and apm install <path> --target claude, the lockfile entry looks like this, trimmed:
dependencies:
- repo_url: _local/review-csharp
name: review-csharp
package_type: claude_skill
deployed_files:
- .claude/skills/review-csharp
- .claude/skills/review-csharp/SKILL.md
deployed_file_hashes:
.claude/skills/review-csharp/SKILL.md: sha256:9403f340c051923d72a1f1b0b7a722b882c49fd6cc3ee8d80c88d2bf069facea
source: local
content_hash: sha256:f60af7333e4d8a7e24c39381c058575b6dbdf17c49d2b63066a6a92ea1e0467b
For a GitHub-hosted package the entry carries the resolved repository and commit in place of _local. The hashes are what a Dependabot pull request will rewrite, and what your CI can re-check.
Review the pull request, not the version number
A bump from v1.0.0 to v1.1.0 says nothing about the instructions inside. The review is the same as for any dependency that runs with your privileges, only shorter, because skill files are short.
Open the diff of the deployed skill file and ask four things:
- Did the scope of the instructions grow? A review skill that now says “and fix what you find” has become a code-writing skill.
- Did it start running commands, fetching URLs or reading paths outside the repository?
- Did it add or change anything about permissions, such as telling the agent to skip a confirmation?
- Are there characters in the diff you can’t see?
The last one is where a tool helps. Instructions hidden in zero-width or other invisible Unicode characters are invisible in a pull request view and still read by a model. APM scans for them. To see it work, append a line containing a zero-width space (U+200B) to the deployed file and run the audit:
apm audit
│ WARNING │ .claude/skills/revi… │ 6:18 │ U+200B │ Zero-width space │
[!] 1 warning(s) in 1 file(s) -- hidden characters detected
[i] Review file contents, then run 'apm audit --strip' to remove hidden
characters
[x] Drift detected: 1 file(s)
modified (1):
- .claude/skills/review-csharp/SKILL.md [/tmp/apmenv/skillrepo/skills/review-csharp]
Two different checks fired. The first is the hidden-character scan, which points at line 6, column 18. The second is drift: the file on disk no longer matches what the lockfile says was installed. On an unmodified install the same command reports “No drift detected” and “no issues found”.
Make CI the first reviewer
Humans skim. Put the mechanical checks in the pull request pipeline so a failing skill update never reaches a person’s attention as a green tick.
apm audit --ci runs lockfile consistency checks and exits 0 if clean, 1 if there are violations, per apm audit --help. Run against the tampered file above it exited 1; after apm audit --strip removed the character, a plain apm audit exited 0. apm install --frozen refuses to install when the lockfile is missing or out of sync with apm.yml.
A GitHub Actions job that applies both. This is a sketch assembled from those documented flags, not a workflow that has been run:
name: skills
on:
pull_request:
paths:
- "apm.yml"
- "apm.lock.yaml"
- ".claude/skills/**"
permissions:
contents: read
jobs:
verify-skills:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install apm-cli==0.35.0
- run: apm install --frozen
- run: apm audit --ci
Pin the apm-cli version, and bump it deliberately. A tool that audits your instructions shouldn’t update itself on the same cadence as the instructions. Adjust the paths filter to wherever your agent’s files land: .github/, .cursor/ or .claude/.
Make it yours
For a monorepo with several agent setups, add one apm entry per directory containing an apm.yml. Each gets its own pull requests, which keeps a Cursor rules update separate from a Claude skill update.
For a team that wants updates batched, use the grouping options in the Dependabot configuration docs
. Check that they apply to the apm ecosystem before relying on them, because the changelog doesn’t say.
For a check between Dependabot runs, apm outdated lists locked dependencies that have moved on, according to its help text. It reports only remote dependencies: with just the local skill from the example installed it printed “No remote dependencies to check”. Run it before a release branch is cut if you’d rather not wait for the weekly pull request, and treat anything it lists as a candidate for the same diff review.
For a team that doesn’t use APM yet, the audit half still applies. apm audit --file <path> scans an arbitrary file, so the hidden-character check can run over a CLAUDE.md, AGENTS.md or rules directory whether or not APM installed it.
What goes wrong
Hashes prove the file matches what was resolved, not that the file is good. A malicious maintainer’s v1.1.0 will have perfectly consistent hashes. The lockfile protects against tampering after resolution and silent ref moves, and nothing more.
Dependabot’s lack of security updates means a skill with a known problem won’t get a prompt to move. If your team depends on third-party skills, someone has to watch those repositories.
Dependabot’s apm support and the apm CLI are both new. The CLI’s command set was at 0.35.0 when checked, and flags are likely to move, so check apm audit --help against the version you pin.
Don’t bother if every skill in the repository is written by your own team and lives in the same repository. Ordinary code review already covers those, and there’s no pin to bump.
First 15 minutes
Run pip install apm-cli and apm init in a repository, then apm install <your-org>/<repo>/<path-to-skill>#<tag> for one skill you already use. Commit apm.yml and apm.lock.yaml, add the Dependabot entry above, and run apm audit on your existing CLAUDE.md with --file. Read the next Dependabot pull request’s skill diff line by line before merging it.