SkillOx GitHub Action

Audit every SKILL.md changed in a pull request. Findings post as inline annotations on the diff, a summary comment lands on the PR, and CI fails when any file drops below your team's minimum grade. Two lines of YAML to install.

Quick start

Drop this into .github/workflows/skillox.yml in your repo:

# .github/workflows/skillox.yml
name: SkillOx

on:
  pull_request:
    paths: ['**/SKILL.md']

permissions:
  contents: read
  pull-requests: write   # for the per-PR audit comment

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: skillox/skillox-action@v1
        with:
          minimum-grade: B   # A | B | C | D | F

From the next pull request onward, every change touching a SKILL.md gets scanned. Reviewers see inline annotations on the offending lines, a summary table on the PR, and the workflow blocks merge when any file scores below the threshold.

Inputs

InputDefaultWhat it does
paths**/SKILL.mdComma-separated globs. On PR events, intersected with the changed-files set so monorepo PRs only scan what actually moved.
minimum-gradeBLowest grade that won't fail CI. A | B | C | D | F.
api-basehttps://api.skillox.ioOverride for self-hosted or staging endpoints.
api-keyOptional Authorization: Bearer …. Lifts rate limits, unlocks Pro-tier features once API-key auth ships.
comment-on-prtrueSet false if you want annotations + summary only, no PR comment.
fail-on-errortrueWhen true, scan errors (network, oversize) also fail CI. Set false to only fail on threshold violations.

Outputs

Common patterns

Only block on F-grade

Don't fail CI on D's — surface them as annotations only. Useful while ramping up scanner adoption:

- uses: skillox/skillox-action@v1
  with:
    minimum-grade: D   # only F blocks CI

Monorepo with skills under multiple directories

- uses: skillox/skillox-action@v1
  with:
    paths: 'apps/agents/**/SKILL.md,packages/skills/**/*.md'
    minimum-grade: B

Push to Slack on every non-A result

- id: audit
  uses: skillox/skillox-action@v1
  with:
    minimum-grade: B

- if: always() && steps.audit.outputs.worst-grade != 'A'
  uses: slackapi/slack-github-action@v2
  with:
    payload: |
      {
        "text": "SkillOx audit: worst grade ${{ steps.audit.outputs.worst-grade }} on ${{ github.event.pull_request.html_url }}"
      }

How it works

  1. On pull_request events, queries the GitHub API for the changed-files set and intersects with paths. On push / manual / scheduled runs, walks the working tree.
  2. Reads each file's content + POSTs them in a single /scan/bulk call (max 50 files). No content is persisted unless you opt in.
  3. Per finding becomes a line-level ::warning:: or ::error:: annotation on the diff. Per-file threshold violations become file-level annotations.
  4. Workflow summary table + PR comment posted. The comment is updated in place on re-runs via a hidden marker, so iterative PRs don't accumulate comment spam.
  5. Exits non-zero when any file is below threshold (or, with fail-on-error: true, when any scan errored out).
Source + bundle are Apache-2.0 under skillox/skillox-action. PRs welcome.