Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
<a href="https://agentskills.io"><img src="https://img.shields.io/badge/Agent%20Skills-compatible-6D5EF5" alt="Agent Skills compatible"></a>
</p>

**SkillConform is the open-source CI and test suite for Agent Skills: conformance, capability inventory, deterministic security review, and regression testing.** It catches broken metadata, unsafe instructions, missing resources, embedded secrets, broad tool grants, and policy regressions before a skill reaches an agent.
**SkillConform is the open-source CI and test suite for Agent Skills: conformance, capability inventory, cross-agent compatibility evidence, deterministic security review, and regression testing.** It catches broken metadata, unsafe instructions, missing resources, embedded secrets, broad tool grants, and policy regressions before a skill reaches an agent.

Agent Skills are portable folders built around `SKILL.md`. The reference validator checks the core format; SkillConform adds a complementary quality layer for security review, workspace scanning, policy tests, CI, JSON, and SARIF.

<p align="center">
<img src="docs/demo.svg" width="900" alt="SkillConform scanning seven Agent Skills and returning a clean pass">
</p>

> Status: `v0.1.1` developer preview. The npm CLI, library API, and GitHub Action are ready for early adopters. Security findings are evidence for review, not a certification.
> Status: `v0.3.0` development line on `main`. The CLI, library API, and GitHub Action are ready for early adopters; published registry releases may lag `main`. Static compatibility and security results are evidence for review, not runtime certification.

## Quick start

Expand All @@ -45,6 +45,15 @@ npx skillconform inventory ./skills --format json -o capabilities.json

The versioned `skillconform.capabilities/v1` document records declared tools, local references, bundled scripts, detected network hosts, shell/network signals, and portability notes. It is evidence for review and CI policy—not a claim that a skill is safe or compatible with every agent.

Compare the same skill against documented host constraints:

```bash
npx skillconform matrix ./skills
npx skillconform matrix ./skills --format json -o compatibility.json
```

The versioned `skillconform.compatibility/v1` matrix starts with Agent Skills, Claude Code, Claude API, OpenAI Skills, and Gemini CLI profiles. `PASS` means no static blocker was found, `REVIEW` means runtime/host evidence is still needed, and `UNSUPPORTED` means a documented constraint is contradicted. See [cross-agent compatibility profiles](docs/compatibility.md).

For a guided walkthrough, follow the [five-minute demo](docs/quick-demo.md).

To run from source:
Expand All @@ -64,6 +73,7 @@ node dist/src/cli.js audit ./skills --fail-on warning
| `check [path]` | Validate Agent Skills structure, metadata, naming, size, and references. |
| `audit [path]` | Run conformance checks plus deterministic security rules. |
| `inventory [path]` | Produce a deterministic capability/portability inventory. |
| `matrix [path]` | Compare static evidence with versioned host compatibility profiles. |
| `test [file]` | Execute regression expectations from `skillconform.yaml`. |
| `init [file]` | Create a starter policy-test configuration. |

Expand Down Expand Up @@ -167,7 +177,7 @@ process.stdout.write(renderReport(result, "json"));
- **CI-native:** reports work in terminals, scripts, and SARIF consumers.
- **Least privilege:** security rules favor explicit tools, paths, and network requirements.

Read [the architecture](docs/architecture.md), [SkillConform 2.0 direction](docs/skillconform-2.md), [roadmap](ROADMAP.md), and [contribution guide](CONTRIBUTING.md) before proposing larger changes.
Read [the architecture](docs/architecture.md), [cross-agent compatibility profiles](docs/compatibility.md), [SkillConform 2.0 direction](docs/skillconform-2.md), [roadmap](ROADMAP.md), and [contribution guide](CONTRIBUTING.md) before proposing larger changes.

## Community and launch resources

Expand Down
13 changes: 7 additions & 6 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ SkillConform is evolving toward an open-source CI and test suite for Agent Skill
- [x] CLI and TypeScript API for capability inventory.
- [x] Deterministic inventory of declared tools, references, bundled scripts, network hosts, and portability notes.
- [ ] JSON Schema for capability inventory and `skillconform.yaml`.
- [ ] Explicit client compatibility profiles.
- [x] Explicit client compatibility profiles.
- [ ] Configurable rule severities and documented suppressions.
- [ ] Incremental scanning for large repositories.

