duet-agent: Skill for Claude Code

.agents/skills/write-eval/SKILL.md

write-eval is a skill for Claude Code from dzhng/duet-agent. It costs 87 tokens per session (4,036 once invoked), scanned A, original, Apache-2.0.

A procedure for writing live evaluations of coding-agent behavior using red-green test-driven development, or TDD: first make the test fail, then make it pass, and finally break the feature to confirm the test detects the failure. It also covers repeated testing for behavior that can vary between runs.

In plain words
What is it for?
Use it when adding or changing agent behavior that needs an evaluation, including checking deterministic context wiring or testing tendencies such as staying within a task’s scope.
Why use it?
It prevents evaluations from passing accidentally or merely checking that code exists. The falsification step shows that the evaluation really tests the intended behavior.

Skill for Claude Code

Written for Claude Code: allowed-tools in frontmatter. Also seen: mentions subagents; installed under .agents/ (shared by several agents); mentions AGENTS.md.

This is dzhng/duet-agent's own configuration. It tells Claude Code how to work on duet-agent itself, so it is not a mod to install elsewhere. Copy it as a starting point and replace the rules that are about this project. Everything duet-agent configures →

Needs its repository: it runs a file that does not travel with it, so clone the repository first. The line is 'cp -R /src/. /work && bun install --frozen-lockfile >/dev/null 2>&1 && bun test ./evals/<name>.eval.ts'.

Reuse

Borrowing it

Nothing to install: this file belongs to dzhng/duet-agent. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.

Copy the file
curl -O https://raw.githubusercontent.com/dzhng/duet-agent/main/.agents/skills/write-eval/SKILL.md
Clone the repo
git clone --depth 1 https://github.com/dzhng/duet-agent

Made for: Claude Code.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for write-eval

README.md
[![agentmods](https://agentmods.dev/badge/skills/dzhng/duet-agent/write-eval/github.svg)](https://agentmods.dev/skills/dzhng/duet-agent/write-eval)
Your own site
<a href="https://agentmods.dev/skills/dzhng/duet-agent/write-eval"><img src="https://agentmods.dev/badge/skills/dzhng/duet-agent/write-eval/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for write-eval

Your own site · 80×15
<a href="https://agentmods.dev/skills/dzhng/duet-agent/write-eval"><img src="https://agentmods.dev/badge/skills/dzhng/duet-agent/write-eval.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 87 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 4,036 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe. Third-party audits
  • NVIDIA SkillSpector warn 7 Sept 2026
SkillSpector: 7 findings, up to high

These are SkillSpector’s own severities. On a checked sample its high-severity flags on skills were ~96% false positives — a documented command, a public API, a “never do X” rule — so we show them as a caution to read, not a verdict. Why →

  • high Tool Misuse · line 83
    Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.
    Fix: Limit tool chaining depth and validate the output of each tool before passing it to the next. Require explicit user approval for multi-step chains.
  • medium MCP Rug Pull · line 52
    Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.
    Fix: Pin the image: image:tag or image@sha256:abc123
  • medium MCP Rug Pull · line 71
    Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.
    Fix: Pin the image: image:tag or image@sha256:abc123
  • medium MCP Rug Pull · line 84
    Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.
    Fix: Pin the image: image:tag or image@sha256:abc123
  • low Tool Misuse · line 52
    Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
    Fix: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.
  • low Tool Misuse · line 52
    Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
    Fix: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.
  • low Tool Misuse · line 83
    Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
    Fix: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.
How audits are shown
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00087 $0.04036
Opus 5.5 $0.00035 $0.01614
Sonnet 5.5 $0.00017 $0.00807
Haiku 4.5 $0.00009 $0.00404

Measured 26d ago against content hash 1f0fd512633a, method: parsed. Prices are Anthropic first-party input rates as of 2026-10-07, from the pricing page.

Security

Grade A, and why

write-eval scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 26d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

.agents/skills/write-eval/SKILL.md · 127 lines

How it starts

The opening of the file, as written. The whole thing — 127 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Write an Eval

An eval is only trustworthy if you have seen it both fail for the right reason and pass for the right reason. Writing the assertions, watching them go green once, and moving on is how you ship an eval that passes whether or not the feature works. The standard operating procedure is: pick the outermost entry point, design the assertion so it can only hold when the behavior is present, watch it go green, then falsify — break the production code, confirm the eval goes red with a diagnostic that points at the real path, and restore.

This is the flow used to land evals/state-machine-slash-skill-expansion.eval.ts; read it as the reference implementation for a deterministic wiring eval (the feature either injects the right context or it doesn't).

When the behavior under test is a model tendency rather than deterministic wiring — "the planner doesn't over-reach into implementation", "the sub-agent doesn't drift into chat mode", anything a prompt layer nudges but cannot guarantee — the single-run flow is not enough, because one run is a coin flip. Read evals/state-machine-agent-stays-in-state-scope.eval.ts as the reference for that shape, and follow §6 below in addition to §1–5.

1. Drive the outermost entry point

Per AGENTS.md and the review skill (§13): test behavior through the surface a user actually hits, not internal helpers.

  • A unit test on the pure function (e.g. test/skill-context-resolve.test.ts for resolveSlashSkillPrompt) proves the helper is correct. The eval proves the live wiring invokes it. Write the eval at the layer the unit test cannot reach — the real TurnRunner + startTurn flow, the CLI binary in JSONL mode, or a real complete() call.
  • For state-machine behavior, drive a real TurnRunner with a mode definition and startTurn from test/helpers/turn-runner-protocol.js. evals/state-machine-agent-cwd.eval.ts and evals/state-machine-slash-skill-expansion.eval.ts are the templates.
  • For CLI behavior, spawn bun src/cli.ts in JSONL mode and inspect the emitted events the same way a production subscriber would. evals/inline-slash-commands.eval.ts is the template.
  • Collect tool calls and assistant text off runner.subscribe step events: step.type === "tool_call_start" for calls as they begin (the canonical tool_call step carries the echoed input plus isError/output), step.type === "text" for text. Sub-agent (state) events carry event.origin.kind === "state_machine_agent"; parent events have no origin. Filter on origin to attribute a tool call to the right agent.

Read the full file on GitHub · 127 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 26d ago Changed · +8 lines 1f0fd512633a
  2. 29d ago Changed cc5f2221b0c1
  3. 1mo ago First seen · 119 lines · 87 tokens per session scan A 1fc4e71a144c

Subscribe to this mod's changes

write-eval is a skill published in the GitHub repository dzhng/duet-agent (52 stars, last pushed 7d ago), licensed Apache-2.0. It adds 87 tokens to every session and 4,036 once invoked, about $0.0003 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.