Skip to main content
Crilio

crilio

The CI/CD quality gate for AI — pytest for prompts.

If Crilio helps you, please ⭐ star this repo — it helps other devs find it and motivates me to keep building.

☁️ Join the Crilio Cloud Waitlist (Get 40% off team dashboards & analytics when we launch)

PyPI Python License


Crilio stops prompt regressions from reaching production. Version your prompts + natural-language rules in crilio.yaml — Crilio calls your model, judges every response with an LLM, and reports PASS / FAIL per rule.


✨ Features

  • LLM-as-a-Judge — Strict Pydantic-verified verdicts (rule_passed: bool), temp 0. No flaky free-text parsing.
  • BYOK — Your keys, your bill. OpenAI + Anthropic. Typically < $0.01 / test on gpt-4o-mini.
  • CI/CD Native — exit 1 blocks PRs in GitHub Actions. Locally it warns but never blocks.
  • PR Comments — Auto-posts formatted failure details to the PR when running in Actions (GITHUB_TOKEN, silent fail, never blocks gate).
  • Leak Guard — Rejects crilio.yaml containing sk-.../api_key — keys must be in .env/Secrets, never committed.
  • Local Bots — target: {command: "python bot.py '{{prompt}}'"} runs any local model (Ollama/vLLM) via stdout → Judge, $0 target.
  • Skip & List — skip: true per-test to pause, crilio ls [--tag] [--json] to preview tests without running.
  • Diff — crilio diff --base main shows prompt/rule changes between git refs (+/- per rule, not whole list).
  • Budget Guard — max_monthly_budget_usd halts the run when cost exceeds cap. Delete the line or leave it blank for unlimited.
  • Rich Terminal UI — crilio (no args) shows a STATUS / EXAMPLES / COMMANDS homepage; crilio run prints a Test / Prompt / Output / Verdict result table and a Gate PASS / Gate FAIL summary footer.
  • Fail-fast — crilio run --fail-fast stops after the first failure.

🚀 Quick Start

pip install crilio

export OPENAI_API_KEY="sk-proj-..."  # or ANTHROPIC_API_KEY — .env also works
crilio init                          # creates crilio.yaml
crilio run --dry-run                 # validate without API calls
crilio run                           # Target → Judge → gate

crilio with no args shows status, config, and next steps.


⚙️ Usage

Command Description
crilio init [--force] [--yes] Create crilio.yaml + optional GitHub Actions workflow
crilio ls [-c FILE] [--tag TAG] [--json] List tests — preview without running
crilio diff [--base REF] [-c FILE] [--json] [--fail-on-change] Show prompt/rule diff between git refs
crilio run [-c FILE] [-m MODEL] [--judge-model MODEL] [--verbose] [--json] [--dry-run] [--tag TAG] [--fail-fast] Run gate — 0 pass, 1 fail (only in CI) · --tag filters to tags: [TAG] tests
crilio validate [-c FILE] [--json] Validate config without API calls — 0 valid, 2 invalid
crilio --version / crilio --docs Version / full interactive guide
Variable Description
OPENAI_API_KEY OpenAI — default target gpt-4o-mini, judge gpt-4o-mini
ANTHROPIC_API_KEY Anthropic — default target claude-3-5-sonnet-latest, judge claude-3-5-haiku-latest

Provider is inferred from env if not set in crilio.yaml. Keys are never flags — env only.

crilio.yaml
# ==========================================
# Crilio Configuration (crilio.yaml)
# The CI/CD quality gate for AI.
# ==========================================

settings:
  # Provider is automatically inferred from your API key (OPENAI_API_KEY or ANTHROPIC_API_KEY)
  provider: openai

  # The AI model you are testing (Target)
  target_model: gpt-4o-mini

  # The fast/cheap model that grades the tests (Judge)
  judge_model: gpt-4o-mini

  # Hard limit on API spending per month (in USD) to prevent surprises
  max_monthly_budget_usd: 10.0

# ==========================================
# Test Cases
# ==========================================

