skillbench-cli 0.1.0__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.
@@ -0,0 +1,6 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ dist/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Adam Saul
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,218 @@
1
+ Metadata-Version: 2.5
2
+ Name: skillbench-cli
3
+ Version: 0.1.0
4
+ Summary: Test your Claude Code skills and agent workflows, the way you test code.
5
+ Project-URL: Homepage, https://github.com/adamsaul314/skillbench
6
+ Project-URL: Issues, https://github.com/adamsaul314/skillbench/issues
7
+ Author: Adam Saul
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: agents,claude,claude-code,evals,skills,testing
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Software Development :: Testing
17
+ Requires-Python: >=3.11
18
+ Requires-Dist: pyyaml>=6.0
19
+ Requires-Dist: rich>=13.7
20
+ Description-Content-Type: text/markdown
21
+
22
+ # skillbench
23
+
24
+ Test your Claude Code skills and agent workflows, the way you test code.
25
+
26
+ You write a small YAML file that says *"send this to Claude, then check these things"*. skillbench runs Claude Code for real on a copy of your repo, records everything it did, and tells you **pass** or **fail**.
27
+
28
+ ---
29
+
30
+ ## 1. Install
31
+
32
+ You need Python 3.11+, git, and Claude Code installed and logged in (check with `claude --version`). Then install with whichever tool you use:
33
+
34
+ ```
35
+ pip install skillbench-cli
36
+ pipx install skillbench-cli
37
+ uv tool install skillbench-cli
38
+ ```
39
+
40
+ The command is `skillbench` either way. To try it without installing: `uvx --from skillbench-cli skillbench init`.
41
+
42
+ ## 2. Try it (2 minutes)
43
+
44
+ In your repo:
45
+
46
+ ```
47
+ skillbench init # creates a skillbench/ folder with two example tests
48
+ skillbench skill # runs the skill test
49
+ skillbench agent # runs the agent test
50
+ ```
51
+
52
+ You'll see something like:
53
+
54
+ ```
55
+ [1/1] hello-greets-by-name default model
56
+ hello-greets-by-name: pass in 2.3s
57
+ dashboard: skillbench/runs/index.html
58
+ ```
59
+
60
+ Open `skillbench/runs/index.html` in your browser to see exactly what Claude did: every message, tool call and check.
61
+
62
+ That's it. The rest of this page shows how to write your own tests.
63
+
64
+ ---
65
+
66
+ ## 3. Two kinds of test
67
+
68
+ | | **Skill test** | **Agent test** |
69
+ |---|---|---|
70
+ | Question it answers | "When my skill runs, does it do the right thing?" | "Given a normal request, does Claude pick the right skills and get the job done?" |
71
+ | Lives in | `skillbench/skills/` | `skillbench/agent/` |
72
+ | Run with | `skillbench skill` | `skillbench agent` |
73
+ | You write | `skill:` and `input:` | `prompt:` |
74
+
75
+ ### A skill test
76
+
77
+ `skillbench/skills/grilling.yaml`
78
+
79
+ ```yaml
80
+ skill: grilling # your skill's name
81
+ input: an idea for a todo app # what to send it
82
+ fixture: . # run it on a copy of this repo
83
+
84
+ assert:
85
+ - final_text_contains: "Q1"
86
+ - tool_not_called: Write
87
+ ```
88
+
89
+ skillbench finds the skill wherever it lives in your repo (`.claude/skills/`, `skills/`, `.github/skills/` or a plugin) and runs it as `/grilling an idea for a todo app`.
90
+
91
+ ### An agent test
92
+
93
+ `skillbench/agent/csv-export.yaml`
94
+
95
+ ```yaml
96
+ prompt: add CSV export to the report page
97
+ fixture: .
98
+
99
+ answers: # replies, sent one at a time when Claude asks something
100
+ - Yes to all your recommendations.
101
+ - approved
102
+
103
+ assert:
104
+ - skill_invoked: planner
105
+ - tool_order: [Read, Edit, Bash]
106
+ - command_succeeds: python -m pytest -q
107
+ ```
108
+
109
+ Nothing is forced here. Claude sees every skill in your repo and decides for itself, and the test checks what it chose.
110
+
111
+ ---
112
+
113
+ ## 4. Checks you can make
114
+
115
+ Put any of these under `assert:`.
116
+
117
+ | Check | Passes when |
118
+ |---|---|
119
+ | `skill_invoked: grilling` | Claude used that skill |
120
+ | `skill_not_invoked: grilling` | Claude didn't use that skill |
121
+ | `tool_order: [Read, Edit]` | Claude used these tools in this order (other tools in between are fine) |
122
+ | `tool_not_called: Write` | Claude never used that tool |
123
+ | `final_text_contains: "Done"` | Claude's last message contains the text |
124
+ | `file_contains: {path: notes.md, text: "approved"}` | That file exists afterwards and contains the text |
125
+ | `command_succeeds: python -m pytest -q` | The command runs successfully in the workspace afterwards |
126
+
127
+ A test passes when every check passes.
128
+
129
+ ---
130
+
131
+ ## 5. Which repo Claude works in (`fixture:`)
132
+
133
+ Claude always works on a **copy**, so your real files are never touched.
134
+
135
+ | `fixture:` | Claude gets |
136
+ |---|---|
137
+ | *(leave it out)* | An empty folder |
138
+ | `.` | A copy of your repo, including work you haven't committed |
139
+ | `some/folder` | A copy of that folder |
140
+ | `https://github.com/you/app.git` | A fresh clone |
141
+ | `{git: https://github.com/you/app.git, ref: v1.2}` | A clone at that branch, tag or commit |
142
+
143
+ Paths are relative to your repo root. The copy is kept after the run so you can look inside, and its path is in the dashboard.
144
+
145
+ ---
146
+
147
+ ## 6. Running tests
148
+
149
+ ```
150
+ skillbench skill # all skill tests
151
+ skillbench skill grilling # just the tests for one skill (or one test by name)
152
+ skillbench agent csv-export # one agent test
153
+ skillbench agent --repeat 5 # run each test 5 times
154
+ skillbench agent --model claude-sonnet-5-5
155
+ ```
156
+
157
+ While it runs you'll see the current test, what Claude is doing, and roughly how long is left.
158
+
159
+ ---
160
+
161
+ ## 7. More options
162
+
163
+ You won't need these to start.
164
+
165
+ **Check a skill gets picked on its own.** List prompts that should and shouldn't trigger it. Each runs briefly and stops as soon as Claude decides:
166
+
167
+ ```yaml
168
+ skill: grilling
169
+ triggers:
170
+ should: ["stress-test my plan"]
171
+ should_not: ["fix this typo"]
172
+ ```
173
+
174
+ **Answer Claude yourself.** Add `interactive: true` and skillbench asks *you* in the terminal whenever Claude is waiting for a reply. Press Enter on an empty line to finish.
175
+
176
+ **Check for flakiness.** Claude doesn't do exactly the same thing every time. `--repeat 5` (or `repeat: 5` in the test) runs it 5 times and shows how often each check passed. Add `min_pass_rate: 0.8` to pass when 4 out of 5 runs pass.
177
+
178
+ **Set defaults for every test** in `skillbench/skillbench.yaml`:
179
+
180
+ ```yaml
181
+ model: claude-sonnet-5-5
182
+ timeout_s: 600 # seconds before a turn is stopped
183
+ fixture: .
184
+ repeat: 1
185
+ min_pass_rate: 1.0
186
+ ```
187
+
188
+ A test's own settings win over these, and command-line flags win over both.
189
+
190
+ **All test fields:**
191
+
192
+ | Field | Meaning |
193
+ |---|---|
194
+ | `skill` / `input` | Skill tests: which skill, and what to send it |
195
+ | `prompt` | Agent tests: the first message |
196
+ | `answers` | Replies sent one per turn |
197
+ | `interactive` | Ask you in the terminal for replies |
198
+ | `triggers` | Prompts that should / shouldn't pick the skill |
199
+ | `fixture` | Which repo Claude works in |
200
+ | `assert` | The checks |
201
+ | `name` | A display name (defaults to the file name) |
202
+ | `timeout_s`, `repeat`, `min_pass_rate` | As above |
203
+
204
+ ---
205
+
206
+ ## Good to know
207
+
208
+ - **It costs real usage.** Every run is a real Claude session. Start with skill tests; long agent tests take longer and cost more.
209
+ - **Your personal setup is ignored.** Only the skills and plugins in the repo being tested are loaded, so results don't depend on whose machine runs them.
210
+ - **Only test repos you trust.** Claude has full tool access inside the copy, and `command_succeeds` runs commands there.
211
+ - **`command_succeeds` uses your system shell** (`sh` on Mac/Linux, `cmd` on Windows), so keep commands simple if you share tests across systems.
212
+ - **Results** are in `skillbench/runs/`, which is git-ignored. Each run has a `run.json` and Claude's raw output.
213
+
214
+ | Status | Meaning |
215
+ |---|---|
216
+ | `pass` | Every check passed |
217
+ | `fail` | Claude finished, but a check failed |
218
+ | `error` | Claude crashed or timed out, or the skill or fixture couldn't be found |
@@ -0,0 +1,197 @@
1
+ # skillbench
2
+
3
+ Test your Claude Code skills and agent workflows, the way you test code.
4
+
5
+ You write a small YAML file that says *"send this to Claude, then check these things"*. skillbench runs Claude Code for real on a copy of your repo, records everything it did, and tells you **pass** or **fail**.
6
+
7
+ ---
8
+
9
+ ## 1. Install
10
+
11
+ You need Python 3.11+, git, and Claude Code installed and logged in (check with `claude --version`). Then install with whichever tool you use:
12
+
13
+ ```
14
+ pip install skillbench-cli
15
+ pipx install skillbench-cli
16
+ uv tool install skillbench-cli
17
+ ```
18
+
19
+ The command is `skillbench` either way. To try it without installing: `uvx --from skillbench-cli skillbench init`.
20
+
21
+ ## 2. Try it (2 minutes)
22
+
23
+ In your repo:
24
+
25
+ ```
26
+ skillbench init # creates a skillbench/ folder with two example tests
27
+ skillbench skill # runs the skill test
28
+ skillbench agent # runs the agent test
29
+ ```
30
+
31
+ You'll see something like:
32
+
33
+ ```
34
+ [1/1] hello-greets-by-name default model
35
+ hello-greets-by-name: pass in 2.3s
36
+ dashboard: skillbench/runs/index.html
37
+ ```
38
+
39
+ Open `skillbench/runs/index.html` in your browser to see exactly what Claude did: every message, tool call and check.
40
+
41
+ That's it. The rest of this page shows how to write your own tests.
42
+
43
+ ---
44
+
45
+ ## 3. Two kinds of test
46
+
47
+ | | **Skill test** | **Agent test** |
48
+ |---|---|---|
49
+ | Question it answers | "When my skill runs, does it do the right thing?" | "Given a normal request, does Claude pick the right skills and get the job done?" |
50
+ | Lives in | `skillbench/skills/` | `skillbench/agent/` |
51
+ | Run with | `skillbench skill` | `skillbench agent` |
52
+ | You write | `skill:` and `input:` | `prompt:` |
53
+
54
+ ### A skill test
55
+
56
+ `skillbench/skills/grilling.yaml`
57
+
58
+ ```yaml
59
+ skill: grilling # your skill's name
60
+ input: an idea for a todo app # what to send it
61
+ fixture: . # run it on a copy of this repo
62
+
63
+ assert:
64
+ - final_text_contains: "Q1"
65
+ - tool_not_called: Write
66
+ ```
67
+
68
+ skillbench finds the skill wherever it lives in your repo (`.claude/skills/`, `skills/`, `.github/skills/` or a plugin) and runs it as `/grilling an idea for a todo app`.
69
+
70
+ ### An agent test
71
+
72
+ `skillbench/agent/csv-export.yaml`
73
+
74
+ ```yaml
75
+ prompt: add CSV export to the report page
76
+ fixture: .
77
+
78
+ answers: # replies, sent one at a time when Claude asks something
79
+ - Yes to all your recommendations.
80
+ - approved
81
+
82
+ assert:
83
+ - skill_invoked: planner
84
+ - tool_order: [Read, Edit, Bash]
85
+ - command_succeeds: python -m pytest -q
86
+ ```
87
+
88
+ Nothing is forced here. Claude sees every skill in your repo and decides for itself, and the test checks what it chose.
89
+
90
+ ---
91
+
92
+ ## 4. Checks you can make
93
+
94
+ Put any of these under `assert:`.
95
+
96
+ | Check | Passes when |
97
+ |---|---|
98
+ | `skill_invoked: grilling` | Claude used that skill |
99
+ | `skill_not_invoked: grilling` | Claude didn't use that skill |
100
+ | `tool_order: [Read, Edit]` | Claude used these tools in this order (other tools in between are fine) |
101
+ | `tool_not_called: Write` | Claude never used that tool |
102
+ | `final_text_contains: "Done"` | Claude's last message contains the text |
103
+ | `file_contains: {path: notes.md, text: "approved"}` | That file exists afterwards and contains the text |
104
+ | `command_succeeds: python -m pytest -q` | The command runs successfully in the workspace afterwards |
105
+
106
+ A test passes when every check passes.
107
+
108
+ ---
109
+
110
+ ## 5. Which repo Claude works in (`fixture:`)
111
+
112
+ Claude always works on a **copy**, so your real files are never touched.
113
+
114
+ | `fixture:` | Claude gets |
115
+ |---|---|
116
+ | *(leave it out)* | An empty folder |
117
+ | `.` | A copy of your repo, including work you haven't committed |
118
+ | `some/folder` | A copy of that folder |
119
+ | `https://github.com/you/app.git` | A fresh clone |
120
+ | `{git: https://github.com/you/app.git, ref: v1.2}` | A clone at that branch, tag or commit |
121
+
122
+ Paths are relative to your repo root. The copy is kept after the run so you can look inside, and its path is in the dashboard.
123
+
124
+ ---
125
+
126
+ ## 6. Running tests
127
+
128
+ ```
129
+ skillbench skill # all skill tests
130
+ skillbench skill grilling # just the tests for one skill (or one test by name)
131
+ skillbench agent csv-export # one agent test
132
+ skillbench agent --repeat 5 # run each test 5 times
133
+ skillbench agent --model claude-sonnet-5-5
134
+ ```
135
+
136
+ While it runs you'll see the current test, what Claude is doing, and roughly how long is left.
137
+
138
+ ---
139
+
140
+ ## 7. More options
141
+
142
+ You won't need these to start.
143
+
144
+ **Check a skill gets picked on its own.** List prompts that should and shouldn't trigger it. Each runs briefly and stops as soon as Claude decides:
145
+
146
+ ```yaml
147
+ skill: grilling
148
+ triggers:
149
+ should: ["stress-test my plan"]
150
+ should_not: ["fix this typo"]
151
+ ```
152
+
153
+ **Answer Claude yourself.** Add `interactive: true` and skillbench asks *you* in the terminal whenever Claude is waiting for a reply. Press Enter on an empty line to finish.
154
+
155
+ **Check for flakiness.** Claude doesn't do exactly the same thing every time. `--repeat 5` (or `repeat: 5` in the test) runs it 5 times and shows how often each check passed. Add `min_pass_rate: 0.8` to pass when 4 out of 5 runs pass.
156
+
157
+ **Set defaults for every test** in `skillbench/skillbench.yaml`:
158
+
159
+ ```yaml
160
+ model: claude-sonnet-5-5
161
+ timeout_s: 600 # seconds before a turn is stopped
162
+ fixture: .
163
+ repeat: 1
164
+ min_pass_rate: 1.0
165
+ ```
166
+
167
+ A test's own settings win over these, and command-line flags win over both.
168
+
169
+ **All test fields:**
170
+
171
+ | Field | Meaning |
172
+ |---|---|
173
+ | `skill` / `input` | Skill tests: which skill, and what to send it |
174
+ | `prompt` | Agent tests: the first message |
175
+ | `answers` | Replies sent one per turn |
176
+ | `interactive` | Ask you in the terminal for replies |
177
+ | `triggers` | Prompts that should / shouldn't pick the skill |
178
+ | `fixture` | Which repo Claude works in |
179
+ | `assert` | The checks |
180
+ | `name` | A display name (defaults to the file name) |
181
+ | `timeout_s`, `repeat`, `min_pass_rate` | As above |
182
+
183
+ ---
184
+
185
+ ## Good to know
186
+
187
+ - **It costs real usage.** Every run is a real Claude session. Start with skill tests; long agent tests take longer and cost more.
188
+ - **Your personal setup is ignored.** Only the skills and plugins in the repo being tested are loaded, so results don't depend on whose machine runs them.
189
+ - **Only test repos you trust.** Claude has full tool access inside the copy, and `command_succeeds` runs commands there.
190
+ - **`command_succeeds` uses your system shell** (`sh` on Mac/Linux, `cmd` on Windows), so keep commands simple if you share tests across systems.
191
+ - **Results** are in `skillbench/runs/`, which is git-ignored. Each run has a `run.json` and Claude's raw output.
192
+
193
+ | Status | Meaning |
194
+ |---|---|
195
+ | `pass` | Every check passed |
196
+ | `fail` | Claude finished, but a check failed |
197
+ | `error` | Claude crashed or timed out, or the skill or fixture couldn't be found |
@@ -0,0 +1,46 @@
1
+ [project]
2
+ name = "skillbench-cli"
3
+ version = "0.1.0"
4
+ description = "Test your Claude Code skills and agent workflows, the way you test code."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ authors = [{ name = "Adam Saul" }]
9
+ requires-python = ">=3.11"
10
+ keywords = ["claude", "claude-code", "agents", "skills", "evals", "testing"]
11
+ classifiers = [
12
+ "Development Status :: 3 - Alpha",
13
+ "Environment :: Console",
14
+ "Intended Audience :: Developers",
15
+ "Operating System :: OS Independent",
16
+ "Programming Language :: Python :: 3",
17
+ "Topic :: Software Development :: Testing",
18
+ ]
19
+ dependencies = [
20
+ "pyyaml>=6.0",
21
+ "rich>=13.7",
22
+ ]
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/adamsaul314/skillbench"
26
+ Issues = "https://github.com/adamsaul314/skillbench/issues"
27
+
28
+ [project.scripts]
29
+ skillbench = "skillbench.cli:main"
30
+
31
+ [dependency-groups]
32
+ dev = ["ruff>=0.6"]
33
+
34
+ [build-system]
35
+ requires = ["hatchling"]
36
+ build-backend = "hatchling.build"
37
+
38
+ [tool.hatch.build.targets.wheel]
39
+ packages = ["src/skillbench"]
40
+
41
+ [tool.ruff]
42
+ line-length = 100
43
+ target-version = "py311"
44
+
45
+ [tool.ruff.lint]
46
+ select = ["E", "F", "W", "I", "B", "UP", "SIM"]
@@ -0,0 +1 @@
1
+ """skillbench: eval framework for agent skills."""