codex - 💡(How to fix) Fix Skill discovery recursively registers nested `SKILL.md` files inside symlinked skill directories

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Fix Action

Fix / Workaround

Current workarounds:

The last workaround avoids the issue, but it requires users to restructure otherwise valid skill packages. The better default behavior would be for Codex to stop discovery at the installed skill directory boundary.

Code Example

~/.agents/skills/workflow-toolkit
  -> /tmp/codex-skill-repro/workflow-toolkit

---

workflow-toolkit/
  SKILL.md
  runtime-sources/
    app-workflow/
      skills/
        apply-log/
          SKILL.md
        init-log/
          SKILL.md
    writing-workflow/
      skills/
        apply-log/
          SKILL.md
        init-log/
          SKILL.md

---

apply-log                  app workflow helper
apply-log                  writing workflow helper
init-log                   app workflow helper
init-log                   writing workflow helper
workflow-toolkit           intended top-level skill

---

mkdir -p /tmp/codex-skill-repro/workflow-toolkit/runtime-sources/app-workflow/skills/apply-log
mkdir -p /tmp/codex-skill-repro/workflow-toolkit/runtime-sources/writing-workflow/skills/apply-log

cat > /tmp/codex-skill-repro/workflow-toolkit/SKILL.md <<'EOF'
---
name: workflow-toolkit
description: Top-level workflow toolkit skill.
---

# Workflow Toolkit
EOF

cat > /tmp/codex-skill-repro/workflow-toolkit/runtime-sources/app-workflow/skills/apply-log/SKILL.md <<'EOF'
---
name: apply-log
description: Internal app workflow source file, not an installed user skill.
---

# Internal App Workflow Source
EOF

cat > /tmp/codex-skill-repro/workflow-toolkit/runtime-sources/writing-workflow/skills/apply-log/SKILL.md <<'EOF'
---
name: apply-log
description: Internal writing workflow source file, not an installed user skill.
---

# Internal Writing Workflow Source
EOF

---

ln -s /tmp/codex-skill-repro/workflow-toolkit ~/.agents/skills/workflow-toolkit

---

find ~/.agents/skills -maxdepth 2 -name SKILL.md -print

---

find -L ~/.agents/skills -name SKILL.md -print | rg 'workflow-toolkit|apply-log'

---

~/.agents/skills/workflow-toolkit/SKILL.md
~/.agents/skills/workflow-toolkit/runtime-sources/app-workflow/skills/apply-log/SKILL.md
~/.agents/skills/workflow-toolkit/runtime-sources/writing-workflow/skills/apply-log/SKILL.md

---

{
  "method": "skills/list",
  "params": {
    "cwds": ["/tmp/codex-skill-repro"],
    "forceReload": true
  }
}

---

name: workflow-toolkit
path: /tmp/codex-skill-repro/workflow-toolkit/SKILL.md
enabled: true

name: apply-log
path: /tmp/codex-skill-repro/workflow-toolkit/runtime-sources/app-workflow/skills/apply-log/SKILL.md
enabled: true

name: apply-log
path: /tmp/codex-skill-repro/workflow-toolkit/runtime-sources/writing-workflow/skills/apply-log/SKILL.md
enabled: true

---

~/.agents/skills/<skill-name>/SKILL.md

---

[[skills.config]]
path = "/tmp/codex-skill-repro/workflow-toolkit/runtime-sources/app-workflow/skills/apply-log/SKILL.md"
enabled = false

---

codex -c 'skills.config=[{path="/tmp/codex-skill-repro/workflow-toolkit/runtime-sources/app-workflow/skills/apply-log/SKILL.md", enabled=false}]'

---

enabled: false
RAW_BUFFERClick to expand / collapse

What version of Codex CLI is running?

codex-cli 0.130.0

What subscription do you have?

Not relevant.

Which model were you using?

Not relevant.

What platform is your computer?

linux

What terminal emulator and version are you using (if applicable)?

Not relevant.

What issue are you seeing?

Codex CLI appears to scan ~/.agents/skills recursively for every SKILL.md, while also following symlinked skill directories. This causes nested implementation files inside a symlinked skill package to be registered as independent user skills.

Example setup:

~/.agents/skills/workflow-toolkit
  -> /tmp/codex-skill-repro/workflow-toolkit

The symlink target has its own root SKILL.md, but it also contains internal source trees:

workflow-toolkit/
  SKILL.md
  runtime-sources/
    app-workflow/
      skills/
        apply-log/
          SKILL.md
        init-log/
          SKILL.md
    writing-workflow/
      skills/
        apply-log/
          SKILL.md
        init-log/
          SKILL.md

Those nested runtime-sources/**/SKILL.md files are source material for the top-level skill package. They are not intended to be installed user skills.

Codex nevertheless registers them as available skills. This produces duplicate entries in the model-visible skill list, for example:

apply-log                  app workflow helper
apply-log                  writing workflow helper
init-log                   app workflow helper
init-log                   writing workflow helper
workflow-toolkit           intended top-level skill

