# How to Integrate SkillSpector into CI/CD Pipelines Using Exit Codes

> Integrate SkillSpector into CI CD pipelines with exit codes. Automate AI agent skill package gating using risk scores and machine readable JSON output for seamless deployment.

- Repository: [NVIDIA Corporation/SkillSpector](https://github.com/NVIDIA/SkillSpector)
- Tags: how-to-guide
- Published: 2026-07-09

---

**SkillSpector provides deterministic exit codes (0, 1, and 2) that allow CI/CD systems to automatically gate AI-agent skill packages based on risk scores, with machine-readable JSON output for detailed automation.**

The NVIDIA/SkillSpector repository offers a purpose-built CLI for scanning AI-agent skill packages to detect security risks. By leveraging the exit code contract implemented in [`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py) and the JSON serialization from [`src/skillspector/models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/models.py), you can create robust CI/CD gates that block high-risk deployments without manual intervention.

## Understanding SkillSpector Exit Codes

SkillSpector implements a three-state exit code system designed for automation, as documented in the repository's exit codes section. According to the NVIDIA/SkillSpector source code, the CLI returns specific codes to indicate scan success and risk thresholds:

| Exit Code | Condition | Risk Score | Recommendation |
|-----------|-----------|------------|----------------|
| **0** | Scan succeeded | ≤ 50 | SAFE or CAUTION |
| **1** | Scan succeeded | > 50 | DO_NOT_INSTALL |
| **2** | Scan failed | N/A | Invalid input or internal error |

### Exit Code 0 (Pass)

When `skillspector scan` exits with code 0, the skill passed all security checks with an acceptable risk profile. This occurs when the risk assessment score is 50 or below, yielding either SAFE or CAUTION recommendations.

### Exit Code 1 (High Risk)

Exit code 1 indicates the scan completed successfully but detected critical security concerns. According to the exit code logic in [`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py), this triggers when the risk score exceeds 50 and the recommendation becomes DO_NOT_INSTALL, signaling that the skill should not be deployed.

### Exit Code 2 (Scan Failure)

Code 2 represents a scan failure unrelated to risk assessment. This covers invalid input paths, unreadable source files, or internal execution errors in the scanning engine, requiring immediate pipeline troubleshooting.

## Capturing Machine-Readable JSON Output

For detailed automation beyond simple pass/fail gates, SkillSpector supports structured output via the `--format json` flag. As implemented in [`src/skillspector/models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/models.py), the `Finding.to_dict()` method serializes scan results into a predictable schema:

```json
{
  "skill": { "name": "...", "source": "...", "scanned_at": "<ISO‑8601>" },
  "risk_assessment": { "score": 0, "severity": "LOW", "recommendation": "SAFE" },
  "components": [],
  "issues": [],
  "metadata": {
    "has_executable_scripts": false,
    "skillspector_version": "...",
    "llm_requested": true,
    "llm_available": true
  }
}

```

You can write this output to a file using `-o` or `--output` for artifact collection and downstream parsing.

## Implementing CI/CD Integration

### Installation

Install the SkillSpector CLI as a step in your pipeline configuration using `uv` for fast, isolated tool installation:

```bash
uv tool install git+https://github.com/NVIDIA/SkillSpector.git

```

For MCP server capabilities, include the optional dependency:

```bash
uv tool install 'skillspector[mcp] @ git+https://github.com/NVIDIA/SkillSpector.git'

```

### Basic Gate Implementation

Use the exit code directly with shell error handling to create a simple security gate. This pattern leverages `set -e` behavior common in CI environments:

```bash
if ! skillspector scan ./my-skill/ --format json -o skill_report.json; then
    echo "⚠️  Skill rejected – see skill_report.json"
    exit 1    # abort the pipeline

fi
echo "✅  Skill passed (score ≤ 50)"

```

### Fine-Grained Risk Handling

Parse the JSON output to differentiate between SAFE and CAUTION recommendations, allowing conditional pipeline behavior:

```bash
RECOMMENDATION=$(jq -r '.risk_assessment.recommendation' skill_report.json)
case "$RECOMMENDATION" in
  SAFE)   echo "✅  Safe – continue";;
  CAUTION) echo "⚠️  Caution – may require manual review";;
  DO_NOT_INSTALL) echo "❌  Do not install – failing build"; exit 1;;
esac

```

## Complete GitHub Actions Example

This workflow demonstrates production-grade integration with artifact upload, exit code evaluation, and conditional alerting:

```yaml
name: CI – Skill Safety Check
on: [push, pull_request]

jobs:
  skillspector:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install uv (optional)
        run: curl -LsSf https://github.com/astral-sh/uv/releases/latest/download/uv-installer.sh | sh

      - name: Install SkillSpector CLI
        run: uv tool install git+https://github.com/NVIDIA/SkillSpector.git

      - name: Run SkillSpector scan
        id: scan
        run: |
          skillspector scan ./my-skill/ \
            --format json \
            --output skill_report.json
        continue-on-error: true   # we want to inspect the report even on failure

      - name: Upload report artifact
        uses: actions/upload-artifact@v4
        with:
          name: skill-report
          path: skill_report.json

      - name: Enforce gate based on exit code
        if: steps.scan.outcome != 'success'
        run: |
          echo "❌ SkillSpector detected high‑risk issues – see artifact"
          exit 1

      - name: Optional CAUTION handling
        run: |
          RECOMMEND=$(jq -r '.risk_assessment.recommendation' skill_report.json)
          if [ "$RECOMMEND" = "CAUTION" ]; then
            echo "⚠️  CAUTION – flagging for manual review"
            # e.g., comment on PR, create a ticket, etc.

          fi

```

## Key Source Files

Understanding these implementation files helps when debugging CI integration issues:

- **[`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py)**: Contains the CLI entry point, argument parsing for `--format` and `--output`, and the exit code logic that returns 0, 1, or 2 based on risk scores.
- **[`src/skillspector/models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/models.py)**: Defines the data models and `Finding.to_dict()` method that generates the JSON schema consumed by your CI pipelines.
- **[`docs/SUPPRESSION.md`](https://github.com/NVIDIA/SkillSpector/blob/main/docs/SUPPRESSION.md)**: Provides baseline configuration options for handling false positives, essential for keeping CI reports stable across runs.
- **[`pyproject.toml`](https://github.com/NVIDIA/SkillSpector/blob/main/pyproject.toml)**: Declares the `skillspector[mcp]` optional extras and version metadata.

## Summary

- **Exit code 0** indicates successful scans with risk scores ≤ 50 (SAFE/CAUTION), while **exit code 1** signals high-risk skills (DO_NOT_INSTALL) and **exit code 2** indicates scan failures.
- Use `--format json` and `--output` to capture machine-readable reports for artifact storage and programmatic parsing.
- Implement gates using shell conditionals on exit codes, or parse JSON fields like `.risk_assessment.recommendation` for granular control.
- Reference [`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py) for exit code logic and [`src/skillspector/models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/models.py) for JSON schema details when building custom integrations.

## Frequently Asked Questions

### What do the SkillSpector exit codes mean in CI/CD contexts?

Exit code 0 means the skill passed security checks with a low risk score (≤ 50), exit code 1 means the scan succeeded but detected high-risk issues requiring blocking (score > 50, DO_NOT_INSTALL), and exit code 2 indicates the scan failed due to invalid inputs or internal errors. According to the NVIDIA/SkillSpector source code, these codes are generated in [`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py) to provide deterministic gating behavior.

### How do I parse SkillSpector JSON output in a CI pipeline?

Use standard JSON parsing tools like `jq` to extract specific fields from the report generated with `--format json`. Common patterns include reading `.risk_assessment.recommendation` to distinguish between SAFE and CAUTION states, or checking `.risk_assessment.score` for numeric thresholds. The JSON structure is defined by the `Finding.to_dict()` method in [`src/skillspector/models.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/models.py).

### Can I suppress false positives in CI runs?

Yes, SkillSpector supports baseline and suppression configurations documented in [`docs/SUPPRESSION.md`](https://github.com/NVIDIA/SkillSpector/blob/main/docs/SUPPRESSION.md). You can create a suppression file to exclude known acceptable patterns from risk scoring, ensuring that CI pipelines only flag new or unhandled security concerns rather than failing on approved components.

### Where is the exit code logic implemented in SkillSpector?

The exit code mapping is implemented in [`src/skillspector/cli.py`](https://github.com/NVIDIA/SkillSpector/blob/main/src/skillspector/cli.py), which evaluates the risk score after scan completion and returns 0 for acceptable risk (≤ 50), 1 for high risk (> 50), or 2 for execution failures. This deterministic contract allows CI systems to rely on standard shell exit status checking without parsing output text.