Engineering Software Lab LTD · Claude Partner Network
Claude Partner Network member
Agent Skills · Claude Code · Evals

Wazatator
the spectator for your skills

Wazatator watches Claude Code use your SKILL.md: every prompt, tool call, and file. Then it scores the run, so you know whether a skill edit helped instead of guessing.

Presented by ESL (Engineering Software Lab), a member of Anthropic's Claude Partner Network.

Open source · MIT Windows · macOS · Linux Claude Code plugin v0.3.0
The problem

You edit a SKILL.md with no proof the edit helped

Silent

Does the skill even fire?

Claude might answer from general knowledge and never invoke your skill. Nothing tells you.

Fragile

Vague prompts break it

"Explain this code" with no snippet: does the skill look for the file, or ask the user to paste it?

Unmeasured

Was v2 better than v1?

Without repeatable tasks and graders, every change is a vibe check.

What it is

A test runner for Agent Skills, driven by real Claude Code sessions

Like a spectator at a match

SpectatorWazatator
Watches the gameWatches the full Claude run: transcript, tools, files
Sees every moveRecords each tool call (Skill, Read, Write, MCP)
Judges the playGraders and LLM judges give pass/fail and a score
Never playsDoesn't change your skill; it measures it

What's inside

CLI: wazatator, a fork of Microsoft Waza (MIT) with a new Claude Code executor.

Plugin: /wazatator:new-eval, /wazatator:eval, /wazatator:quality inside Claude Code.

Graders: text, regex, files, tool calls, skill invocation, token budget, trigger precision, and LLM-as-judge.

Output: results.json, a terminal report, model comparison, and a CI exit code.

The ESL AI-SDLC

Agent skills are software. They need a lifecycle too.

AI agents now plan, write, review and test code. The skills that steer them deserve the same discipline: a spec, tests, review, and a release gate. Wazatator covers the Test and Review stages for agent skills.

Plan
Specs and tasksAI-assisted planning and tracking. monday.com
Code
AI coding agentsClaude Code, Amp, Sourcegraph code search
Build
Versioning and CIPerforce, CloudBees
Test
Code and skill testingParasoft static and unit testing, plus evals of agent skillsWazatator
Review
Quality and policy gatesParasoft compliance, LLM judges, tool-policy checksWazatator
Release
Supply chainSonatype, ESL SBOMator, CI exit codes
Operate
Monitor and supportInstana, Atera

Findings loop back: Review → fix the SKILL.md in Code → re-run in Test → compare.

How it works

From eval.yaml to a score in five steps

1WorkspaceFresh temp folder per task with your fixture files
›
2Install skillCopies SKILL.md to .claude/skills/ so Claude discovers it natively
›
3Run Claudeclaude -p --output-format stream-json with personal plugins and MCP turned off
›
4RecordMessages, tool calls, skill invocations, files, tokens, cost
›
5GradeRules plus an LLM judge that resumes the same session
internal/execution/claude.go (the core of the Claude Code executor)
args := []string{"-p", "--output-format", "stream-json", "--verbose",
    "--permission-mode", "bypassPermissions",
    // results depend on the skill under test, not on this machine's setup
    "--setting-sources", "project,local", "--strict-mcp-config"}
if req.SessionID != "" { args = append(args, "--resume", req.SessionID) } // follow-ups and judges
if len(req.Tools) > 0 { bridge, _ := startClaudeToolBridge(req.Tools) } // judge tools over local MCP
Code sample 1

An eval suite is one small YAML file

evals/code-explainer/eval.yaml
name: code-explainer-eval
skill: code-explainer
config:
  executor: claude-cli        # run through Claude Code
  model: sonnet
  trials_per_task: 3        # repeat to catch flakiness
  timeout_seconds: 300
  inject_skill_body: false  # Claude must find the skill itself
graders:                  # apply to every task
  - type: text
    name: no_errors
    config:
      regex_not_match: ["(?i)fatal error|crashed"]
