skill-installer

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗

Install Codex skills into $CODEX_HOME/skills from a curated list or a GitHub repo path. Use when a user asks to list installable skills, install a curated skill, or install a skill from another repo (including private repos).

codex-rs/skills/src/assets/samples/skill-installer/SKILL.md

Download bundle ↓
main · 18d7ace8 bundle filesScanned 2026-09-14

scripts/list-skills.py

705 tokens · o200k_base · 2,948 bytes

Source excerpt starting at line 1.
#!/usr/bin/env python3"""List skills from a GitHub repo path.""" from __future__ import annotations import argparseimport jsonimport osimport sysimport urllib.error from github_utils import github_api_contents_url, github_request DEFAULT_REPO = "openai/skills"DEFAULT_PATH = "skills/.curated"DEFAULT_REF = "main"  class ListError(Exception):    pass  class Args(argparse.Namespace):    repo: str    path: str    ref: str    format: str  def _request(url: str) -> bytes:    return github_request(url, "codex-skill-list")  def _codex_home() -> str:    return os.environ.get("CODEX_HOME", os.path.expanduser("~/.codex"))  def _installed_skills() -> set[str]:    root = os.path.join(_codex_home(), "skills")    if not os.path.isdir(root):        return set()    entries = set()    for name in os.listdir(root):        path = os.path.join(root, name)        if os.path.isdir(path):            entries.add(name)    return entries  def _list_skills(repo: str, path: str, ref: str) -> list[str]:    api_url = github_api_contents_url(repo, path, ref)    try:        payload = _request(api_url)    except urllib.error.HTTPError as exc:        if exc.code == 404:            raise ListError(                f"Skills path not found: https://github.com/{repo}/tree/{ref}/{path}"            ) from exc        raise ListError(f"Failed to fetch skills: HTTP {exc.code}") from exc    data = json.loads(payload.decode("utf-8"))    if not isinstance(data, list):        raise ListError("Unexpected skills listing response.")    skills = [item["name"] for item in data if item.get("type") == "dir"]    return sorted(skills)  def _parse_args(argv: list[str]) -> Args:    parser = argparse.ArgumentParser(description="List skills.")    parser.add_argument("--repo", default=DEFAULT_REPO)    parser.add_argument(        "--path",        default=DEFAULT_PATH,        help="Repo path to list (default: skills/.curated)",    )    parser.add_argument("--ref", default=DEFAULT_REF)    parser.add_argument(        "--format",        choices=["text", "json"],        default="text",        help="Output format",    )    return parser.parse_args(argv, namespace=Args())  def main(argv: list[str]) -> int:    args = _parse_args(argv)    try:        skills = _list_skills(args.repo, args.path, args.ref)        installed = _installed_skills()        if args.format == "json":            payload = [                {"name": name, "installed": name in installed} for name in skills            ]            print(json.dumps(payload))        else:            for idx, name in enumerate(skills, start=1):                suffix = " (already installed)" if name in installed else ""                print(f"{idx}. {name}{suffix}")        return 0    except ListError as exc:        print(f"Error: {exc}", file=sys.stderr)        return 1  if __name__ == "__main__":    raise SystemExit(main(sys.argv[1:])) 
Referenced from SKILL.md