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.
Files changed (76) hide show
  1. caliper_eval-0.2.2/.github/workflows/publish.yml +25 -0
  2. caliper_eval-0.2.2/PKG-INFO +465 -0
  3. caliper_eval-0.2.2/README.md +428 -0
  4. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/run.py +16 -19
  5. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/harness/claude_code.py +19 -27
  6. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/autorater.py +2 -0
  7. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/base.py +2 -0
  8. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/claude_code_judge.py +12 -1
  9. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/codex_judge.py +2 -0
  10. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/openai_api_judge.py +2 -0
  11. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/script_assert.py +2 -0
  12. caliper_eval-0.2.2/caliper/resources/evaluate_skill/REFERENCE.md +110 -0
  13. caliper_eval-0.2.2/caliper/resources/evaluate_skill/SKILL.md +141 -0
  14. caliper_eval-0.2.2/caliper/runner.py +336 -0
  15. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/pyproject.toml +2 -1
  16. caliper_eval-0.2.2/skills/evaluate-skill/REFERENCE.md +110 -0
  17. caliper_eval-0.2.2/skills/evaluate-skill/SKILL.md +155 -0
  18. caliper_eval-0.2.2/skills/grill-skill/REFERENCE.md +94 -0
  19. caliper_eval-0.2.2/skills/grill-skill/SKILL.md +138 -0
  20. caliper_eval-0.2.2/skills/grill-skill/grill-skill.eval.yaml +146 -0
  21. caliper_eval-0.2.2/tests/claude-code-smoke.eval.yaml +18 -0
  22. caliper_eval-0.2.2/tests/codex-smoke.eval.yaml +17 -0
  23. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_runner.py +5 -5
  24. caliper_eval-0.2.0/PKG-INFO +0 -635
  25. caliper_eval-0.2.0/README.md +0 -599
  26. caliper_eval-0.2.0/assets/caliper-banner.png +0 -0
  27. caliper_eval-0.2.0/assets/demo.tape +0 -45
  28. caliper_eval-0.2.0/assets/logo.png +0 -0
  29. caliper_eval-0.2.0/caliper/resources/evaluate_skill/SKILL.md +0 -252
  30. caliper_eval-0.2.0/caliper/runner.py +0 -308
  31. caliper_eval-0.2.0/docs/launch-copy.md +0 -45
  32. caliper_eval-0.2.0/skills/evaluate-skill/SKILL.md +0 -252
  33. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/.gitignore +0 -0
  34. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/assets/caliper-demo.gif +0 -0
  35. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/__init__.py +0 -0
  36. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/__init__.py +0 -0
  37. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/install_skill.py +0 -0
  38. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/list_cmd.py +0 -0
  39. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/new.py +0 -0
  40. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/report.py +0 -0
  41. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/update_cli.py +0 -0
  42. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/commands/validate.py +0 -0
  43. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/harness/__init__.py +0 -0
  44. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/harness/base.py +0 -0
  45. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/harness/claude_api.py +0 -0
  46. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/harness/codex.py +0 -0
  47. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/harness/openai_api.py +0 -0
  48. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/judge/__init__.py +0 -0
  49. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/main.py +0 -0
  50. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/reporter.py +0 -0
  51. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/resources/__init__.py +0 -0
  52. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/resources/evaluate_skill/__init__.py +0 -0
  53. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/schema/__init__.py +0 -0
  54. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/schema/results.py +0 -0
  55. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/schema/spec.py +0 -0
  56. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/scoring.py +0 -0
  57. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/caliper/wizard.py +0 -0
  58. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/evaluate-skill.eval.yaml +0 -0
  59. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/claude-code-smoke/SKILL.md +0 -0
  60. {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
  61. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/commit-simple/SKILL.md +0 -0
  62. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/commit-simple/commit-simple.eval.yaml +0 -0
  63. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/screenshot/SKILL.md +0 -0
  64. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/screenshot/screenshot.eval.yaml +0 -0
  65. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/summarize/SKILL.md +0 -0
  66. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/summarize/summarize.eval.yaml +0 -0
  67. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/tdd/SKILL.md +0 -0
  68. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/evals/tdd/tdd.eval.yaml +0 -0
  69. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/skills/evaluate-skill/references/examples/simple.eval.yaml +0 -0
  70. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_claude_harness.py +0 -0
  71. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_claude_judge.py +0 -0
  72. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_codex_harness.py +0 -0
  73. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_codex_judge.py +0 -0
  74. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_install_skill.py +0 -0
  75. {caliper_eval-0.2.0 → caliper_eval-0.2.2}/tests/test_reporter.py +0 -0
  76. {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
+ [![PyPI](https://img.shields.io/pypi/v/caliper-eval.svg)](https://pypi.org/project/caliper-eval/)
41
+ [![Python](https://img.shields.io/pypi/pyversions/caliper-eval.svg)](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
+ ![Caliper terminal demo](assets/caliper-demo.gif)
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.