## v0.3 — Cross-agent compatibility

- Compatibility adapters for major Agent Skills hosts.
- `matrix` command with tested / untested / unsupported evidence per profile.
- Community-maintained compatibility fixtures.
- Shell and PowerShell command-aware analysis.
- Reusable CI examples for multi-agent skill repositories.
- [x] Versioned compatibility profiles for Agent Skills, Claude Code, Claude API, OpenAI Skills, and Gemini CLI.
- [x] `skillconform.compatibility/v1` matrix with pass / review / unsupported evidence.
- [x] `matrix` CLI, TypeScript API, GitHub Action mode, and provider-specific fixtures.
- [ ] Community-maintained compatibility fixtures.
- [ ] Shell and PowerShell command-aware analysis.
- [ ] Reusable CI examples for multi-agent skill repositories.

## v0.4 — Behavioral regression

Expand Down
10 changes: 5 additions & 5 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: SkillConform
description: Validate, inventory, and security-audit Agent Skills in GitHub Actions.
description: Validate, inventory, compare host compatibility, and security-audit Agent Skills in GitHub Actions.
author: Ramzi Sultan
branding:
icon: check-circle
Expand All @@ -10,7 +10,7 @@ inputs:
required: false
default: .
mode:
description: Mode: check, audit, or inventory.
description: Mode: check, audit, inventory, or matrix.
required: false
default: audit
fail-on:
Expand Down Expand Up @@ -45,10 +45,10 @@ runs:
SKILLCONFORM_FORMAT: ${{ inputs.format }}
SKILLCONFORM_OUTPUT: ${{ inputs.output }}
run: |
case "$SKILLCONFORM_MODE" in check|audit|inventory) ;; *) echo "mode must be check, audit, or inventory" >&2; exit 2 ;; esac
case "$SKILLCONFORM_MODE" in check|audit|inventory|matrix) ;; *) echo "mode must be check, audit, inventory, or matrix" >&2; exit 2 ;; esac
case "$SKILLCONFORM_FORMAT" in pretty|json|sarif) ;; *) echo "format must be pretty, json, or sarif" >&2; exit 2 ;; esac
if [[ "$SKILLCONFORM_MODE" == "inventory" && "$SKILLCONFORM_FORMAT" == "sarif" ]]; then
echo "inventory mode supports pretty or json format" >&2
if [[ ( "$SKILLCONFORM_MODE" == "inventory" || "$SKILLCONFORM_MODE" == "matrix" ) && "$SKILLCONFORM_FORMAT" == "sarif" ]]; then
echo "$SKILLCONFORM_MODE mode supports pretty or json format" >&2
exit 2
fi
case "$SKILLCONFORM_FAIL_ON" in error|warning|note|none) ;; *) echo "fail-on has an invalid value" >&2; exit 2 ;; esac
Expand Down
53 changes: 53 additions & 0 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Cross-agent compatibility profiles

SkillConform compatibility profiles turn documented host constraints into conservative, machine-readable checks.

The command is:

```bash
npx skillconform matrix ./skills
npx skillconform matrix ./skills --format json -o compatibility.json
```

The JSON schema identifier is `skillconform.compatibility/v1`. The initial profile set is versioned `2026-09-23`.

## Status semantics

- `pass`: no blocker is visible from deterministic static evidence for the checks SkillConform currently implements.
- `review`: the skill may work, but host-specific runtime, permissions, discovery placement, or dependencies still need verification.
- `unsupported`: the skill contradicts a documented constraint for that profile.

A `pass` is **not** a claim that the skill was executed successfully on that agent. Runtime claims belong in the future behavioral evaluation layer.

## Initial profiles

| Profile | Evidence encoded |
|---|---|
| Agent Skills standard | Core SkillConform conformance baseline; runtime is host-defined. |
| Claude Code | Claude-specific name constraints, local network model, and project discovery under `.claude/skills/<name>/SKILL.md`. |
| Claude API | Claude-specific name constraints plus the documented no-network and no-runtime-package-install environment. |
| OpenAI Skills | Open Agent Skills compatibility; host-specific permissions are surfaced for review rather than guessed. |
| Gemini CLI | Documented project discovery under `.agents/skills/<name>/SKILL.md`; host-specific permission behavior remains reviewable. |

