Claude Skills, anywhere: making them first-class in Codex CLI

Make Claude Skills work in other agents like Codex by adding the missing piece: a small enumerator script.

Claude Skills, anywhere: making them first-class in Codex CLI

Claude Skills work because they are vendor-agnostic by design. Hats off to Anthropic for designing such a simple, yet mighty concept. A directory holds a SKILL.md with YAML front-matter (name, description, optional allowed-tools) and a body that is only read when relevant.

├── algorithmic-art
│   ├── LICENSE.txt
│   ├── SKILL.md
│   └── templates
│       ├── generator_template.js
│       └── viewer.html
├── artifacts-builder
│   ├── LICENSE.txt
│   ├── scripts
│   │   ├── bundle-artifact.sh
│   │   ├── init-artifact.sh
│   │   └── shadcn-components.tar.gz
│   └── SKILL.md
├── brand-guidelines
│   ├── LICENSE.txt
│   └── SKILL.md

That narrow contract gives you progressive discoverability without chewing through context (like MCP servers with extensive tool descriptions do, if you configured a installed of them), and it travels well beyond Claude if you respect the format.

First try: setup on project level

I started by cloning Anthropic’s skills repo into a Codex project and adding one paragraph to AGENTS.md that explains the boot sequence: enumerate skills by reading front-matter only; remember them; load a skill’s body progressively on demand.

The missing piece in non-Claude-Code agents is a small, standard-compliant skills enumerator.

Mine is a single file with uv inline dependencies. It walks skills/**/SKILL.md, parses the YAML front-matter, and prints a minimal JSON array. There’s no proprietary schema here—just name, description, and optionally allowed-tools.

#!/usr/bin/env -S uv run -s
# /// script
# requires-python = ">=3.8"
# dependencies = ["python-frontmatter","pyyaml"]
# ///
import os, sys, json
from pathlib import Path
import frontmatter

root = (
    Path(sys.argv[1])
    if len(sys.argv) > 1
    else Path(
        os.environ.get("CODEX_SKILLS_DIR", str(Path.home() / ".config/codex/skills"))
    )
)
if not root.exists():
    print(f"missing skills dir: {root}", file=sys.stderr)
    sys.exit(1)

skills = []
for f in sorted(root.rglob("SKILL.md")):
    meta = (frontmatter.load(f).metadata) or {}
    n, d = meta.get("name"), meta.get("description")
    if isinstance(n, str) and isinstance(d, str):
        item = {"name": n, "description": d, "path": str(f)}
        if "allowed-tools" in meta:
            item["allowed-tools"] = meta["allowed-tools"]
        skills.append(item)
skills.sort(key=lambda s: s["name"])
json.dump(skills, sys.stdout, ensure_ascii=False, indent=2)

~/bin/list-skills

Once that was in place, Codex behaved exactly as hoped, with the following added to the AGENTS.md

## Skills
You’ve got skills.
- List your skills directly after reading this via `list-skills` (uses `$CODEX_SKILLS_DIR`). Remember them.
- If a skill matches a certain task at hand, only then read its full documentation (`SKILL.md`) and use it.

AGENTS.md

Next I asked Codex to

create a single page pdf (test.pdf) with a nicely centered one-liner describing this project.

It looked up the skill candidates, lazily opened the matching PDF skill’s SKILL.md, composed a short reportlab script, and ran it via uv. The trace shows the sequence: read SKILL.md, generate the script, produce test.pdf.

• Ran list-skills
  └ [
      {
    … +73 lines
      }
    ]

• Explored
  └ Read SKILL.md

• I'll create a Python script using reportlab to produce a nicely centered one-liner PDF named test.pdf, running
  it via uv to follow instructions for Python scripts with dependencies, and choosing a clear, concise text with
  appropriate font and page size.

• Ran uv run --with reportlab python - <<'PY'
  … (creates test.pdf)
  PY

• Explored
  └ List test.pdf

Codex output

Well, that was easy.

Up next: making skills available globally

This worked well enough that the next concern immediately showed up: one project is nice, but I keep several codebases active at once. I don’t want to copy the skills into every repository or chase updates in five places. The fix is to treat the skills and the enumerator as global assets. I put the skills in Codex’ installation folder and dropped the single executable enumerator list-skills into my PATH. Codex can now discover skills in any repo simply by running that command as I instructed it in AGENTS.md (can also be globally set in ~/.codex/AGENTS.md).

The skills live in ~/.codex/skills. The enumerator is placed in ~/bin/list-skills and defaults to that directory, but accepts a path override.

The flow still makes sense after this change. Codex boots, executes list-skills, holds the small JSON in memory, and defers any heavy reads until a skill actually matches. The global setup removes duplication and keeps updates trivial: pull the skills once, and every project sees the change immediately.

For completeness, here is a shortened sample of what Codex sees from list-skills

[
  {
    "name": "pdf",
    "description": "Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.",
    "path": "/Users/robertg/.codex/skills/document-skills/pdf/SKILL.md"
  },
…
  {
    "name": "algorithmic-art",
    "description": "Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.",
    "path": "/Users/robertg/.codex/skills/algorithmic-art/SKILL.md"
  }
]

That’s all an agent needs to behave like Claude with respect to progressive discovery and selection. The heavy lifting remains in the skill authoring, which is exactly how it should be. Anthropic deserves credit for specifying a format that keeps the contract small and the runtime behavior predictable; the rest is prompt discipline. With a single executable named list-skills and a single paragraph in AGENTS.md, Codex becomes a good citizen of that ecosystem—no lock-in, no ceremony, and no duplicate manifests scattered across your repos.