tasks:
  - "tasks/*.yaml"

Why these settings matter

executor: claude-cli: real Claude Code sessions, the same way your users run the skill.

trials_per_task: models vary from run to run. Three trials show whether a pass is reliable.

inject_skill_body: false: tests real discovery. If the skill's description is weak, Claude won't pick it, and the eval shows that.

Exit codes: 0 = pass, 1 = test failure, 2 = config error, ready for CI.

Code sample 2

A task: a prompt, input files, and graders

tasks/explain-recursion.yaml
id: explain-python-recursion-001
inputs:
  prompt: "Explain this code to me"   # deliberately vague
  files:
    - path: factorial.py
expected:
  output_contains: ["recursive", "factorial"]
graders:
  - name: used-skill
    type: skill_invocation
    config:
      required_skills: [code-explainer]
      mode: any_order
  - name: judge
    type: prompt                    # LLM-as-judge
    config:
      model: haiku
      continue_session: true      # judge reads the real conversation
      prompt: |-
        If the answer explains the recursion and base case,
        call set_waza_grade_pass, otherwise set_waza_grade_fail.

Three layers of checking

Rules
output_contains, regex, JSON schema, file contents and diffs: fast, free and deterministic.

Behavior
skill_invocation, tool-call sequences, token and turn budgets: did Claude do the right things?

Judgment
prompt graders: a second Claude session reviews quality that keywords can't capture, and gives its reason.

Code sample 3

Trigger tests: does the skill fire only when it should?

trigger_tests.yaml
skill: pirate-greeter
should_trigger_prompts:
  - prompt: "Hello!"
  - prompt: "Say hello to my team"
  - prompt: "Good morning, how about a greeting?"
should_not_trigger_prompts:   # near-misses
  - prompt: "Translate this paragraph into Spanish"
  - prompt: "Tell me a pirate joke about coffee"
  - prompt: "Proofread this email for typos"

Real output

TRIGGER ACCURACY
  Accuracy:  100.0%
  Precision: 100.0%  Recall: 100.0%  F1: 100.0%
  TP: 4  FP: 0  FN: 0  TN: 5

Precision catches a skill that grabs requests it shouldn't (the pirate joke). Recall catches a skill Claude never picks. Each trigger run stops as soon as the skill fires, which saves tokens.

What it can find

Real findings from real runs

Skill weakness

Asks instead of acting

"Explain this code to me" got "I don't see any code in your message yet", even though factorial.py was right there.

Skill weakness

Ignores the input file

Judge: "fails to greet Priya… asks for clarification about who the person is." The name was in newcomer.txt.

Discovery

Skill never invoked

Trigger recall 0%: with the skill pasted into the prompt, Claude answered without ever calling its Skill tool.

Safety

Tool-policy violations

A read-only agent (tools: ["read"]) was asked to write a file. Only Read was available; any other call fails the run.

Integration

MCP tool usage

Mocked GitHub MCP server: Claude called mcp__github__list_issues and reported issue #363. Wrong arguments fail loudly.

Cost

Tokens and dollars

5 tasks + judges + 9 trigger prompts: 72 s, 2,685 output tokens, about $0.31 on Sonnet.

Finding → fix → proof

"I don't see any code": fixed in the skill, proven by a re-run

code-explainer/SKILL.md (the fix)
+ ## Finding the Code
+ If the user refers to "this code" but no snippet is in
+ the message, do not ask for the code right away:
+ 1. Use code from the conversation or attached files.
+ 2. Otherwise list the working directory. If there is
+    exactly one source file, read and explain it, and
+    say which file you explained.
+ 3. Ask only when there is no candidate or several
+    equally likely ones.
TaskBeforeAfter (3 trials)
"Explain this code to me"✗ asked for code✓ 3/3
"Explain the code in factorial.py"✓✓ 3/3
tools: Skill → Glob → Glob → Read
output: "I explained `factorial.py`, since it's the only
        source file in the working directory. ..."

