caliper-eval 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- caliper_eval-0.2.2/.github/workflows/publish.yml +25 -0
- caliper_eval-0.2.2/PKG-INFO +465 -0
- caliper_eval-0.2.2/README.md +428 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/run.py +16 -19
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/harness/claude_code.py +19 -27
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/autorater.py +2 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/base.py +2 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/claude_code_judge.py +12 -1
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/codex_judge.py +2 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/openai_api_judge.py +2 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/script_assert.py +2 -0
- caliper_eval-0.2.2/caliper/resources/evaluate_skill/REFERENCE.md +110 -0
- caliper_eval-0.2.2/caliper/resources/evaluate_skill/SKILL.md +141 -0
- caliper_eval-0.2.2/caliper/runner.py +336 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/pyproject.toml +2 -1
- caliper_eval-0.2.2/skills/evaluate-skill/REFERENCE.md +110 -0
- caliper_eval-0.2.2/skills/evaluate-skill/SKILL.md +155 -0
- caliper_eval-0.2.2/skills/grill-skill/REFERENCE.md +94 -0
- caliper_eval-0.2.2/skills/grill-skill/SKILL.md +138 -0
- caliper_eval-0.2.2/skills/grill-skill/grill-skill.eval.yaml +146 -0
- caliper_eval-0.2.2/tests/claude-code-smoke.eval.yaml +18 -0
- caliper_eval-0.2.2/tests/codex-smoke.eval.yaml +17 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_runner.py +5 -5
- caliper_eval-0.2.0/PKG-INFO +0 -635
- caliper_eval-0.2.0/README.md +0 -599
- caliper_eval-0.2.0/assets/caliper-banner.png +0 -0
- caliper_eval-0.2.0/assets/demo.tape +0 -45
- caliper_eval-0.2.0/assets/logo.png +0 -0
- caliper_eval-0.2.0/caliper/resources/evaluate_skill/SKILL.md +0 -252
- caliper_eval-0.2.0/caliper/runner.py +0 -308
- caliper_eval-0.2.0/docs/launch-copy.md +0 -45
- caliper_eval-0.2.0/skills/evaluate-skill/SKILL.md +0 -252
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/.gitignore +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/assets/caliper-demo.gif +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/__init__.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/__init__.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/install_skill.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/list_cmd.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/new.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/report.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/update_cli.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/validate.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/harness/__init__.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/harness/base.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/harness/claude_api.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/harness/codex.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/harness/openai_api.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/__init__.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/main.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/reporter.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/resources/__init__.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/resources/evaluate_skill/__init__.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/schema/__init__.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/schema/results.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/schema/spec.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/scoring.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/wizard.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/evaluate-skill.eval.yaml +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/claude-code-smoke/SKILL.md +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/claude-code-smoke/claude-code-smoke.eval.yaml +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/commit-simple/SKILL.md +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/commit-simple/commit-simple.eval.yaml +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/screenshot/SKILL.md +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/screenshot/screenshot.eval.yaml +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/summarize/SKILL.md +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/summarize/summarize.eval.yaml +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/tdd/SKILL.md +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/tdd/tdd.eval.yaml +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/examples/simple.eval.yaml +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_claude_harness.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_claude_judge.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_codex_harness.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_codex_judge.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_install_skill.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_reporter.py +0 -0
- {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_update_cli.py +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
id-token: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
pypi:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
environment: pypi
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.x"
|
|
20
|
+
- name: Build distributions
|
|
21
|
+
run: |
|
|
22
|
+
python -m pip install --upgrade build
|
|
23
|
+
python -m build
|
|
24
|
+
- name: Publish to PyPI
|
|
25
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: caliper-eval
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: CLI for evaluating Claude Code skills and AI agents
|
|
5
|
+
Project-URL: Homepage, https://github.com/edonadei/caliper
|
|
6
|
+
Project-URL: Repository, https://github.com/edonadei/caliper
|
|
7
|
+
Project-URL: Issues, https://github.com/edonadei/caliper/issues
|
|
8
|
+
Project-URL: Skills, https://clawhub.ai/edonadei/evaluate-skill
|
|
9
|
+
Author: Emrick Donadei
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
Keywords: agents,ai,claude,codex,evals,skills
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Software Development :: Testing
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: anthropic>=0.28
|
|
25
|
+
Requires-Dist: pydantic>=2
|
|
26
|
+
Requires-Dist: pyyaml>=6
|
|
27
|
+
Requires-Dist: rich>=13
|
|
28
|
+
Requires-Dist: typer>=0.15
|
|
29
|
+
Provides-Extra: codex
|
|
30
|
+
Requires-Dist: openai>=1.0; extra == 'codex'
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
34
|
+
Provides-Extra: openai
|
|
35
|
+
Requires-Dist: openai>=1.0; extra == 'openai'
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
# Caliper
|
|
39
|
+
|
|
40
|
+
[](https://pypi.org/project/caliper-eval/)
|
|
41
|
+
[](https://pypi.org/project/caliper-eval/)
|
|
42
|
+
|
|
43
|
+
**pytest for agent skills.** Write a task in YAML, run it k times, get a reliability score.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx skills@latest add edonadei/caliper
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
Agent skills are hard to test. A skill that works on your machine, on this prompt, today, might fail tomorrow after a model update or a one-line prompt edit. Caliper makes reliability measurable: define what success looks like, run the skill repeatedly, and get a pass@k score you can track over time.
|
|
52
|
+
|
|
53
|
+
Use Caliper to answer questions like:
|
|
54
|
+
|
|
55
|
+
- Did my prompt edit actually improve the skill?
|
|
56
|
+
- Is the skill doing the work, or would the base agent pass without it?
|
|
57
|
+
- Does it still pass the workflows it passed last week?
|
|
58
|
+
- Which backend — Claude Code or Codex — runs this skill more reliably?
|
|
59
|
+
|
|
60
|
+

|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## How it works
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
.eval.yaml spec
|
|
68
|
+
│
|
|
69
|
+
▼
|
|
70
|
+
Harness ──── runs your skill against the agent (Claude Code / Codex / API)
|
|
71
|
+
│
|
|
72
|
+
▼
|
|
73
|
+
Judge ──── LLM autorater and/or deterministic Python assertions
|
|
74
|
+
│
|
|
75
|
+
▼
|
|
76
|
+
pass@k score + saved transcript
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Each attempt runs in an isolated temporary home with no session history. Results are saved as JSON you can inspect and diff later.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Quick start
|
|
84
|
+
|
|
85
|
+
**1. Install**
|
|
86
|
+
|
|
87
|
+
Install the `evaluate-skill` agent skill — it handles everything from inside your agent:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npx skills@latest add edonadei/caliper
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Or install the CLI directly if you prefer running evals from the terminal:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
pipx install caliper-eval
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Requires Python 3.10+.
|
|
100
|
+
|
|
101
|
+
**2. Create a spec**
|
|
102
|
+
|
|
103
|
+
```yaml
|
|
104
|
+
# my-skill.eval.yaml
|
|
105
|
+
skill:
|
|
106
|
+
path: ./SKILL.md
|
|
107
|
+
backend: claude-code
|
|
108
|
+
|
|
109
|
+
judge:
|
|
110
|
+
backend: claude-code
|
|
111
|
+
|
|
112
|
+
tasks:
|
|
113
|
+
- name: Writes a greeting file
|
|
114
|
+
cleanup: rm -f /tmp/hello.txt
|
|
115
|
+
prompt: "Write 'hello world' to /tmp/hello.txt"
|
|
116
|
+
expect: "A file at /tmp/hello.txt containing 'hello world' was created."
|
|
117
|
+
assert: |
|
|
118
|
+
from pathlib import Path
|
|
119
|
+
assert Path("/tmp/hello.txt").read_text().strip() == "hello world"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**3. Run it**
|
|
123
|
+
|
|
124
|
+
If you installed via the skill, ask your agent:
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
/evaluate-skill run my-skill.eval.yaml --k 3 --baseline
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Or from the terminal if you installed the CLI:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
caliper run my-skill.eval.yaml --k 3 --baseline
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**4. Read the output**
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
CALIPER - my-skill - k=3 - claude-code
|
|
140
|
+
|
|
141
|
+
ID Task k (3) pass@k
|
|
142
|
+
task-1 Writes a greeting file 3/3 100% PASS
|
|
143
|
+
|
|
144
|
+
With skill 100% ####################
|
|
145
|
+
No skill 70% ##############------
|
|
146
|
+
Delta +30% up
|
|
147
|
+
|
|
148
|
+
Results saved to .caliper/results/my-skill/2026-06-19T14-23-01Z.json
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Browse past results anytime:
|
|
152
|
+
|
|
153
|
+
```text
|
|
154
|
+
/evaluate-skill list
|
|
155
|
+
/evaluate-skill report my-skill
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Core concepts
|
|
161
|
+
|
|
162
|
+
| Term | What it is |
|
|
163
|
+
|---|---|
|
|
164
|
+
| **Spec** | A `.eval.yaml` file that describes the skill, judge, and tasks to run |
|
|
165
|
+
| **Backend** | The agent that executes the skill (`claude-code`, `codex`, `claude-api`, `openai-api`) |
|
|
166
|
+
| **Judge** | What decides pass/fail — an LLM reading the transcript (`expect:`), Python assertions (`assert:`), or both |
|
|
167
|
+
| **pass@k** | Reliability score: run k times, measure how often the skill succeeds |
|
|
168
|
+
| **Baseline** | Re-run the same tasks without the skill to prove the skill is doing the work |
|
|
169
|
+
| **Attempt** | One isolated run of a single task — fresh temporary home, no session history |
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Choosing a backend
|
|
174
|
+
|
|
175
|
+
| Backend | Requires | Best for |
|
|
176
|
+
|---|---|---|
|
|
177
|
+
| `claude-code` | Claude Code CLI installed and authenticated | Testing Claude Code slash-command skills |
|
|
178
|
+
| `codex` | Codex CLI installed (`npm install -g @openai/codex`) | Testing Codex skills |
|
|
179
|
+
| `claude-api` | `ANTHROPIC_API_KEY` env var | API-backed agents, no CLI needed |
|
|
180
|
+
| `openai-api` | `OPENAI_API_KEY` env var | OpenAI API agents |
|
|
181
|
+
|
|
182
|
+
The agent backend and judge backend are independent — you can test a Codex skill with a Claude judge, or any other combination.
|
|
183
|
+
|
|
184
|
+
### Claude Code setup
|
|
185
|
+
|
|
186
|
+
Install and authenticate the `claude` CLI. `backend: claude-code` uses your existing Claude Code auth — no extra configuration needed.
|
|
187
|
+
|
|
188
|
+
For `backend: claude-api`:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
export ANTHROPIC_API_KEY=...
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Codex setup
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
npm install -g @openai/codex
|
|
198
|
+
codex login
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
`backend: codex` calls `codex exec`. It does not fall back to the OpenAI API. If the Codex desktop app is installed, Caliper prefers the app-bundled binary over `codex` on `PATH`. Set `CODEX_CLI_PATH` to force a specific binary.
|
|
202
|
+
|
|
203
|
+
For `backend: openai-api`:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
export OPENAI_API_KEY=...
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Check installed CLI versions:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
caliper update-cli --check
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Recommended workflow
|
|
218
|
+
|
|
219
|
+
1. Create a spec for one behavior you care about.
|
|
220
|
+
2. Run with `--k 1` while iterating on the spec.
|
|
221
|
+
3. Add `assert:` for facts an LLM judge might guess wrong (files, JSON, command output).
|
|
222
|
+
4. Move to `--k 3` or higher once the task is stable.
|
|
223
|
+
5. Add `--baseline` to prove the skill is making a difference.
|
|
224
|
+
6. Commit the spec alongside the skill so contributors can run the same eval.
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
caliper run my-skill.eval.yaml --k 3 --baseline --verbose
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Spec format
|
|
233
|
+
|
|
234
|
+
```yaml
|
|
235
|
+
skill:
|
|
236
|
+
path: ./SKILL.md # path to the skill file (optional for baseline-only runs)
|
|
237
|
+
backend: claude-code # claude-code | codex | claude-api | openai-api
|
|
238
|
+
model: <model-name> # optional model override
|
|
239
|
+
|
|
240
|
+
judge:
|
|
241
|
+
backend: claude-code # claude-code | codex | claude-api | openai-api
|
|
242
|
+
model: <model-name> # optional model override
|
|
243
|
+
|
|
244
|
+
sandbox:
|
|
245
|
+
extra_path:
|
|
246
|
+
- ./bin # prepended to PATH inside each attempt
|
|
247
|
+
forbidden_files:
|
|
248
|
+
- ".*\\.eval\\.yaml$" # prevents agent from reading the spec
|
|
249
|
+
- "./.caliper/.*" # prevents agent from reading saved results
|
|
250
|
+
|
|
251
|
+
tasks:
|
|
252
|
+
- name: Short task name
|
|
253
|
+
setup: <shell command> # optional, runs before each attempt
|
|
254
|
+
cleanup: <shell command> # optional, always runs after each attempt
|
|
255
|
+
prompt: <prompt sent to the agent>
|
|
256
|
+
expect: <natural-language success condition>
|
|
257
|
+
assert: |
|
|
258
|
+
# optional inline Python assertion
|
|
259
|
+
assert True
|
|
260
|
+
|
|
261
|
+
- name: Task with external assertion script
|
|
262
|
+
prompt: "Generate a report"
|
|
263
|
+
assert: ./assertions/check_report.py
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Each task needs at least one of `expect` or `assert`. Task IDs are assigned automatically as `task-001`, `task-002`, and so on.
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Judging
|
|
271
|
+
|
|
272
|
+
### LLM autorater (`expect:`)
|
|
273
|
+
|
|
274
|
+
The judge backend reads the full attempt transcript and decides whether the `expect` condition was met. When the backend captures tool-call traces (Claude Code, Codex), those traces are included — the judge can verify things like "the agent used tool X" without relying on the final text alone.
|
|
275
|
+
|
|
276
|
+
```yaml
|
|
277
|
+
judge:
|
|
278
|
+
backend: claude-code
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Deterministic assertions (`assert:`)
|
|
282
|
+
|
|
283
|
+
Python assertions run locally. Use these for facts the LLM judge might guess:
|
|
284
|
+
|
|
285
|
+
- file exists / exact file contents
|
|
286
|
+
- JSON / schema validity
|
|
287
|
+
- command output
|
|
288
|
+
- images or screenshots
|
|
289
|
+
- repository state
|
|
290
|
+
|
|
291
|
+
```yaml
|
|
292
|
+
tasks:
|
|
293
|
+
- name: Writes an output file
|
|
294
|
+
cleanup: rm -f /tmp/out.txt
|
|
295
|
+
prompt: "Write hello world to /tmp/out.txt"
|
|
296
|
+
assert: |
|
|
297
|
+
from pathlib import Path
|
|
298
|
+
path = Path("/tmp/out.txt")
|
|
299
|
+
assert path.exists(), "Output file was not created"
|
|
300
|
+
assert path.read_text().strip() == "hello world"
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
When both `expect` and `assert` are present, both must pass.
|
|
304
|
+
|
|
305
|
+
### `--judge` flag
|
|
306
|
+
|
|
307
|
+
| Flag | Behavior |
|
|
308
|
+
|---|---|
|
|
309
|
+
| `--judge autorater` (default) | LLM judge evaluates `expect` |
|
|
310
|
+
| `--judge script` | Runs `assert:` always; also runs LLM judge if `expect` is present |
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## CLI reference
|
|
315
|
+
|
|
316
|
+
| Command | Description |
|
|
317
|
+
|---|---|
|
|
318
|
+
| `caliper run <spec>` | Run an evaluation spec |
|
|
319
|
+
| `caliper new [name]` | Create a new spec with the interactive wizard |
|
|
320
|
+
| `caliper validate <spec>` | Validate a spec file |
|
|
321
|
+
| `caliper list [spec]` | List specs and saved runs |
|
|
322
|
+
| `caliper report <spec-or-result>` | Re-render saved results |
|
|
323
|
+
| `caliper install-skill <backend>` | Install the bundled evaluate-skill into Claude Code or Codex |
|
|
324
|
+
| `caliper update-cli [backend]` | Check or update installed agent CLI versions |
|
|
325
|
+
|
|
326
|
+
### `caliper run` flags
|
|
327
|
+
|
|
328
|
+
| Flag | Default | Description |
|
|
329
|
+
|---|---|---|
|
|
330
|
+
| `--k INT` | `3` | Attempts per task |
|
|
331
|
+
| `--baseline` | off | Also run each task without the skill |
|
|
332
|
+
| `--judge MODE` | `autorater` | `autorater` or `script` |
|
|
333
|
+
| `--workers INT` | `4` | Parallel task workers |
|
|
334
|
+
| `--timeout INT` | `120` | Seconds per attempt |
|
|
335
|
+
| `--model MODEL` | — | Override `skill.model` |
|
|
336
|
+
| `--verbose` | off | Show per-attempt judge reasoning |
|
|
337
|
+
| `--output PATH` | — | Also save results JSON to a specific path |
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Scoring
|
|
342
|
+
|
|
343
|
+
For each task:
|
|
344
|
+
|
|
345
|
+
```
|
|
346
|
+
pass@k = 1 - (1 - successes / k) ^ k
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
The aggregate score is the average task pass@k. With `--baseline`, Caliper runs the same tasks without the skill and reports the delta.
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## Agent skills
|
|
354
|
+
|
|
355
|
+
The repo ships two agent skills. Install both with:
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
npx skills@latest add edonadei/caliper
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### `evaluate-skill` — run and manage evals
|
|
362
|
+
|
|
363
|
+
Create, validate, run, and summarize evals from inside your normal workflow — no separate terminal needed. The skill installs Caliper automatically if it's missing.
|
|
364
|
+
|
|
365
|
+
Or, if you already have Caliper installed and want to wire up the skill manually:
|
|
366
|
+
|
|
367
|
+
```bash
|
|
368
|
+
caliper install-skill claude-code
|
|
369
|
+
caliper install-skill codex
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Preview without writing files:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
caliper install-skill claude-code --dry-run
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Then use it in Claude Code:
|
|
379
|
+
|
|
380
|
+
```text
|
|
381
|
+
/evaluate-skill run my-skill.eval.yaml --k 3
|
|
382
|
+
/evaluate-skill validate my-skill.eval.yaml
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Or in Codex:
|
|
386
|
+
|
|
387
|
+
```text
|
|
388
|
+
Use the evaluate-skill skill to run my-skill.eval.yaml with k=3 and summarize the result.
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### `grill-skill` — create evals interactively
|
|
392
|
+
|
|
393
|
+
Don't have evals yet? `grill-skill` guides you through creating them. It reads your `SKILL.md`, interviews you about what good behavior looks like, and generates a 3-task spec (happy path, edge case, adversarial). Then it runs the eval and loops — k=1 to validate, k=3 to measure, baseline before you commit.
|
|
394
|
+
|
|
395
|
+
```text
|
|
396
|
+
/grill-skill ./my-skill/SKILL.md
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
No path needed if you're already in the skill's directory:
|
|
400
|
+
|
|
401
|
+
```text
|
|
402
|
+
/grill-skill
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
If an `.eval.yaml` already exists next to your skill, `grill-skill` reads the existing tasks and interviews you about gaps instead of starting from scratch.
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## Project layout
|
|
410
|
+
|
|
411
|
+
```text
|
|
412
|
+
caliper/
|
|
413
|
+
commands/ CLI command implementations
|
|
414
|
+
harness/ Agent execution backends (Claude Code, Codex, API)
|
|
415
|
+
judge/ LLM and script judging implementations
|
|
416
|
+
schema/ Eval spec and result models
|
|
417
|
+
runner.py Evaluation orchestration
|
|
418
|
+
skills/
|
|
419
|
+
evaluate-skill/ Agent skill for running Caliper from Claude Code or Codex
|
|
420
|
+
grill-skill/ Agent skill for creating and iterating on evals interactively
|
|
421
|
+
tests/ Pytest coverage for harnesses, judges, and runner behavior
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## Contributing
|
|
427
|
+
|
|
428
|
+
Good first areas:
|
|
429
|
+
|
|
430
|
+
- add example evals for real skills
|
|
431
|
+
- improve backend error messages
|
|
432
|
+
- add deterministic assertion helpers
|
|
433
|
+
- expand tests for harness and judge behavior
|
|
434
|
+
- improve result reporting and summaries
|
|
435
|
+
- document common setup problems for Claude Code and Codex
|
|
436
|
+
|
|
437
|
+
Before opening a pull request:
|
|
438
|
+
|
|
439
|
+
```bash
|
|
440
|
+
pip install -e ".[dev,openai]"
|
|
441
|
+
pytest
|
|
442
|
+
ruff check .
|
|
443
|
+
caliper validate skills/evaluate-skill/evaluate-skill.eval.yaml
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
When changing behavior, include a test or an eval fixture that demonstrates the expected outcome. Keep backend-specific logic isolated to the relevant module under `caliper/harness/` or `caliper/judge/`.
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## Troubleshooting
|
|
451
|
+
|
|
452
|
+
**`codex judge failed: model ... is not supported`**
|
|
453
|
+
The model name is not available to your Codex account. Use a model that `codex exec --model <name>` accepts.
|
|
454
|
+
|
|
455
|
+
**`codex CLI not found`**
|
|
456
|
+
|
|
457
|
+
```bash
|
|
458
|
+
npm install -g @openai/codex
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
**`claude` command not found**
|
|
462
|
+
Install and authenticate Claude Code, or switch the backend to `codex`, `claude-api`, or `openai-api`.
|
|
463
|
+
|
|
464
|
+
**A task passes only because of `assert:`**
|
|
465
|
+
When a task has only `assert:`, no LLM judge runs. Add `expect:` if you also want an LLM to evaluate the transcript.
|