Skill read labels lose skill names for symlink and alias paths
What version of Codex CLI is running?
Current upstream main at b8b61bc692517adcd18622df260f2ddd80635122 contains the affected exact-path annotation logic.
The behavior was observed and locally validated in a downstream 0.145.0 build based on the same upstream TUI implementation.
What subscription do you have?
Not subscription-specific.
Which model were you using?
Not model-specific. The observed reproduction used GPT-5.6 Luna, but the issue is in TUI rendering of parsed command metadata.
What platform is your computer?
Linux. The path-identity issue is not inherently Linux-specific; symlink or alternate-path aliases can occur on other supported platforms.
What terminal emulator and version are you using (if applicable)?
Not terminal-specific.
Codex doctor report
Not applicable. Skill loading and command execution succeed; only the TUI activity label loses the known skill name.
What issue are you seeing?
The fix for #16303 / #16813 annotates SKILL.md reads only when the parsed command path is byte-for-byte equal to a path in ChatWidget.skills_all.
If the same known skill is read through a symlink or another equivalent path alias, the lookup misses and the TUI falls back to the generic label:
• Explored
└ Read SKILL.md
The skill is still loaded and read successfully. Only its semantic name is lost from the activity display.
A second fragile case is visible in the same function: if the asynchronous skills list has not populated skills_all yet, annotation returns immediately. An early skill read can therefore be rendered without a name even though its metadata becomes available later.
What steps can reproduce the bug?
- Make a user skill available through a symlinked skill directory, for example:
``text``
~/.agents/skills/frontend-coding
-> /home/user/code/skills/frontend-coding
- Ensure Codex has loaded the skill with its frontmatter name
frontend-coding. - Have the agent read the discovered alias path:
``sh``
cat ~/.agents/skills/frontend-coding/SKILL.md
- Observe the completed command in the TUI.
- The activity is rendered as
Read SKILL.mdrather than includingfrontend-coding.
In the locally captured failing rollout, the actual command was:
cat /home/ignat/.agents/skills/frontend-coding/SKILL.md
The symlink resolves to:
/home/ignat/code/skills/skills/frontend-coding/SKILL.md
What is the expected behavior?
Equivalent paths for a known SKILL.md should resolve to the loaded skill's authoritative frontmatter name:
• Explored
└ Read SKILL.md (frontend-coding skill)
This should also remain reliable when the command starts before the initial skills-list response completes.
Directory names should not replace authoritative metadata when the two differ. A directory-derived name is useful only as a last-resort display fallback.
Additional information
Related issue and fix:
- Original report: #16303
- Original exact-path annotation fix: #16813
No separate open report for symlink/alias path misses was found before filing this follow-up.
Local validation:
- Before: a real TUI run reading
/home/ignat/.agents/skills/frontend-coding/SKILL.mdrenderedRead SKILL.md. - After: downstream commit https://github.com/ignatremizov/codex/commit/3f8017a12d208949ba92104718deedb0d83b9b88 rendered
Read SKILL.md (frontend-coding skill)for the same symlink path. - The patched tree passed full workspace format, Clippy, and nextest verification, then a fresh installed 0.145.0 Linux binary reproduced the corrected TUI output.
Source analysis
The current TUI returns without annotation while skills_all is empty, then compares read paths using exact equality:
Skill loading canonicalizes roots for identity:
The resulting canonical path is retained in SkillMetadata:
That makes a valid alias path from ParsedCommand::Read fail the exact comparison even though both paths identify the same skill document.
Implementation / fix considerations
An upstream fix should preserve frontmatter metadata as authoritative while making path matching alias-aware. Possible approaches include:
- Build the TUI lookup from normalized/canonical skill identities plus known discovered aliases when the skills list is ingested.
- Normalize a parsed
SKILL.mdread path before lookup without adding blocking filesystem work to rendering. - Re-annotate pending/running reads when skill metadata arrives, so startup ordering does not permanently lose the label.
- Use the parent directory only as a bounded last-resort display fallback when authoritative metadata is unavailable.
Acceptance criteria
- Reading a known skill through its canonical path includes the skill name.
- Reading the same skill through a symlink/discovered alias includes the same skill name.
- A frontmatter name that differs from the directory name remains authoritative whenever metadata is available.
- A skill read that begins before the initial skills-list response is not permanently rendered as generic
Read SKILL.md. - Ordinary non-skill file-read labels remain unchanged.
- TUI snapshot or rendering coverage includes canonical, symlink/alias, and metadata-not-yet-loaded cases.