Explicit $skill mention injects SKILL.md, then the model reads the file again because of the read-completely rule
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
What version of Codex CLI is running?
codex-cli 0.153.4
What subscription do you have?
Pro
Which model were you using?
gpt-5.6-sol (reasoning effort high)
What platform is your computer?
macOS 26.6.2 (Darwin 25.6.0), arm64
What terminal emulator and version are you using (if applicable)?
Not terminal-specific. Reproduced from the session rollout jsonl.
Codex doctor report
Not included; the report is about deterministic prompt text and is reproducible from the rollout file.
What issue are you seeing?
When a skill is invoked by explicit $skill-name mention, the CLI injects the full SKILL.md into the user turn as a <skill> block (codex-rs/ext/skills/src/fragments.rs, SkillInstructions::body: <name>, <path>, then the complete file contents). The skills section of the system prompt (codex-rs/ext/skills/src/catalog_prompt.rs) then says:
- After deciding to use a skill, the main agent must read its
SKILL.mdcompletely before taking task actions. ... For a filesystem path, open the file.
Nothing tells the model that the injected block satisfies that requirement. The model's first tool call is therefore a shell read of the same file from the <path> shown in the block, returning byte-identical text.
Observed in thread 01a075e4-7a77-7f51-80ce-89cc522ef21d:
- User turn:
$bmad-build inspector story 1 from ~/src/obeya, followed by the injected<skill>block containing the full 1.5 kBSKILL.md. - First model action:
sed -n '1,240p' <path>/.agents/skills/bmad-build/SKILL.md. - The skill's own first line says to run one render command "exactly once", so the extra read is pure overhead: one round trip (about 6 s on this connection) and about 4K uncached input tokens per agent.
- A sub-agent spawned from that thread (no
<skill>block in its prompt at all) selected the same skill and made the same read, so the rule fires for every agent that decides to use a skill.
Asked afterwards why it re-read the file, the model answered:
Because the harness instructions explicitly say: "When a skill is triggered, the main agent must read its
SKILL.mdcompletely." I treated the injected copy as metadata/context, not proof that I had performed that required file read, so I re-read the file from its declared path.
That is a reasonable reading of the prompt as written. The two mechanisms (mention injection and the read-completely rule from #16479 / commit 56554904) were introduced independently and are not reconciled.
What steps can reproduce the bug?
- Create any repository skill, e.g.
.agents/skills/demo/SKILL.mdwith a short body (a few lines is enough). - Start
codexin that repository. - Send
$demo do the thing. - Inspect the rollout jsonl in
~/.codex/sessions/: the user turn contains the full<skill>block, and the firstexec_commandis ased/catof the sameSKILL.mdpath.
What is the expected behavior?
When the selected skill's SKILL.md has already been injected into the conversation by the mention path, the model should proceed directly with the skill's instructions and not open the file again. Either:
- amend step 1 in
catalog_prompt.rswith one sentence such as "If the completeSKILL.mdis already present in the conversation inside a<skill>block, treat it as read and do not open the file again", or - have the
<skill>block itself state that it is the complete file and satisfies the read requirement.
Additional information
Related: #16479 (introduced the read-completely wording), #35853 (re-reads across turns on implicit selection, closed by the reporter). This report is the explicit-mention case, where the file is already in the prompt.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with codex-rs/ext/skills/src/catalog_prompt.rs and codex-rs/ext/skills/src/fragments.rs to trace the read-completely wording and the injected block. Reproduce the explicit $demo flow and inspect the rollout JSONL; done means a complete injected SKILL.md no longer causes a duplicate file read.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- ai, cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 87/100