When I ask an agent to explain a function, I want a correct explanation. For that request, I would avoid having it load the instructions, rubric and report format for a code review as well. When assessing a skill, I therefore look at both the result and the path the agent took.
This guide’s lab compares two descriptions of the same skill, a package of reusable instructions for the agent. The broad description also included code explanations. With that description, Codex opened the three review files before explaining discountedTotal; no reads of those files were observed in the session with the focused description. Both review requests found the introduced defect. I would use that difference when deciding what to keep in the skill catalog.
What we are installing
A skill packages reusable instructions for a task. Its main file, SKILL.md, starts with YAML metadata containing a name and description, followed by the procedure. Supporting files can supply criteria, templates or scripts. The Agent Skills specification defines the shared format; Claude Code and Codex add their own discovery and invocation behavior.
The client initially makes skill metadata available. When a skill is selected, its instructions are loaded; references are read as needed. The description therefore needs to identify the right task before the body explains how to perform it. Instructions that are never opened cannot fix a selection problem.
For this example, I would start with a diff review: it gives us a specific change to inspect and a contract to check it against. The lab contains a known defect, and the tests let me check the finding. That makes it possible to inspect skill selection separately from the review result. Permanent project rules stay in AGENTS.md or CLAUDE.md. The skill holds the steps needed when someone requests a review, divided between instructions, a rubric and a report format.
Set up the lab
You need Git, Node.js with its built-in test runner, and at least one of the two clients installed and authenticated. The commands below use a Bash-compatible shell. The observed run used Codex CLI 0.163.0 and Node 24.19.0. The Claude setup follows its documentation; Claude was not run in this lab.
Create a new directory and enter it:
mkdir skills-lab
cd skills-lab
git init -qThis is the Codex layout. For Claude, replace the .agents/skills container with .claude/skills. The three skill files keep the same contents.
skills-lab/
├── README.md
├── discount.mjs
├── discount.test.mjs
└── .agents/skills/review-change/
├── SKILL.md
├── references/review-rubric.md
└── assets/result-format.mdPut the contract to be reviewed in README.md:
# Discount fixture
This is a synthetic review example.
The percentage accepts finite values from 0 through 100 inclusive. A full discount is valid and returns zero.
Run node --test discount.test.mjs. The requested change is the uncommitted diff in discount.mjs.Save this implementation as discount.mjs:
export function discountedTotal(price, percent) {
if (!Number.isFinite(price) || price < 0) throw new RangeError('price');
if (!Number.isFinite(percent) || percent < 0 || percent > 100) throw new RangeError('percent');
return price * (1 - percent / 100);
}Save these four cases as discount.test.mjs:
import test from 'node:test';
import assert from 'node:assert/strict';
import {discountedTotal} from './discount.mjs';
test('ordinary discount', () => assert.equal(discountedTotal(100, 20), 80));
test('no discount', () => assert.equal(discountedTotal(100, 0), 100));
test('full discount is valid', () => assert.equal(discountedTotal(100, 100), 0));
test('out of range is rejected', () => assert.throws(() => discountedTotal(100, 101), RangeError));Run the initial check and commit the comparison baseline in this demonstration repository. The identity below applies only to this commit:
node --test discount.test.mjs
git add README.md discount.mjs discount.test.mjs
git -c user.name="Skills lab" -c user.email="skills-lab@example.invalid" commit -qm "Add discount contract and tests"All four tests should pass. Now change percent > 100 to percent >= 100 in the second condition of discount.mjs, without committing it. The diff should contain only this regression:
- if (!Number.isFinite(percent) || percent < 0 || percent > 100) throw new RangeError('percent');
+ if (!Number.isFinite(percent) || percent < 0 || percent >= 100) throw new RangeError('percent');Run the test again. full discount is valid fails: the contract accepts a 100% discount, while the new condition rejects it. This expected result lets us check the agent’s review against something other than its own assessment.
The three skill files
For Codex, create the directories:
mkdir -p .agents/skills/review-change/references .agents/skills/review-change/assetsFor Claude, use the same subpaths inside .claude/skills/review-change. Save SKILL.md in the review-change directory:
---
name: review-change
description: Review a specified diff for correctness and regressions. Use when asked to review a change before commit or merge. Do not use for explanation-only requests.
---
Review the requested change without editing it.
1. Establish the requested diff or revision range. If the target is
materially ambiguous, ask for the missing scope.
2. Read applicable repository instructions and inspect the diff.
3. Follow affected call sites and tests only as needed to assess
a concrete risk. Use references/review-rubric.md for the rubric.
4. Run relevant, authorized checks when useful and feasible.
Record checks that could not run and the reason.
5. Report actionable findings with file locations, the failure
condition, and its consequence. Do not invent findings.
6. Separate findings from open questions and verification limits.
Use assets/result-format.md to format the result.
Do not claim that unrun checks passed.
Do not commit, push, merge, or publish.The complete description names a change review before commit or merge and excludes explanation-only requests. I would use the same approach beyond this example: name the task that should trigger the skill, without adding activities its procedure is not designed to handle. The body can then focus on the diff, the affected code, and the connection between a defect, its trigger and its consequence.
Put the criteria in references/review-rubric.md:
# Review rubric
Prioritize failures in the changed behavior.
For boundary changes, check empty, missing, and invalid values.
For state changes, check retries, partial failure, and duplicate actions.
For public contracts, inspect affected callers and compatibility.
For performance claims, require an appropriate measurement.
A finding must explain a plausible trigger and consequence.
Do not report a theoretical concern without a code-supported path.
State uncertainty when evidence is incomplete.Put the report format in assets/result-format.md:
# Findings
For each finding: severity, location, trigger, consequence, evidence.
If there are no supported findings, say so.
# Verification
List checks actually run and their results.
List unrun checks and material limits.
# Open questions
Include only unresolved questions that affect the review.Three files are enough for this example. I keep the task boundary and procedure in SKILL.md, put the review criteria in the rubric, and give the report format its own file. If the presentation of findings changes, I know which file to edit. If a criterion is missing, I can add it without lengthening the description shown to the client. The procedure references both supporting files; their presence in the directory alone does not make the agent read them.
Invoke it and inspect what happens
Open the client at the root of skills-lab after saving the files. In Codex CLI or IDE, check the /skills selector and invoke $review-change explicitly. In Claude Code, use /review-change. Local discovery is documented for Codex and Claude Code. If the new skill does not appear, start a fresh session before rewriting its instructions.
Explicit invocation answers one question: can the client use this package? To observe when it selects the skill itself, make an ordinary request without naming the skill:
Explain what discountedTotal does in discount.mjs and which values it accepts. Reply in English.Start a fresh session and ask:
Review the uncommitted change in discount.mjs against the contract in README. Report only concrete issues with file names and line numbers; do not edit files. Reply in English.To retain events from a Codex session, use its non-interactive command. Keep the results outside the project so the trace does not become another file under inspection:
skills_run_dir=$(mktemp -d)
codex exec --ignore-user-config --ephemeral --sandbox read-only --json \
--cd "$PWD" \
"Explain what discountedTotal does in discount.mjs and which values it accepts. Reply in English." \
> "$skills_run_dir/explanation.jsonl"Use the same command with the review prompt and a different output name. --ephemeral avoids retaining the session, while --sandbox read-only restricts writes by the agent’s commands. --ignore-user-config excludes the user configuration file; it does not establish that every personal skill or managed setting is absent. Record those conditions when comparing results.
Inspect completed JSONL events: which command read SKILL.md, which references it opened, whether it ran the tests, and their exit status. “I used the skill” adds no evidence beyond what the trace shows. OpenAI’s guide to skill evals uses this distinction between observable actions and output quality.
Two descriptions, four observations
The broad description in the comparison was:
description: Improve code. Use this skill for code explanations, bugs, performance, tests and quality.The other description is in the complete file above: review a diff, excluding explanation-only requests. To repeat the comparison, prepare two copies of the lab with the same change and the same three skill files, altering only that description. Use a new session for each request in each copy.
Before repeating the trial, define two expected outcomes: a relevant explanation and a review that finds the 100% defect. Record reads and tests separately.
The four observed Codex sessions produced these results. They used the Italian prompts printed in the Italian edition; the prompts above are translations for an English-language run.
| Description and request | Skill reads in the trace | Result |
|---|---|---|
| Broad, explanation | SKILL.md, rubric and format | Function explained; no tests run |
| Focused, explanation | No reads of the three files observed | Function explained; inconsistency with the tests noted |
| Broad, review | All three files | 100% defect found; tests run: three pass and one fails |
| Focused, review | All three files | Same defect found; tests not run |
The useful result, to me, is the difference in selection: no reads of the three files appear in the explanation session with the focused description. Both reviews found the same defect; these observations show no improvement in review quality. The lab and skill files remained unchanged throughout the sessions.
Before adopting the focused description, I would also look at how the review is carried out: the review with the focused description found the problem by reading the diff without running the tests. The procedure permits checks when useful and feasible. In a process that always requires them, I would make that obligation explicit and have the workflow check the result. A correct finding alone does not meet that requirement.
These are four observations on one fixture in the stated client and environment. The trace exposes neither the resolved model nor the complete effective skill catalogue, so I do not use these runs to estimate token savings, general reliability or differences from Claude. The defect is also simple enough to find without a skill: the example shows the path taken, rather than a comparison against an instruction-free baseline.
When it does not trigger, or triggers too often
If the selector cannot find it, check the path, name and YAML header. Codex uses .agents/skills for project skills; Claude uses .claude/skills. A skill stored only in a personal directory on your computer is not automatically available in a cloud environment. Check for another package using the same name, too.
If explicit invocation works but ordinary requests miss the skill, work on the description and test phrases. An overly narrow boundary can exclude a legitimate review phrased differently. If the skill is selected for explanations and general questions, remove tasks that do not belong to its procedure. Keep the requests that exposed a problem as cases to revisit after the next change.
Claude Code documents /skill-doctor from version 2.1.252 to inspect skills’ context cost and use, and claude plugin validate .claude/skills from 2.1.233 to check YAML frontmatter in the directory. /skill-doctor requires feature-flag fetching and is unavailable over Remote Control; see the Claude Code documentation. Neither replaces a review trial. In Codex, /skills exposes the catalogue and codex exec --json records execution events.
Invocation controls are client-specific. Claude supports disable-model-invocation: true for manual invocation only. For Codex, create agents/openai.yaml inside the skill directory:
policy:
allow_implicit_invocation: falseThis manifest is product-specific and separate from the SKILL.md frontmatter; the Codex reference documents the policy. Leave this option out of the description comparison, which observes implicit selection. Claude’s allowed-tools concerns preapproval, rather than a sandbox that makes every other operation impossible.
For this skill, I would keep the focused description and leave the agent to assess the diff and describe defects. The discount calculation and allowed boundary already have a checkable answer in code and tests. I would use the saved requests to decide what to change: an explanation request that opens the review points back to the description; a mandatory test left unrun calls for a workflow check. I would add criteria to the procedure when the problem lies in how the diff is assessed.
For context costs, see the Claude and Codex token research. For connecting claims to evidence, see the agent verification method.

