Display actual skill names instead of "Read SKILL.md"
Resolved 💬 8 comments Opened Mar 31, 2026 by zly2006 Closed Apr 6, 2026
💡 Likely answer: A maintainer (etraut-openai, contributor)
responded on this thread — see the highlighted reply below.
What variant of Codex are you using?
CLI
What feature would you like to see?
Currently, when a skill is explored, the system displays a generic Read SKILL.md. This makes it slightly difficult to grasp which specific skill is being executed at a glance.
Possible solution
It would be much clearer and more intuitive if we displayed the actual skill name (e.g., Skill docx) instead of the markdown file name.
Expected Behavior (Before & After)
Before:
• Explored
└ Read SKILL.md
List wechat_sxhm_report
After:
• Explored
└ Skill docx
List wechat_sxhm_report
Additional information
I have already implemented a draft of this improvement on my end. If the maintainers think this is a valuable enhancement, I would be more than happy to open a Pull Request for your review!
https://github.com/zly2006/codex/tree/feat/skill-names
8 Comments
I've looked into this and identified the fix. The issue is in
codex-rs/tui/src/exec_cell/render.rsin thereads_onlybranch ofexploring_display_lines()(around line 297). Currently it extracts onlyname(which is always"SKILL.md") and labels it"Read". The fix is to detect whenname == "SKILL.md"and extractpath.parent().file_name()as the skill identifier instead, displaying"Skill python"rather than"Read SKILL.md". Regular file reads would be labeled"File". Edge case: when path has no parent, fall back to the raw filename safely via.and_then(). I have a working implementation ready if the team would like to review it.Adding more detail on the root cause and fix for anyone evaluating this.
Root cause —
codex-rs/tui/src/exec_cell/render.rs,exploring_display_lines(), lines 297-309:nameinParsedCommand::Readis the bare filename — it is always"SKILL.md"for skill reads. Thepathfield (aPathBuf) contains the full path like/home/user/.codex/skills/python/SKILL.md, so the parent directory name is the actual skill identifier.Fix — detect
name == "SKILL.md"and extractpath.parent().file_name():Result:
"Read SKILL.md"→"Skill python". Regular file reads (non-SKILL.md) get a"File"label. Mixed calls (skill + regular file in the same merged block) produce two separate display entries.Tests written (in the existing
#[cfg(test)]block):skill_reads_display_skill_name_not_filename— full path resolves to skill name,SKILL.mdhiddenmixed_skill_and_regular_reads_display_both_labels— bothSkillandFilelabels renderskill_read_with_bare_path_falls_back_gracefully— bare path with no parent does not panicThe same fix is applied consistently in the
elsebranch (mixed reads/non-reads calls).Happy to submit a PR if invited.
@theshivam7 are you spamming the community using LLMs? According to the skill standards, the SKILL.md must have a parent. And why are you voting up yourself?
Hey @zly2006, fair points. I did use AI assistance to help understand the codebase — I should have mentioned that upfront. That said, I did put in genuine effort to read through the code, understand the root cause, and write proper tests for the edge cases. The fallback for the bare path was intentional defensive coding, but I take your point that per skill standards it's not needed.
The upvote was just me reacting to the issue, not trying to game anything. No bad intent.
I'm still learning and trying to contribute where I can. Apologies if it came across the wrong way.
The challenge here is that reads from a SKILL.md file are just like reads of any other project files from the perspective of the harness.
@theshivam7, the solution you're suggesting is a bit of a hack — a heuristic that will break under some circumstances. In particular, it won't work for a skill whose frontmatter-specified name differs from its directory name. To get the proper name, we'd need to look up its frontmatter name in an internal map of known skills.
Good point — I've updated the implementation to use the frontmatter name instead of the directory name.
The fix now builds a
HashMap<PathBuf, String>fromChatWidget.skills_allatExecCellcreation time, mapping each skill'spath_to_skills_md(normalized viadunce::canonicalize) to its display name (usingskill_display_name, which respectsinterface.display_namebefore falling back toname). The render layer looks upParsedCommand::Read { path }in that map — if found, the frontmatter name is shown; if not found, it falls back to the raw filename unchanged.Changes across 5 files (
exec_cell/model.rs,exec_cell/render.rs,chatwidget/skills.rs,chatwidget.rs,history_cell.rs). The implementation is on my fork at theshivam7/codex, branchfix/skill-names-in-tui, if useful for reference.(I used an AI assistant only to help navigate and understand the codebase — the analysis, design, and implementation decisions are entirely my own.)
This will be included in the next release.
Thank you! Really appreciate the feedback and the opportunity to contribute.