## Sources

Profiles intentionally cite first-party documentation:

- Agent Skills specification: https://agentskills.io/specification
- Anthropic Agent Skills: https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview
- OpenAI Skills: https://developers.openai.com/api/docs/guides/tools-skills
- Google Gemini CLI Agent Skills codelab: https://codelabs.developers.google.com/gemini-cli/how-to-create-agent-skills-for-gemini-cli

When provider behavior changes, update the profile set version, add or change fixtures, and explain the change in the pull request.

## Non-goals

The matrix does not:

- claim that every runtime feature is statically knowable;
- execute untrusted skill scripts;
- infer unpublished provider behavior;
- convert a host-specific permission declaration into a universal permission model;
- replace real runtime evaluations.

The behavioral regression layer will add executable evidence separately so static portability and runtime behavior remain auditable concepts.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "skillconform",
"version": "0.2.0",
"description": "CI-native conformance, capability inventory, security review, and regression testing for Agent Skills.",
"version": "0.3.0",
"description": "CI-native conformance, capability inventory, cross-agent compatibility, security review, and regression testing for Agent Skills.",
"type": "module",
"bin": {
"skillconform": "dist/src/cli.js"
Expand Down Expand Up @@ -34,6 +34,8 @@
"skill-linter",
"claude-code",
"codex",
"gemini-cli",
"cross-agent",
"security",
"sarif"
],
Expand Down
14 changes: 11 additions & 3 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#!/usr/bin/env node
import { resolve } from "node:path";
import { buildCompatibilityMatrix, renderCompatibilityMatrix } from "./compatibility.js";
import { buildCapabilityInventory, renderCapabilityInventory } from "./inventory.js";
import { createPolicyConfig, runPolicyTests } from "./policy-tests.js";
import { renderReport, shouldFail, writeReport } from "./reporters.js";
import { scanTarget } from "./scanner.js";
import type { CliOptions, OutputFormat, Severity } from "./types.js";

const VERSION = "0.2.0";
const VERSION = "0.3.0";

interface ParsedArguments {
command: string;
Expand Down Expand Up @@ -48,6 +49,13 @@ async function main(): Promise<void> {
return;
}

if (parsed.command === "matrix") {
if (parsed.options.format === "sarif") throw new Error("The matrix command supports pretty or json output.");
const matrix = buildCompatibilityMatrix(parsed.target);
writeReport(renderCompatibilityMatrix(matrix, parsed.options.format), parsed.options.output);
return;
}

const mode = parsed.command === "audit" ? "audit" : "check";
const result = scanTarget(parsed.target, mode);
if (!parsed.options.quiet || parsed.options.output) {
Expand All @@ -66,7 +74,7 @@ function parseArguments(args: string[]): ParsedArguments {
if (args.includes("--version") || args.includes("-v")) return { command: "version", target: ".", options: defaults() };

const command = args[0] ?? "help";
if (!["check", "audit", "inventory", "test", "init"].includes(command)) throw new Error(`Unknown command '${command}'. Run skillconform --help.`);
if (!["check", "audit", "inventory", "matrix", "test", "init"].includes(command)) throw new Error(`Unknown command '${command}'. Run skillconform --help.`);
let target = command === "test" ? "skillconform.yaml" : ".";
const options = defaults();

Expand All @@ -76,7 +84,7 @@ function parseArguments(args: string[]): ParsedArguments {
if (arg === "--format") {
const value = args[++index];
if (value !== "pretty" && value !== "json" && value !== "sarif") throw new Error("--format must be pretty, json, or sarif.");
if ((command === "test" || command === "inventory") && value === "sarif") throw new Error(`The ${command} command supports pretty or json output.`);
if ((command === "test" || command === "inventory" || command === "matrix") && value === "sarif") throw new Error(`The ${command} command supports pretty or json output.`);
options.format = value as OutputFormat;
} else if (arg === "--output" || arg === "-o") {
const value = args[++index];
Expand Down
Loading
Loading