The fix went into the skill, not the test, so real users benefit too.

Real collision test

One of our own skills vs. our real 49-skill library

Target: parasoft-static-analysis-misra-c-2023. Same eval, run alone and then with every other skill on this machine loaded via --skill-library, including its near-twin parasoft-static-analysis.

MetricSkill aloneWith 48 other skills
Trigger recall50%25%
Trigger precision100%100%
MISRA prompts missed2 of 43 of 4
MISRA review task (scale.c)✓ passed✓ passed

Claude Code, Sonnet, one run per prompt, 3 Oct 2026. Treat single runs as signals, not verdicts.

What it found

Lost when crowded
"Check this C function against MISRA C:2023…" used the skill alone, but not once the library was installed.

Never attracted
Rule questions ("signed/unsigned conversions", "switch without default") were answered from Claude's memory in both runs. The description doesn't claim rule-knowledge questions.

Correct routing
AUTOSAR C++14 went to the sibling parasoft-static-analysis; libFuzzer went to libfuzzer. No false triggers.

Action: sharpen the description to claim MISRA C:2023 rule questions and to say how it differs from parasoft-static-analysis, then re-run both modes. Result on the next slide.

Finding → fix → proof

One description change: recall 25% → 100%, even in a crowd

parasoft-static-analysis-misra-c-2023/SKILL.md (frontmatter only)
- description: "Analyzes C/C++ code using Parasoft C/C++test
-   static analysis rules combined with MISRA C:2023 standard.
-   Covers MISRA-C:2023, CERT-C, AUTOSAR, CWE, ... Use when
-   reviewing code for MISRA C:2023 compliance ..."
+ description: "MISRA C:2023 expert with the matching Parasoft
+   C/C++test checkers. Use for ANY request that names MISRA
+   C:2023: what a rule requires, whether a construct violates
+   it (goto, switch without default, signed/unsigned or
+   narrowing conversions), rule numbers such as Rule 10.4 ...
+   Prefer this over parasoft-static-analysis whenever MISRA
+   C:2023 is named; use parasoft-static-analysis for AUTOSAR,
+   CERT, or older MISRA editions."

Same 9 trigger prompts and review task, Claude Code, Sonnet, one run per prompt, 3 Oct 2026.

Trigger recallBeforeAfter
Skill alone50%100%
With 48 other skills25%100%
Precision (both modes)100%100%
MISRA review task✓✓

Why it worked

The old description listed standards; the new one claims the questions users actually ask and draws the line against its near-twin. AUTOSAR still routes to parasoft-static-analysis and libFuzzer to libfuzzer: the fix didn't steal anyone else's prompts.

Research backing: Google's WikiSkill (arXiv 2608.27454)

Google Research measured what skills do. Triggering was out of scope.

From the paper's Limitations section

"Our study follows prior work by directly injecting active skills into the agent prompt. This setup does not evaluate skill retrieval or triggering, which becomes important as the number of available skills grows."

Tang et al., Google Research and Virginia Tech, Aug 2026.

In Claude Code a skill has to win the routing decision against every other installed skill before it can help. That's exactly what --skill-library measures: our MISRA skill fell to 25% recall in a 49-skill library, then reached 100% after one description change.

WikiSkill methodNow in Wazatator v0.3.0
Paired bootstrap, 1,000 resamples, p < 0.05Significance in --baseline and compare
Cross-model transfer table, negative transferSkill transfer matrix per --model
Gating and rollback on validation scoregate + keep-or-revert loop in the plugin
skill-impact.md history tracker--impact-log skill-impact.md
Train / validation / test splitsHeld-out tasks: --tags '!holdout'
5 failing + 3 passing traces, 15k chars eachFailure diagnosis in /wazatator:eval
"When to Apply / When NOT to Apply"; 45 to 143-line skillscheck: boundary sections, skill-too-long, low-level-steps
v0.3.0 live run: the evidence loop

