netresearch/composer-agent-skill-plugin
最新稳定版本:v2.1.0
Composer 安装命令:
composer require netresearch/composer-agent-skill-plugin
包简介
Composer plugin for managing AI agent skills
README 文档
README
A Composer plugin for AI agent skills in PHP projects. Skills are skill dependencies of your repo: you declare them through one or more of the mechanisms below (they are equivalent in the sense that everything flows into the same discovery, trust, and AGENTS.md pipeline—you may combine them). Versioning and publishing differ (semver packages vs pinned git lock), not whether the path is “official.”
Features
- Three ways to bring skills in — see How skills enter your project: (1)
composer requireatype: ai-agent-skillpackage, (2)composer requireany package that lists skills underextra.ai-agent-skill, (3) declare GitHub or in-repo paths underextra.ai-agent-skillswithcomposer.skills.lockandcomposer skills …(Direct sources). - Automatic discovery: Finds skills from installed packages (legacy type and universal
extraform). - AGENTS.md generation: Creates XML skill index compatible with openskills
- CLI commands:
composer list-skills,composer read-skill, trust helpers,composer skills:*for direct sources, andcomposer outdatedappends direct-skill rows (text) or points tocomposer skills:outdated - Convention Over Configuration: Works out of the box with zero configuration
- Progressive Disclosure: Lightweight index, full details on demand
- Security First: Rejects unsafe paths, validates skill metadata (including descriptions bound for AGENTS.md)
- Multiple Skills Per Package: Support for both single and multi-skill packages
Installation
composer require netresearch/composer-agent-skill-plugin
During installation, Composer will prompt you to authorize the plugin:
netresearch/composer-agent-skill-plugin contains a Composer plugin which is currently not in your allow-plugins config.
Do you trust "netresearch/composer-agent-skill-plugin" to execute code and wish to enable it now? [y,n,d,?]
Choose y to allow the plugin to activate.
Non-Interactive Installation
For CI/CD or non-interactive environments, pre-authorize the plugin in your composer.json:
{
"config": {
"allow-plugins": {
"netresearch/composer-agent-skill-plugin": true
}
}
}
How skills enter your project
composer requirea dedicated skill package —type: ai-agent-skill(classic).composer requireany package that ships skills —extra.ai-agent-skillon libraries, bundles, etc. (universal discovery).- Direct sources — root
extra.ai-agent-skills+composer.skills.lock+composer skills …. Same trust /AGENTS.mdpipeline as (1) and (2); you can use several of these together.
Quick Start
1. Install Skill Packages
Install any package with type ai-agent-skill:
composer require vendor/database-analyzer-skill
2. Skills Auto-Register (after trust)
The plugin automatically:
- Discovers skill packages during
composer installorcomposer update - Asks once before registering skills from a package it hasn't seen before — see Trust Model
- Generates/updates
AGENTS.mdin your project root with the trusted skills - Registers them in XML format for AI agent consumption
3. Use Skills
AI agents automatically discover skills via AGENTS.md:
# List all available skills composer list-skills # Read a specific skill composer read-skill database-analyzer
Design rationale: see docs/adr/ for short Architecture Decision Records covering universal discovery, the trust prompt design, atomic-write persistence, glob semantics, direct skills (009–012), and more.
Direct sources: GitHub and project paths
Path (3) above: pin skills from GitHub or from a directory inside the project using extra.ai-agent-skills and a generated lockfile composer.skills.lock. Full technical notes: docs/IMPLEMENTATION-DIRECT-SKILLS.md.
Requirements
gitonPATHwhen using GitHub sources (clone/fetch).- Supported source strings match
SourceResolver: GitHub HTTPS/SSH,owner/reposhorthand (with optional:refsuffix), GitHub tree URLs, and existing local directories. Generic non-GitHub git HTTPS URLs are not supported yet.
Semver on git tags (like composer require)
For GitHub shorthand (or --ref), you can use Composer-style semver constraints against annotated/lightweight tags on the remote (git ls-remote --tags). Examples:
# Highest tag satisfying ^1.2 (e.g. 1.2.6), stored as ref "^1.2" in composer.json; lock pins the commit composer skills:add acme/some-skill-repo:^1.2 --skill=my-skill # Same, via flag composer skills:add acme/some-skill-repo --skill=my-skill --ref='^1.2'
On composer update, the plugin’s post-update hook re-resolves the constraint against current remote tags and refreshes composer.skills.lock (same idea as relaxing a lock when you bump constraints—here the constraint lives in extra.ai-agent-skills.sources[].ref). composer install still applies the pinned commit from the lock only.
Constraints are detected when the ref contains semver operators (^, ~, *, >=, ranges with , / ||, etc.). Plain names like main or v1.2.3 are still treated as literal git refs.
Outdated checks (composer outdated and composer skills:outdated)
composer outdated(same ascomposer show --latest --outdated) lists Composer packages as usual. When you use text output, this plugin appends a short block for direct agent skills whosecomposer.skills.lockpin is behind the current remote git tip (for semver, branch, or tag sources) or whose path skill content hash changed on disk. Resolving usesgit ls-remote(read-only); failures are skipped with a comment on stderr.composer outdated -f jsonmust stay valid JSON for package rows only. If direct skills are stale, the plugin prints a stderr notice; runcomposer skills:outdated -f jsonfor a machine-readable{"outdated":[…]}document.composer skills:outdated— full list; add--strictfor exit code 1 when anything is outdated (handy in CI).composer outdated --strictstill reflects Composer packages only (unchanged upstream behaviour).
Typical workflow
# Add a source and resolve skills into composer.skills.lock (writes composer.json + lock) composer skills:add vercel-labs/skills --skill=find-skills --ref=main # On CI or a fresh clone: install exactly what the lock pins (no implicit network update) composer install # After editing sources in composer.json: refresh the lock + installed files composer skills:update
Equivalent forms: composer skills add … and composer skills:add … (same for install, update, remove, list, outdated).
Configuration keys (extra.ai-agent-skills)
| Key | Purpose |
|---|---|
version |
Schema version (currently 1) |
install-dir |
Where skill trees are materialized (default vendor/agent-skills/installed/) |
cache-dir |
Git clone and temporary work directories (default vendor/agent-skills/cache) |
sources-dir |
Declared directory prefix (included in the content-hash); clone cache uses cache-dir, not this path |
sources |
List of sources (type: path, github, or git with url / path / ref / skills) |
Relative directory keys must not use .. or absolute paths. Lockfile install-path / path / path-type url fields are checked the same way so a tampered lock cannot write outside the project.
Trust for direct skills
Direct skills use the same extra.ai-agent-skill.allow-skills map as packages. Keys look like:
direct:<source-name>/<skill-id>
Use composer list-skills to see the exact package column value, then:
composer skills:trust 'direct:vercel-labs/skills/find-skills'
See ADR-012: changing allow/deny does not change the lock content-hash; changing sources does.
Disable direct-skill sync
Set environment variable:
COMPOSER_AGENT_SKILLS=0
…to skip direct-skill install/update hooks (legacy AGENTS.md behaviour is unchanged).
Trust Model
Skills are instructions an AI agent will follow in your project. To prevent transitive dependencies from silently injecting skills, the plugin asks before registering skills from a new package — modeled on Composer's own allow-plugins flow.
The first time a new package wants to register skills, you'll see:
Package "vendor/foo" wants to register AI agent skills.
Skills are instructions an AI agent will follow in your project.
Allow this package to register skills?
[y] Yes — allow & persist (writes to composer.json)
[n] No — deny & persist (suppress future prompts)
[a] Allow for this session only
[d] Discard — leave undecided, ask again next run
[?] Show details about this choice
(change later with: composer skills:trust vendor/foo [--deny|--revoke])
(defaults to n) [y,n,a,d,?]:
Decisions persist under extra.ai-agent-skill.allow-skills in your root composer.json:
{
"extra": {
"ai-agent-skill": {
"allow-skills": {
"vendor/foo": true,
"vendor/bar": false,
"trusted-org/*": true
}
}
}
}
Managing trust decisions
Use the dedicated commands (preferred):
composer skills:trust vendor/foo # allow & persist composer skills:trust vendor/foo --deny # deny & persist composer skills:trust vendor/foo --revoke # remove from the map (re-prompts next install) composer skills:list-trust # show every persisted decision
Or edit composer.json directly. Glob patterns (vendor/*) are supported. Direct skills use keys direct:<source>/<skill-name> in the same map — see Direct sources.
⚠️ Glob matching is case-sensitive and
*matches any characters within a pattern segment. Composer normalizes published package names to lowercase, so write trust patterns in lowercase. A pattern likeacme/skills-*also trustsacme/skills-anything-else— use globs only for namespaces you fully control. Exact-string keys always override matching globs, even when the glob was added first. Prefer explicit per-package entries when in doubt.
In non-interactive mode (composer install --no-interaction, CI), packages without an explicit decision are skipped with a warning — the plugin never auto-trusts on your behalf. The warning suggests composer skills:trust <package> so CI failures are one command away from a fix. composer list-skills shows the trust state per skill ([allowed] / [pending] / [denied]) without firing prompts.
First-run policy (covers v0.1.x upgrades)
The first time the plugin runs in a project that already has type: ai-agent-skill packages installed — typically a fresh install of those packages or an upgrade from v0.1.x where they were silently auto-trusted — you'll see a one-time prompt asking how to seed the trust map:
The AI Agent Skill plugin found 3 existing skill packages that have not been authorized yet.
- vendor/skill-a (in your require)
- vendor/skill-b (pulled in by another package)
- vendor/skill-c (pulled in by another package)
How should they be trusted on this first run?
[n] None — prompt for each package later (default, strict)
[d] Direct dependencies only — auto-trust packages your root composer.json explicitly requires
[a] All — auto-trust every existing skill package (including transitive)
(defaults to n) [n,d,a]:
n(default, recommended) — nothing is auto-trusted. Each package goes through the per-package prompt during the same install.d— only packages listed directly in your rootcomposer.json'srequire/require-devare auto-trusted. Transitive skill packages still prompt.a— every existing skill package is auto-trusted. This restores the v0.1.x behaviour at the user's explicit consent — fastest, widest trust surface.
The choice is persisted under extra.ai-agent-skill.allow-skills, so the prompt only fires once. In non-interactive mode (composer install --no-interaction, CI) the policy defaults to n and a warning lists every affected package with the composer skills:trust ... recovery command. CI installs never silently expand trust on your behalf.
Library-bundled skills (type: library + extra.ai-agent-skill) are not part of this first-run policy — they always go through the per-package prompt because the user chose the library for its primary purpose, not to import skills.
Usage
List Available Skills
$ composer list-skills Available AI Agent Skills: database-analyzer vendor/db-skill 1.2.0 [allowed] oro-bundle-helper vendor/oro-skill 1.0.0 [allowed] symfony-security vendor/symfony-security 2.1.0 [pending] 3 skills available. Use 'composer read-skill <name>' for details. 1 pending — run `composer install` interactively to be prompted.
Read Skill Details
$ composer read-skill database-analyzer
Reading: database-analyzer
Package: vendor/db-skill v1.2.0
Base Directory: vendor/vendor/db-skill
---
name: database-analyzer
description: Analyze and optimize database schemas and relationships
---
# Database Analyzer Skill
[Full SKILL.md content with instructions and examples]
Skill read: database-analyzer
The Base Directory is the directory containing SKILL.md, used as the root for resolving bundled resources like references/, scripts/, and assets/.
Creating Skill Packages
There are two ways to ship skills, both fully supported:
Option A: Library bundles a skill (recommended for libraries)
Any package — regardless of type — can ship skills by declaring extra.ai-agent-skill:
{
"name": "vendor/my-library",
"type": "library",
"extra": {
"ai-agent-skill": "skills/my-helper.md"
}
}
This mirrors the pattern phpstan/extension-installer uses for PHPStan extensions: the library opts in via extra, no special package type required. Use this when an existing library wants to ship a companion skill alongside its primary purpose.
Option B: Dedicated skill package
A package whose only purpose is shipping skills can use type: ai-agent-skill and place SKILL.md in the package root with no extra config:
1. Create composer.json:
{
"name": "vendor/my-skill",
"description": "My awesome AI agent skill",
"type": "ai-agent-skill",
"license": "MIT",
"require": {
"php": "^8.2"
}
}
2. Create SKILL.md in package root:
--- name: my-skill description: Brief description of what this skill does and when to use it --- # My Skill ## Instructions Step-by-step guidance for using this skill... ## Examples Example 1: How to use feature X Example 2: How to handle scenario Y ## Requirements - PHP 8.2+ - Any other dependencies
3. Publish to Packagist:
git tag 1.0.0 git push --tags
Multi-Skill Package
For packages containing multiple skills, configure paths in extra.ai-agent-skill:
{
"name": "vendor/database-tools",
"type": "ai-agent-skill",
"require": {
"netresearch/composer-agent-skill-plugin": "*"
},
"extra": {
"ai-agent-skill": [
"skills/analyzer/SKILL.md",
"skills/optimizer/SKILL.md",
"skills/validator/SKILL.md"
]
}
}
Custom Skill Path
For a single skill in a non-standard location:
{
"name": "vendor/custom-skill",
"type": "ai-agent-skill",
"require": {
"netresearch/composer-agent-skill-plugin": "*"
},
"extra": {
"ai-agent-skill": "docs/agent-skill.md"
}
}
Security Note: Only relative paths from package root are allowed. Absolute paths are rejected.
SKILL.md Schema
Skills must follow the Claude Code SKILL.md specification:
Required Frontmatter
--- name: skill-name # lowercase, numbers, hyphens only (max 64 chars) description: Clear description of functionality and triggers (max 1024 chars) ---
Optional Frontmatter
--- name: my-skill description: What it does and when to use it allowed-tools: [Read, Grep, Glob] # Claude Code only ---
Validation Rules
- Name format:
^[a-z0-9-]{1,64}$(lowercase alphanumeric and hyphens) - Name length: Maximum 64 characters
- Description length: Maximum 1024 characters
- YAML syntax: Valid YAML with proper delimiters (
---)
Configuration Options
Default (Convention)
No configuration needed. Plugin looks for SKILL.md in package root:
vendor/my-skill/
├── composer.json
├── SKILL.md ← Auto-discovered
└── src/
Custom Single Skill
{
"extra": {
"ai-agent-skill": "custom/path/skill.md"
}
}
Multiple Skills
{
"extra": {
"ai-agent-skill": [
"skills/skill-one.md",
"skills/skill-two.md",
"docs/skill-three.md"
]
}
}
Troubleshooting
No Skills Found
[WARNING] No AI agent skills found in installed packages.
Solution: Install packages with "type": "ai-agent-skill" in their composer.json.
Duplicate Skill Names
[vendor/tools-b] Duplicate skill name 'database-analyzer' (already defined by vendor/tools-a).
Using skill from vendor/tools-b (last one wins).
Behavior: Last package wins. Consider renaming skills to avoid conflicts.
Invalid Frontmatter
[vendor/broken-skill] Invalid frontmatter in 'SKILL.md': Missing required field: 'description'
Solution: Ensure SKILL.md has both name and description fields in valid YAML format.
Malformed YAML
[vendor/broken-yaml] Malformed YAML in 'SKILL.md':
A colon cannot be used in an unquoted mapping value at line 3
Solution: Fix YAML syntax. Use spaces (not tabs), quote values with colons.
Missing SKILL.md
[vendor/missing-skill] SKILL.md not found at 'SKILL.md'.
Expected SKILL.md in package root (convention).
Solution: Create SKILL.md in package root or configure extra.ai-agent-skill path.
Absolute Path Rejected
[vendor/unsafe-config] Absolute paths not allowed in 'extra.ai-agent-skill'.
Use relative paths from package root.
Solution: Use relative paths like "skills/analyzer.md" instead of /absolute/path.
How It Works
Discovery Process
- Plugin hooks into
composer installandcomposer updateevents - Finds all packages with type
ai-agent-skill - Reads each package's
composer.jsonfor skill paths - Parses SKILL.md files and validates frontmatter
- Generates XML skill registry in
AGENTS.md
AGENTS.md Structure
<skills_system priority="1"> ## Available Skills <!-- SKILLS_TABLE_START --> <usage> When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. How to use skills: - Invoke: Bash("composer read-skill <skill-name>") - The skill content will load with detailed instructions - Base directory provided in output for resolving bundled resources </usage> <available_skills> <skill> <name>database-analyzer</name> <description>Analyze and optimize database schemas</description> <location>vendor/vendor/db-skill</location> </skill> </available_skills> <!-- SKILLS_TABLE_END --> </skills_system>
Progressive Disclosure
- AGENTS.md: Lightweight index with skill names and descriptions
- read-skill: Full SKILL.md content loaded on demand
- Benefits: Fast discovery, reduced context size, on-demand details
Requirements
- PHP 8.2 or higher
- Composer 2.1 or higher
- Symfony YAML Component 5.4+, 6.0+, or 7.0+
- Symfony Console Component 5.4+, 6.0+, or 7.0+
Development
Running Tests
# Run all tests ./vendor/bin/phpunit # Run with coverage ./vendor/bin/phpunit --coverage-text # Run specific test ./vendor/bin/phpunit tests/Unit/SkillDiscoveryTest.php
Code Quality
# PHPStan static analysis (level 8) ./vendor/bin/phpstan analyse # PHP CS Fixer (PSR-12) ./vendor/bin/php-cs-fixer fix --allow-risky=yes # Check without fixing ./vendor/bin/php-cs-fixer fix --dry-run --allow-risky=yes
Project Structure
src/
├── Commands/
│ ├── ListSkillsCommand.php # composer list-skills
│ └── ReadSkillCommand.php # composer read-skill
├── Exceptions/
│ └── InvalidSkillException.php
├── AgentsMdGenerator.php # AGENTS.md generation
├── CommandCapability.php # Command registration
├── SkillDiscovery.php # Package discovery
└── SkillPlugin.php # Main plugin class
tests/
├── Unit/ # Unit tests
├── Integration/ # Integration tests
└── Fixtures/ # Test fixtures
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Write tests for your changes
- Ensure all tests pass (
./vendor/bin/phpunit) - Run static analysis (
./vendor/bin/phpstan analyse) - Fix code style (
./vendor/bin/php-cs-fixer fix --allow-risky=yes) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Code Standards
- PSR-12 coding style
- PHPStan level 8
- 100% type coverage
- Comprehensive tests (>80% coverage)
License
This project is licensed under the MIT License - see the LICENSE file for details.
Inspiration
Inspired by openskills - Universal AI Agent Skills for standardized skill distribution across development environments.
Links
Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with ❤️ by Netresearch
统计信息
- 总下载量: 1.14k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 5
- 点击次数: 3
- 依赖项目数: 18
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-11-25