ESLint for agent skills and plugins.
SkillForge helps agent extension authors scaffold, lint, smoke-test, inspect, and package skills/plugins before they publish or submit them to a marketplace.
Codex is the first-class target today. Portable skill compatibility for Claude-style skills and cross-agent packages is now starting with skillforge compat.
Listed in awesome-codex-plugins under "Validate Before You Ship."
npx agent-skillforge lint .Example output:
SkillForge plugin lint found 3 issue(s) (2 blocking, 1 advisory) [source]:
[ERROR blocking] plugin.skills.missing - Manifest path does not exist: ./skills/
[WARNING advisory] skill.description.vague - Description should clearly say what the skill does and when Codex should use it.
[ERROR blocking] metadata.openai-yaml.legacy-shape - agents/openai.yaml fields must live under interface:
Agent skills and plugins are small, powerful folders. They are also easy to get subtly wrong:
- weak skill descriptions that Codex will not trigger well
- stale
agents/openai.yamlshapes - plugin paths that are not
./-relative - missing bundled skills, hooks, MCP, app, or asset files
- packages that work locally but are not marketplace-ready
- skills that claim cross-agent compatibility but still contain agent-specific assumptions
SkillForge is not a marketplace. It is the publish-readiness check you run before sharing an agent skill/plugin repo.
SkillForge is a CLI linter, not an agent runtime plugin. Running lint, compat, doctor, and smoke reads local files and reports issues; it does not install skills, load plugins into Codex, or execute scripts from the target project.
Commands that write files are explicit:
initcreates scaffold files in the destination you choose.packwrites release artifacts to an output directory.
For cautious use, pin the npm version, review the source, and start with read-only commands:
npx agent-skillforge@0.3.2 lint .
npx agent-skillforge@0.3.2 compat . --target portableRun with npm:
npx agent-skillforge lint .Or install it in a project:
npm install --save-dev agent-skillforge
npx skillforge lint .After installing, you can use the shorter aliases:
skillforge lint .
asf lint .The old codex-skillforge binary remains available as a compatibility alias.
Run SkillForge in CI:
name: SkillForge
on:
pull_request:
push:
branches: [main]
jobs:
lint-skills:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: f0d010c/skillforge@v0.3.2
with:
path: .
profile: sourceFor marketplace-ready checks, use:
- uses: f0d010c/skillforge@v0.3.2
with:
path: .
profile: marketplaceSee a tiny working example repo:
See real-world scan notes:
The examples/real-world-cases/ folder contains tiny, intentionally flawed examples based on issues found while scanning public Codex plugin bundles:
missing-mcp-server-file: plugin manifest points at./mcp.json, but the file is absent.stale-skill-reference:SKILL.mdlinks to a reference file that no longer exists.weak-trigger-description: skill frontmatter is valid YAML, but too vague for reliable triggering.plugin-missing-include: bundled skills use plugin-level resources that are not declared in manifestinclude.plugin-readme-stale-path: README file trees mention folders missing from the installable bundle.marketplace-category: local marketplace metadata and plugin manifest categories drift apart.
Try them:
npx agent-skillforge lint examples/real-world-cases/missing-mcp-server-file
npx agent-skillforge lint examples/real-world-cases/stale-skill-reference
npx agent-skillforge lint examples/real-world-cases/weak-trigger-description --strict
npx agent-skillforge lint ./plugins/my-plugin --profile marketplaceCreate and check a new skill:
npx agent-skillforge init skill ./my-skill --name my-skill
npx agent-skillforge lint ./my-skill
npx agent-skillforge smoke ./my-skill
npx agent-skillforge pack ./my-skillCheck an existing agent extension repo:
npx agent-skillforge lint .If SkillForge is installed globally or in your project, the same workflow is shorter:
skillforge lint .
skillforge compat . --target portable
skillforge smoke ./my-skill
skillforge pack ./my-skillskillforge init skill ./my-skill --name my-skill
skillforge init plugin ./my-plugin --name my-plugin
skillforge init plugin ./hook-plugin --name hook-plugin --template hook-package
skillforge lint ./my-skill --format text
skillforge lint ./my-skill --format json
skillforge lint ./my-skill --format sarif
skillforge lint ./my-plugin --profile marketplace
skillforge lint ./my-skill --strict
skillforge lint .
skillforge compat . --target portable
skillforge doctor .
skillforge smoke ./my-skill
skillforge pack ./my-pluginlint . can inspect a repository-style collection and recursively find skill/plugin folders under paths like .agents/skills and plugins.
Default lint mode focuses on deterministic publish-readiness problems. Use --strict to include advisory checks such as trigger-description quality, large skill bodies, unreferenced scripts, and plugin name/folder mismatch.
Add skillforge.json at the repo or package root to tune checks:
{
"name": "my-agent-skill-pack",
"lint": {
"ignore": [
"templates/**",
"tests/fixtures/**",
"examples/broken-on-purpose/**"
]
},
"checks": {
"maxSkillMdLines": 500,
"requireOpenAiYaml": false,
"allowScripts": true
}
}Use lint.ignore for intentional fixtures, vendored examples, generated output, or template folders that should not be treated as publishable skills/plugins.
Use compat to check whether a skill/package is likely to work in a specific agent ecosystem.
skillforge compat . --target codex
skillforge compat . --target claude
skillforge compat . --target portablecodex runs Codex-oriented lint checks.
claude checks the shared SKILL.md basics expected by Claude-style skills.
portable combines both and adds warnings for agent-specific wording, .claude/, .codex/, .agents/, and obvious OS-specific script assumptions.
This is an analysis command, not an auto-converter.
Use profiles to match where the plugin is being checked:
skillforge lint . --profile source
skillforge lint . --profile marketplacesource is the default. It is friendlier for repository work and treats obvious build-generated paths such as ./dist/server.js as advisories when a package.json build script exists.
marketplace is stricter. It treats every manifest path as something that must already be bundled, which is what users and install tooling need after publishing.
Issue output uses deterministic impact labels:
blocking: likely to break install, discovery, packaging, or runtime setup.advisory: worth fixing, but not necessarily a publish blocker.
Use SkillForge in CI:
name: SkillForge
on:
pull_request:
push:
branches: [main]
jobs:
lint-agent-extensions:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: f0d010c/skillforge@main
with:
path: .
format: sarif
profile: marketplaceAdd skillforge.json to a skill or plugin root:
{
"name": "my-codex-skill",
"type": "skill",
"examples": [
{
"prompt": "Use $my-codex-skill to review a React UI for visual issues.",
"shouldTrigger": true
}
],
"checks": {
"maxSkillMdLines": 500,
"requireOpenAiYaml": false,
"allowScripts": true
}
}Skill checks:
SKILL.mdfrontmatter hasnameanddescription.- skill names are lowercase hyphen-case and under 64 characters.
- explicit Markdown links and known resource references resolve.
- optional
agents/openai.yamluses the current nestedinterface,policy, anddependenciesshape. - strict mode: descriptions are concise, trigger-oriented, and front-loaded.
- strict mode: scripts are mentioned in
SKILL.md.
Plugin checks:
.codex-plugin/plugin.jsonexists and parses.- plugin names are lowercase hyphen-case and match the folder.
- published metadata has useful
versionanddescription. skills,mcpServers,apps,hooks, and visual asset paths resolve.- manifest file paths are
./-relative and stay inside the plugin root. - MCP server config parses and each server defines a
urlorcommand. - MCP server
argsare arrays of strings. - source profile downgrades missing build-generated command paths when a build script exists.
- bundled skills are linted too.
- default
hooks/hooks.jsonis detected and parsed. - hook packages warn about the required
codex_hooksfeature flag. - strict mode: plugin folder/name mismatch is reported.
Codex reads local skills from repo and user locations such as:
./.agents/skills/<skill-name>
$HOME/.agents/skills/<skill-name>
Plugins are distributed through marketplace files such as:
./.agents/plugins/marketplace.json
$HOME/.agents/plugins/marketplace.json
skillforge pack writes:
<name>.zipINSTALL.mdmarketplace-entry.json
0: pass, or warnings only1: lint errors or failed smoke checks2: invalid CLI usage or unreadable input
Before publishing:
npm run build
npm test
npm audit
npm pack --dry-runVerify from a clean directory after npm publish:
mkdir skillforge-smoke
cd skillforge-smoke
npx agent-skillforge --version
npx agent-skillforge init skill ./demo-skill --name demo-skill
npx agent-skillforge lint ./demo-skill