| description | Install the Coder Eval plugin for Claude Code — six slash commands to scaffold, author, review, run and analyze evaluation suites, including an activation suite that measures whether your own Claude Code skills actually trigger. |
|---|
Coder Eval ships as a Claude Code plugin, so the whole loop — scaffold a suite, author a task, check whether a skill triggers, read the results, wire it into CI — happens inside the agent instead of in a separate terminal.
The UiPath/coder_eval repository is itself the plugin marketplace:
/plugin marketplace add UiPath/coder_eval
/plugin install coder-eval@coder-eval
The first command registers the repository as a marketplace; the second installs
the one plugin it hosts. Marketplace and plugin share the name coder-eval,
which is why the install target reads coder-eval@coder-eval.
Installing the plugin does not install the CLI. A plugin ships skills and
references, not packages, so the coder-eval binary is a separate step:
uv tool install coder-eval # or: pip install coder-evalYou do not have to do it in advance. init, task and check-skill — the three
skills that shell out to the CLI — check coder-eval --version before doing any
work and, if it is missing, offer to install it and ask first. They never
install unprompted: that writes outside your repository, so it is your call, and
they verify the install worked before continuing. analyze and ci do not invoke
the CLI, and lint-tasks needs neither the CLI nor credentials — it only reads
files, though the report it produces ends by suggesting you run coder-eval plan
yourself.
Running a suite additionally needs credentials for whichever agent the tasks use —
ANTHROPIC_API_KEY for the default claude-code agent.
| Command | What it does |
|---|---|
/coder-eval:init |
Scans the repository for what is worth evaluating (Claude Code skills, an MCP server, a CLI), reports the findings, then scaffolds a task directory with one real task. |
/coder-eval:check-skill |
Builds and runs an activation suite for one of your skills — does the agent engage it when it should, and leave it alone when it shouldn't? |
/coder-eval:task |
Turns a natural-language description into task YAML with criteria that check output content, validated through coder-eval plan. |
/coder-eval:lint-tasks |
Reviews task YAML that already exists and reports, per task, criteria that cannot fail, prompts that leak the answer, fixtures with no cleanup and near-duplicates — each with a severity and a fix. Read-only. |
/coder-eval:analyze |
Reads a finished run directory and writes analysis.md: systemic failure patterns, per-task findings, and concrete fixes. |
/coder-eval:ci |
Emits a GitHub Actions workflow that runs the suite as a gate, or on a schedule to catch skill drift. |
init and ci are explicit-invocation only — scaffolding a directory or writing
a workflow is never something to do unprompted. The other four can also be
reached by the agent on its own when a request clearly calls for them.
task and lint-tasks are two halves of the same concern and share one bundled
rubric: task applies it to work it is writing, lint-tasks applies it to files
you already have. They are separate skills because authoring needs Write and a
review pass should not have it, and frontmatter declares tool policy per skill —
so one skill cannot hold both stances.
lint-tasks expresses read-only three ways, and it is worth being precise about
what each buys, because only the last one spans a whole review: its
allowed-tools lists just Read, Glob and Grep; its disallowed-tools names
every write tool, which removes them from the pool for the invoking turn only —
the restriction clears when you send your next message, and the skill asks you one
before linting a whole directory; and its own instructions carry a standing
prohibition on modifying a file, which is what actually holds for the rest of the
review.
A skill is selected almost entirely from its frontmatter description. Whether
that description wins the requests it should — and loses the ones it shouldn't —
is invisible until a user complains. check-skill turns it into a number.
Point it at a skill:
/coder-eval:check-skill .claude/skills/pdf-forms
It then:
- reads the skill's frontmatter
description— the string the model actually matches on; - designs positive rows (requests the description claims to cover, paraphrased — never lifted from the description, which would test string overlap rather than activation) and distractor rows (adjacent requests the skill should decline, especially ones sharing its vocabulary);
- copies the bundled activation template into your task directory as a
dataset-backed task — one row per request, each scored by the
skill_triggeredcriterion; - validates with
coder-eval plan, tells you the row count and the cost implication, and asks before running; - reports recall, precision, F1 and the confusion matrix — then interprets them: low precision means the description over-claims and is stealing adjacent requests; low recall means it under-claims once truncation and listing eviction are ruled out (see below).
One prerequisite the suite cannot infer: the evaluated agent runs in a fresh sandbox holding none of your files, so it is offered no skills unless the task says where they live. The template reads that location from an environment variable — point it at the directory containing the skill's own directory:
export SKILL_SOURCE_PATH="$(pwd)/.claude/skills"Leave it unset and the skill is simply absent, every positive row scores 0, and the result is indistinguishable from a skill that never fires. It stays an environment variable rather than a path baked into the YAML so the suite is portable — it is committed and re-run on other machines, and in CI.
Two of them are budgets rather than wording, and both produce a number that looks exactly like a badly written description:
- Per-skill truncation.
descriptionandwhen_to_useare concatenated and cut at 1,536 characters (configurable viaskillListingMaxDescChars). Trigger text past the cutoff cannot affect activation at all. - Whole-listing eviction. The skill listing's character budget scales at about 1% of the model's context window and is shared with every skill you have installed. On overflow, descriptions are dropped starting with the skills you invoke least — so a newly authored skill, which is by definition rarely invoked, is the likeliest casualty. That is a systematic bias against exactly the skill you are testing.
Check both before rewriting anything: /doctor estimates the listing's context
cost and its biggest contributors, and the Skills row in /context reports the
listing size after the budget is applied — what the model actually received.
Only once the description is demonstrably in the listing is the wording the
culprit.
The suite is a normal task file, so it stays in your repository and can be re-run after every description edit — which is the point. Editing skill wording without a suite is guesswork; with one, the change either moves recall or it doesn't.
Because the suite is gated on suite_thresholds (recall.yes, precision.yes),
it also works as a CI gate: run it on a schedule and a skill that quietly stops
triggering — because the model changed, or someone reworded the description —
fails a build instead of surprising a user.
The skills are written for a repository that already has a suite, not only for an empty one. Three things follow from that, and they are worth knowing before you install:
- They discover; they do not assume. Nothing looks for
tasks/orruns/latestby name. A skill globs for YAML carrying atask_id:key and forrun.json, reports the tree it resolved, and asks when a monorepo offers more than one. Call your eval treeevals/, or nest the whole thing undertests/, and the skills follow it. - They will not scaffold over what you have.
initrun against a configured repository reports the inventory and stops, pointing atlint-tasksandanalyzeinstead.check-skilllooks for a suite that already covers the skill and offers to extend it rather than writing a second one. And where your repository pins a coder-eval version, the CLI-driving skills resolve that pin first and stop on a mismatch rather than validating with the wrong binary — a schema error from a mismatched CLI is indistinguishable from a real one. - Your own tooling stays authoritative. If you already have slash commands or a CI
workflow covering the same ground, these skills are additive. The naming keeps them
apart: plugin skills are always namespaced
/coder-eval:<name>, while a repo-local command in your own.claude/commands/keeps whatever name you gave it. Where both exist, prefer yours — it knows things the plugin cannot.
task applies the same rule to authoring: it reads whatever your repository declares
about writing tasks and follows it, and reports which conventions it adopted. The bundled
rubric is a check of last resort, for what no local rule covers.
An installed plugin is copied to ~/.claude/plugins/cache/ without its parent
directories, so every file a skill reads travels with it under reference/:
criteria.md— every criterion type and its fields, generated from Coder Eval's ownSuccessCriterionmodel union (make plugin-reference), so it cannot drift from the schema the CLI validates against.task-rubric.md— the adversarial task-quality checklisttaskapplies to work it writes andlint-tasksapplies to task files already on disk: could this task pass for the wrong reason, does it grade behavior or a self-report, do its fixtures reset and clean up.cli-setup.md— how the CLI-driving skills handle a missingcoder-evalbinary: offer the install, ask first, verify it worked.run-layout.md— the on-disk run-directory contractanalyzereads: what is inside a run directory.repo-layout.md— how a skill finds where your eval tree is, by globbing fortask_id:files andrun.jsonrather than assumingtasks/andruns/. All six skills read it, which is what lets them work in a repository that names or nests the tree differently.templates/— the canonical activation suitecheck-skillcopies.
- The plugin's own README lives at
plugins/coder-eval/README.md. - For the GitHub Action the
ciskill emits — its inputs, JUnit output and score floor — see CI Gate & GitHub Action. - For the criterion vocabulary in full, see the Task Definition Guide.