Gate it, log it, check the holdout, trust only significant gains

# 1. tune on visible tasks, log every attempt
wazatator run eval.yaml --model haiku --tags '!holdout' \
    -o new.json --impact-log skill-impact.md
# 2. keep the SKILL.md edit only if this exits 0
wazatator gate --baseline old.json --current new.json
  pass rate: 33.3% -> 100.0%   outcome: PASS (exit 0)
wazatator compare old.json new.json
  Significance: +50.0 pp, 95% CI [+0, +100], p = 0.15
  -> not significant: add tasks or trials
# 3. final run: holdout included, three Claude models
wazatator run eval.yaml --baseline --model haiku --model sonnet --model opus

pirate-greeter demo skill, Claude Code. Steps 1-2: 2 trials per task, 4 Oct 2026. Step 3: one run, 4 tasks, 3 trials per task, 5 Oct 2026; cost is what Claude Code reported for the 12 with-skill task runs.

ModelWithWithoutΔ pp (95% CI)pCost
haiku66.7%25.0%+41.7 [+0, +83]0.12$0.26
sonnet75.0%25.0%+50.0 [+0, +100]0.12$0.39
opus100%25.0%+75.0 [+25, +100]0.01 *$0.74

What the loop caught

Gate passed
A description fix took Haiku from 33% to 100% on the tuning tasks. Logged and kept.

Holdout failed
"Say hi to this person" failed on Haiku and Sonnet: the skill fired, but they never read newcomer.txt to find the name. Only Opus did. Tuning alone would have shipped that gap.

Which model?
Only Opus is significant (p = 0.01), at 2.8× Haiku's cost. Fix the skill to read the file and re-run before paying for Opus; Wazatator shows the trade-off instead of guessing.

Demo

A real run, replayed

pirate-greeter: wazatator run

Replay of an actual run on 2 Oct 2026 (Sonnet runs the tasks, Haiku judges). Output is abridged; timings are compressed.

Inside Claude Code

The plugin: ask Claude to test your skill

Three slash commands

/wazatator:new-eval pirate-greeter
  # writes eval.yaml, 5 tasks, fixtures, trigger tests

/wazatator:eval evals/pirate-greeter/eval.yaml
  # runs it, explains failures, proposes SKILL.md fixes,
  # keeps a fix only if the gate passes, logs it, checks holdout

/wazatator:quality skills/code-explainer
  # static check + LLM review of the SKILL.md itself

Tested live: Claude Code ran the plugin, which ran Wazatator, which ran its own Claude Code sessions.

/wazatator:quality on code-explainer: 3.8 / 5

clarity
4
completeness
4
trigger precision
4
scope coverage
3
anti-patterns
4

"Primary weaknesses are fuzzy scope boundaries around code complexity/type and ambiguous guidance about when to invoke versus use file tools directly."

Why Wazatator

Anthropic tests plugins. Wazatator tests skills.

Capabilityclaude plugin evalWazatator
What it testsA plugin; the suite lives in the plugin's evals/Any SKILL.md, wherever it lives; no packaging
Cheapest Claude model that does the jobOne model per run; compare by hand✓ Haiku, Sonnet, Opus with and without the skill in one run: does it make Haiku good enough?
Score with vs. without the skill✓✓ --baseline
Collisions with your other skills–✓ --skill-library, prompts stolen per skill
Trigger precision / recall / F1Per-case "skill fired" check✓ should / should-not suites, confusion matrix
Custom-code graders– "no custom-code graders"✓ code, program, JSON schema, file diff
Lint the SKILL.md itself–✓ check (token budget, compliance), quality (LLM rubric)
Prompt-injection / adversarial packs–✓ adversarial
Skill transfer / negative transfer–✓ per-model with/without matrix, flags models the skill hurts
Statistical significanceMean Δ only✓ paired bootstrap: 95% CI and p-value
Regression gate vs. last versionAbsolute score threshold✓ gate vs. previous results, --impact-log, held-out tasks
Built in, zero install✓– CLI + Claude Code plugin