This makes skill routing ambiguous and noisy. It also makes symlinked skill packages behave differently from the user expectation that one direct child of ~/.agents/skills represents one installed skill.

What steps can reproduce the bug?

Create a minimal skill package with one root skill and nested internal skill-like source files:

mkdir -p /tmp/codex-skill-repro/workflow-toolkit/runtime-sources/app-workflow/skills/apply-log
mkdir -p /tmp/codex-skill-repro/workflow-toolkit/runtime-sources/writing-workflow/skills/apply-log

cat > /tmp/codex-skill-repro/workflow-toolkit/SKILL.md <<'EOF'
---
name: workflow-toolkit
description: Top-level workflow toolkit skill.
---

# Workflow Toolkit
EOF

cat > /tmp/codex-skill-repro/workflow-toolkit/runtime-sources/app-workflow/skills/apply-log/SKILL.md <<'EOF'
---
name: apply-log
description: Internal app workflow source file, not an installed user skill.
---

# Internal App Workflow Source
EOF

cat > /tmp/codex-skill-repro/workflow-toolkit/runtime-sources/writing-workflow/skills/apply-log/SKILL.md <<'EOF'
---
name: apply-log
description: Internal writing workflow source file, not an installed user skill.
---

# Internal Writing Workflow Source
EOF

Symlink that package into ~/.agents/skills:

ln -s /tmp/codex-skill-repro/workflow-toolkit ~/.agents/skills/workflow-toolkit

Start Codex and inspect available skills, or call the app-server skills/list method with forceReload: true.

The filesystem difference is easy to see from the shell. A shallow scan sees no nested files:

find ~/.agents/skills -maxdepth 2 -name SKILL.md -print

But following symlinks recursively reveals files that Codex also registers:

find -L ~/.agents/skills -name SKILL.md -print | rg 'workflow-toolkit|apply-log'

Observed output:

~/.agents/skills/workflow-toolkit/SKILL.md
~/.agents/skills/workflow-toolkit/runtime-sources/app-workflow/skills/apply-log/SKILL.md
~/.agents/skills/workflow-toolkit/runtime-sources/writing-workflow/skills/apply-log/SKILL.md

The app-server skills/list method reports the same nested files as available user skills:

{
  "method": "skills/list",
  "params": {
    "cwds": ["/tmp/codex-skill-repro"],
    "forceReload": true
  }
}

Representative result:

name: workflow-toolkit
path: /tmp/codex-skill-repro/workflow-toolkit/SKILL.md
enabled: true

name: apply-log
path: /tmp/codex-skill-repro/workflow-toolkit/runtime-sources/app-workflow/skills/apply-log/SKILL.md
enabled: true

name: apply-log
path: /tmp/codex-skill-repro/workflow-toolkit/runtime-sources/writing-workflow/skills/apply-log/SKILL.md
enabled: true

What is the expected behavior?

Codex should treat each direct child of ~/.agents/skills as one installed skill entry:

~/.agents/skills/<skill-name>/SKILL.md

If <skill-name> is a symlink to a directory, Codex should resolve the symlink to read the target's root SKILL.md, but it should not continue recursively discovering additional nested SKILL.md files inside that target.

In other words, the symlink target should be used as the skill directory, not as a new recursive discovery root.

The preferred fix is to prohibit deeper recursive discovery after resolving a direct installed skill directory. Installing one skill folder should install one skill.

Alternative acceptable fixes:

  • Add a scan-depth option, defaulting to one skill directory level.
  • Add a skill discovery ignore option, such as skills.discovery.exclude = ["**/runtime-sources/**"].
  • If recursive scanning is intentional, document it explicitly in the skills docs, including the fact that any nested SKILL.md under an installed skill directory may be registered as a separate skill.

My recommendation is the first option: do not scan deeper. That keeps symlinked skill directories consistent with normal installed skill directories and avoids accidental registration of internal source material.

Additional information

Current workarounds:

  1. Disable specific false-positive skills by path in config.toml:
[[skills.config]]
path = "/tmp/codex-skill-repro/workflow-toolkit/runtime-sources/app-workflow/skills/apply-log/SKILL.md"
enabled = false

This works after restarting Codex, but it does not prevent the scan and does not scale well when many nested SKILL.md files exist.

  1. Disable by one-off CLI config override:
codex -c 'skills.config=[{path="/tmp/codex-skill-repro/workflow-toolkit/runtime-sources/app-workflow/skills/apply-log/SKILL.md", enabled=false}]'

This causes skills/list to report that entry with:

enabled: false
  1. Disable individual skills through /skills in the TUI. This is only practical for a small number of false positives.

  2. Avoid symlinking rich development packages into ~/.agents/skills. Instead, use a shallow wrapper directory containing only the intended root SKILL.md, or install a compiled flat skill snapshot that has only direct skill directories.

The last workaround avoids the issue, but it requires users to restructure otherwise valid skill packages. The better default behavior would be for Codex to stop discovery at the installed skill directory boundary.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix Skill discovery recursively registers nested `SKILL.md` files inside symlinked skill directories