tests:
  # Test 1: Semantic Rule Check (API)
  - name: "Refund Policy Check"
    prompt: "How long do I have to return a product?"
    rules:
      - "Must mention the 30-day return window."
      - "Must NOT mention competitor names like Amazon or Walmart."
    tags:
      - "refund"
      - "policy"
      - "customer service"

  # Test 2: JSON Formatting Enforcement (API)
  - name: "JSON Format Check"
    prompt: "Return my user status as JSON."
    rules:
      - "Must return valid JSON with keys 'status' and 'user_id'."
      - "Must NOT include apologies or extra prose."
    tags:
      - "json"
      - "formatting"

  # Test 3: Local Model Execution (Zero API Cost, Total Privacy)
  # Uncomment the lines below to test a local model via Ollama!
  # - name: "Local Llama 3 Check"
  #   prompt: "Say hello in a professional tone."
  #   target:
  #     command: "ollama run llama3 '{{prompt}}'"
  #   rules:
  #     - "Must contain the word 'Hello' or 'Hi'."
  #   tags:
  #     - "local"
  #     - "llama"

Keys:

  • provider: openai or anthropic
  • model / judge_model: override defaults
  • settings.max_monthly_budget_usd: monthly cap — run stops when exceeded, shows Budget: $spent / $cap (pct) after each test
  • system: global system prompt (passed to Target); per-test system overrides
  • tests[].name must be unique
  • tests[].rules are natural language — Judge is literal. Use Must / Must NOT.
  • tests[].tags optional list — filter with crilio run --tag smoke (no flag = all, missing tags = skipped when filtered)
  • tests[].target.command — local CLI e.g. python bot.py '{{prompt}}' or ollama run llama3 '{{prompt}}', {{prompt}} → shlex.quote, no placeholder → stdin pipe, timeout 30s, $0 target, injection-safe
  • tests[].skip — set skip: true to pause a test (shows SKIPPED)
  • Per-test provider/model/judge_model/system/tags/target/skip overrides global (advanced, needs its own key).
  • Leak Guard: crilio.yaml containing sk-... or api_key: fails validate/run (exit 2) — use .env / Secrets, never commit keys.
🦙 Ollama template — test any local model
# 1. ollama serve & ollama pull llama3  (or mistral, qwen2, etc.)
# 2. crilio.yaml:
settings:
  target_model: gpt-4o
  judge_model: gpt-4o-mini

tests:
  - name: Ollama Refund
    prompt: "How long do I have to return a product?"
    target:
      command: "ollama run llama3 '{{prompt}}'"  # any model: mistral, qwen2, gemma
      # no placeholder also works → stdin: command: "ollama run llama3"
    rules:
      - "Must mention the 30-day return window."
    tags: ["ollama", "local"]

# 3. export OPENAI_API_KEY="sk-..."  # Judge still API
# 4. crilio run --tag ollama --verbose

🔄 CI/CD Integration

crilio init can scaffold this for you. Or drop in .github/workflows/crilio.yml:

name: Crilio AI Tests
on: [pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write  # for PR failure comments
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - run: pip install crilio
      - run: crilio run
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}  # auto-provided for PR comments

Add the secret matching your provider. A FAIL gate exits 1 and blocks the PR. On failure in Actions, Crilio auto-posts a 🛑 Crilio AI Test Failed comment (test / rule / AI response / reason) via GITHUB_TOKEN + GITHUB_REPOSITORY / GITHUB_REF (refs/pull/12/merge → 12) — silent fail on API error (timeout/401) and locally, never blocks the gate.


📄 License

AGPL-3.0 — see LICENSE.

Metadata

Release files for crilio 0.0.8

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for crilio 0.0.8
File Size Uploaded
crilio-0.0.8.tar.gz 491.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for crilio 0.0.8
File Interpreter ABI Platform
crilio-0.0.8-py3-none-any.whl Python 3 none any Details

Total release size: 540.9 kB

Release files / crilio-0.0.8.tar.gz

Download URL crilio-0.0.8.tar.gz
Size 491.3 kB
Tags Source
SHA-256 checksum
How to use checksums
621adff438d2a834463150a78203e835e926af63d8d652ab2adb31f6c69ab5ca
BLAKE2b-256 checksum
How to use checksums
605f6774b9aa5465ade286df1424ad352e01f441c75701de148dd27053db37e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.9

Release files / crilio-0.0.8-py3-none-any.whl

Download URL crilio-0.0.8-py3-none-any.whl
Size 49.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c09bc33620217f633c4674a829a151f53b3651f81308df1ccc135af5ca9d39f6
BLAKE2b-256 checksum
How to use checksums
a24795c9eeb651cf362f7131a3fdacd746ac1194250f77388f343f7a25b74ec7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.9

Release history Release notifications | RSS feed

This release

0.0.8 This release

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page