claude plugin eval tells you whether your plugin helps Claude. Wazatator tells you whether your skill is well written, triggers precisely, survives your other skills and attacks, and which Claude model it needs. Use both.

Q&A: does it overlap with prompt-audit?

prompt-audit reads your instructions. Wazatator runs them.

Lance Martin's /claude-api prompt-audit (also /checkup prompt-audit) scans CLAUDE.md, AGENTS.md, skills and prompts for six anti-patterns newer models no longer need: verification rituals, emphasis boosters, mandatory scaffolds, stale few-shot examples, contradictory rules, and dated configuration.

prompt-auditWazatator
MethodStatic review of the instruction textRuns real Claude Code sessions and grades them
ScopeCLAUDE.md, AGENTS.md, skills, agents, promptsSkills and .agent.md agents
FindsWording that may hurt performanceBehavior that does: missed triggers, collisions, wrong answers, policy violations, cost
Proves a change helped– advice✓ before/after, --baseline, compare
OverlapStatic review only: wazatator quality also scores an anti_patterns dimension

Complementary, not competing

prompt-audit says "delete this rule". It can't tell you whether deleting it breaks the skill; Wazatator measures exactly that. The MISRA skill's text looked fine, yet only running it showed 25% recall in a crowded library.

Audit it, then prove it

1. Run prompt-audit and apply its suggestions.
2. Re-run wazatator run --baseline and --skill-library.
3. Keep the change only if the scores hold or improve.

Q&A: isn't this the same as Skillify?

Skillify writes a skill from your session. Wazatator proves it works.

claude-skillify (0xMH, MIT) ports Anthropic's internal /skillify: at the end of a session it analyzes the conversation, interviews you, and generates a SKILL.md with steps and success criteria. It doesn't run or test the skill it writes.

SkillifyWazatator
JobAuthor: turn a workflow you just did into a skillTest: measure how a skill behaves, then improve it
InputThe current conversation + your answersAny SKILL.md + an eval suite of realistic tasks
OutputA new SKILL.mdScores, failures with reasons, gated fixes, skill-impact.md
Does the skill fire? Collisions?–✓ trigger precision / recall, --skill-library
Better than no skill? On every model?–✓ --baseline, significance, transfer matrix
OverlapSmall: wazatator new skill scaffolds an empty template; it doesn't mine your session

Complementary, not competing

A skill generated from one session encodes what worked once, for one model, often as detailed steps. That's where WikiSkill saw negative transfer, and where trigger collisions hide. Skillify gives you the draft; Wazatator tells you whether to trust it.

Skillify it, then prove it

1. /skillify at the end of the session.
2. /wazatator:new-eval: its per-step success criteria make good graders.
3. /wazatator:eval with --baseline and --skill-library.
4. Keep the skill, and every later edit, only if the scores hold.

Q&A: is this the same as tw93's Waza?

Waza gives Claude engineering habits. Wazatator measures whether a skill works.

tw93/Waza (MIT, 7k+ stars) is a pack of eight skills: /think, /ui, /check, /hunt, /write, /learn, /read, /health. Same root word, different projects: Wazatator is a fork of Microsoft Waza, an eval framework, and has no relation to tw93's skill pack.

tw93/WazaWazatator
What it isA skill pack: things Claude doesA test harness: measures what a skill does
OutputPlans, reviews, root-cause debugging, polished prosePass rates, trigger precision / recall, collisions, with vs. without skill, significance
Evidence its skills help"Refined through 300+ sessions"; repo testsThat evidence is the product: --baseline, transfer matrix, gate
OverlapSmall: /health audits an agent's setup statically; wazatator check / quality review one SKILL.md statically

