llm/skills
A Composer plugin that syncs AI Skills from your vendor packages and arbitrary GitHub/GitLab repos into a project-local directory (default .agents/skills/). Skills are auto-discovered by their SKILL.md files and kept up to date automatically on composer install and update.
There are now two ways to get skills into a project: the Composer plugin (unchanged) or the standalone binary shipped as of 1.15.0.
Option A — Composer plugin (existing projects):
Install the package in your Laravel project:
composer require --dev llm/skills
Enable the plugin in composer.json:
{
"config": {
"allow-plugins": {
"llm/skills": true
}
}
}
Initialize the config (optional but recommended):
composer skills:init
This creates a skills.json file in your project root with default settings.
Add a skill package to your composer.json:
{
"require-dev": {
"vendor/skill-package": "^1.0"
}
}
Run composer update to install it. The package should declare its skills in extra.skills:
{
"extra": {
"skills": {
"source": "path/to/skills"
}
}
}
Verify skills are synced:
composer skills:show
Check the .agents/skills/ directory for the imported skills.
Option B — Standalone binary (new in 1.15.0):
PATH:
chmod +x skills
mv skills /usr/local/bin/skills
skills init
skills update
skills show
skills.json and composer.json/composer.lock).Use Option A when you want skills synced automatically on every composer install/update. Use Option B when you have no PHP toolchain available (docs sites, Node/Go services, Docker images without PHP) or when you want to generate skills in CI before PHP is installed.
Integrate a skill for AI-assisted Laravel migrations:
composer require --dev vendor/laravel-migration-skills
skills.json to trust the package:
{
"trusted": ["vendor/*"]
}
composer update to auto-sync the skill (or skills update if using the binary)..agents/skills/migrate/.Vendor Side:
resources/skills/ directory (e.g., resources/skills/laravel-auth/).SKILL.md with Laravel-specific instructions (e.g., authentication flow templates).composer.json:
{
"extra": {
"skills": {
"source": "resources/skills"
}
}
}
Consumer Side:
composer.json under require-dev.composer update to auto-sync skills to .agents/skills/.SKILL.md for generating Laravel auth controllers).skills.json to create aliases for different agents:
{
"target": ".agents/skills",
"aliases": [".claude/skills", ".cursor/skills"]
}
.claude/skills).--discovery to include packages without explicit extra.skills:
composer skills:update --discovery
# or, with the binary:
skills update --discovery
skills update vendor/package --trust="vendor/*"
composer.json untouched apart from the donor packages you require.ARG SKILLS_VERSION=1.15.0
RUN curl -fsSL -o /usr/local/bin/skills \
"https://github.com/roxblnfk/skills/releases/download/${SKILLS_VERSION}/skills-linux-amd64" \
&& chmod +x /usr/local/bin/skills
skills update
Skill for Artisan Commands:
SKILL.md containing Artisan command templates. Example:
# SKILL.md
## Laravel Command Generation
Use this skill to generate Artisan commands for:
- Database seeding
- Queue workers
- Console commands
templates/command.stub file for AI to fill in.Skill for Migration Writes:
SKILL.md for migration logic and templates/migration.stub.SKILL.md:
## Laravel Migration Helper
Generate migrations for:
- Table creation with indexes
- Foreign key constraints
- Soft deletes
Skill for API Resource Handling:
SKILL.md for API resource boilerplate (e.g., App\Http\Resources\PostResource).Auto-Sync in CI (plugin path):
Ensure skills.json has "auto-sync": true to sync skills during composer install in CI.
- run: composer install
# Skills auto-synced here
- run: php artisan test
Sync Before the PHP Toolchain Exists (binary path, 1.15.0): Useful when your AI/lint job runs on a slimmer image than your PHP job:
- name: Sync skills
run: |
curl -fsSL -o /usr/local/bin/skills \
https://github.com/roxblnfk/skills/releases/download/1.15.0/skills-linux-amd64
chmod +x /usr/local/bin/skills
skills update
Cache Skills in CI:
Add .agents/skills/ to your CI cache to avoid re-downloading skills on every run:
- uses: actions/cache@v3
with:
path: |
vendor
.agents/skills
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
Pin the binary version in CI (1.15.0, not latest) — same reason you commit composer.lock. A drifting skills binary changes what your AI agents read between builds.
skills update --dry-run
skills show
Trust Misconfiguration:
skills.json under "trusted" or use --trust in CLI:
skills update vendor/package --trust="vendor/*"
skills show to see skipped packages and reasons.Alias Conflicts:
.claude/skills) already exist as directories, causing failures.--alias to override:
skills update --alias=.claude/skills
Auto-Sync Overrides:
composer install --no-scripts disables auto-sync, leaving skills unsynced.skills.json has "auto-sync": true or manually run skills update.Malformed skills.json:
skills init to generate a valid template or validate against the schema:
{
"$schema": "https://raw.githubusercontent.com/roxblnfk/skills/master/resources/skills.schema.json"
}
Cross-Platform Alias Issues:
Mixing Plugin and Binary (new in 1.15.0):
.agents/skills/. Auto-sync from the plugin may silently overwrite (or lag behind) what the binary produced, producing confusing "it worked yesterday" behaviour.llm/skills from require-dev and drop the allow-plugins entry.Binary Not on PATH in Non-Interactive Shells:
RUN steps frequently use a shell that does not source your profile, so skills is "command not found" even though it works in your terminal./usr/local/bin) or invoke by full path in scripts.Windows Binary Invocation:
.\ prefix (.\skills.exe update), and SmartScreen may block an unsigned downloaded executable.%PATH%, invoke with .\ when testing locally, and unblock with Unblock-File if SmartScreen quarantines the download.Verbose Output:
Use -v or -vv for detailed logs:
skills update -vv
Check Sync Status:
skills show
Look for SKIPPED entries to identify trust or discovery issues.
Validate Donor Packages:
Ensure donor packages declare extra.skills correctly. Test with:
skills update --discovery
Confirm Which Build You Are Running:
When a sync behaves differently on a colleague's machine or in CI, check the version of whichever driver produced the output — composer skills:show for the plugin path, skills --version for the binary — before chasing config problems.
Manual Sync: For debugging, manually trigger sync:
skills update
Custom Trust Logic:
Override trust behavior by extending the plugin or using --trust dynamically:
skills update --trust="vendor/*" --trust="another/*"
Post-Sync Hooks:
Add a post-update-cmd script in composer.json to run custom logic after sync:
{
"scripts": {
"post-update-cmd": [
"@php artisan skills:update",
"@php artisan your:custom-task"
]
}
}
This hook only fires on the Composer path — with the binary, wire the follow-up explicitly in your Makefile, Taskfile or CI step.
Custom Target Directory:
Override the default .agents/skills path in skills.json:
{
"target": "custom/skills/path"
}
Dynamic Skill Loading:
Use --discovery to include packages without explicit skill declarations:
skills update --discovery
Wrapper Script for Teams:
Wrap the binary in a small bin/skills script that pins the version and passes house defaults, so every developer and CI job gets identical behaviour without memorising flags:
#!/usr/bin/env bash
exec skills update --discovery --trust="vendor/*" "$@"
Service Provider Integration: Load skills dynamically in a service provider:
public function boot()
{
$skillsPath = base_path('.agents/skills');
if (file_exists($skillsPath)) {
$this->loadSkillsFrom($skillsPath);
}
}
This works identically whether the skills directory was populated by the plugin or the standalone binary — the output on disk is the same format.
Skill-Based Artisan Commands: Create a custom Artisan command to generate files from skills, so developers who never touch the CLI tooling still get the templates:
// app/Console/Commands/
How can I help you explore Laravel packages today?