Shared philosophy

Waza's rule, "state the outcome, the red lines, and how it's verified, then step back", matches WikiSkill's finding: general procedures transfer across models, while low-level workarounds can hurt them. Wazatator's low-level-steps check warns about exactly that.

Test any skill pack, including Waza

--baseline: does /hunt beat plain Claude?
--skill-library: do /check and /health, or /read and /learn, compete for the same prompts?
--model × 3: which Claude model each skill needs.

Cybersecurity relevance

Skill behavior is measurable. Security behavior is behavior too.

Security benefitHow an eval expresses it
Prompt injection resistanceAdversarial task: malicious instructions inside an input fixture. Graders fail the run if the agent disregards the skill's rules.
Tool usage restrictionsName the prohibited commands and tools in the graders; pass/fail is computed from the recorded tool calls.
Sensitive data protectionOutput and file validation: fail the run if generated outputs contain credentials or other restricted information.
Security regression detection--baseline over security tasks: repeat them after any skill, model, or agent configuration change, and gate in CI.
Investigation evidenceTranscripts, tool calls, and generated files from every run, to understand an unsafe action instead of guessing.

These are uses of the documented capabilities (adversarial testing, execution recording, behavior and output graders, CI integration) that you configure per skill; they are not security checks that run out of the box. Source: security assessment of github.com/zuwasi/wazatator, 13 Oct 2026.

Cybersecurity relevance: conditions and limits

Evidence for the scenarios you test. Not a security product.

You design the test

A security eval needs three things from you: the security requirement, the adversarial or representative input, and an observable pass/fail rule. Example: hide instructions to disclose a synthetic secret inside an untrusted document, then grade the output and tool calls for prohibited behavior.

What it is not

Not a runtime enforcement system, not a vulnerability scanner, and not a substitute for sandboxing and access controls. Recording an unsafe action or failing an evaluation does not necessarily prevent it.

How to run the evaluations

With appropriate isolation, restricted permissions, and synthetic sensitive data. Passing a suite is evidence for the scenarios tested: it does not prove resistance to every attack or guarantee the same behavior in a different execution environment.

Recommended positioning: "An AI agent skill evaluation framework supporting security testing and behavioral assurance."

Get started

Install in two commands

1. CLI (Windows PowerShell)
irm https://raw.githubusercontent.com/zuwasi/wazatator/main/install.ps1 | iex
1. CLI (macOS / Linux)
curl -fsSL https://raw.githubusercontent.com/zuwasi/wazatator/main/install.sh | bash
2. Plugin (inside Claude Code)
/plugin marketplace add zuwasi/wazatator-plugin
/plugin install wazatator@wazatator

Requirements

Claude Code installed and logged in. Every task and judge is a real session on your account, so keep trials_per_task: 1 while iterating.

Also works with

MCP servers and hermetic MCP mocks, .agent.md tool policies, follow-up turns, reasoning effort, CI gating, and side-by-side model comparison with wazatator compare.

Open source

Wazatator

CLI and releases: github.com/zuwasi/wazatator
Claude Code plugin: github.com/zuwasi/wazatator-plugin

6
platform binaries (Windows, macOS, Linux; x64 + ARM)
3
plugin skills: new-eval, eval, quality
12
grader types, from regex to LLM judge

Based on Microsoft Waza (MIT License). Wazatator adds the Claude Code executor and plugin. It is not affiliated with or endorsed by Microsoft.

ESL · Engineering Software Lab · Claude Partner Network

Great Software Tools, Excellent Service

Who we are

Since 2005, ESL has helped Israeli software teams adopt and get the most out of leading development tools: code analysis, testing, version control, compliance, and AI coding agents. As a member of Anthropic's Claude Partner Network, we help teams adopt Claude and Claude Code, and build open tools like Wazatator to make AI agents measurable.

Talk to us

ESL · eswlab.com · Claude Partner Network
← Swipe to navigate →