首页
/ Open Interpreter skill-installer 技能实战:从 GitHub 仓库检索并安装 Skills 到 $CODEX_HOME/skills

Open Interpreter skill-installer 技能实战:从 GitHub 仓库检索并安装 Skills 到 $CODEX_HOME/skills

2026-09-06 16:14:49作者:沈韬淼Beryl

本文为 Open Interpreter 内置的 skill-installer 技能编写技术解析。该技能用于把存放在 GitHub 仓库中的 Codex 技能(Skill)按目录结构安装到本地 $CODEX_HOME/skills,支持列出自定义精选列表、批量安装、私有仓库认证与多种下载策略。读完后,你将掌握其全部命令行参数、fallback 下载链路,以及技能安装后为何"下一轮对话才生效"的运行时原理。

技能定位与文件结构

skill-installer 是随本仓库分发的一个系统技能(system skill),其定义入口为 SKILL.md。frontmatter 声明了技能身份:

---
name: skill-installer
description: 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).
metadata:
  short-description: Install curated skills from openai/skills or other repos
---

这段 frontmatter 不是摆设——运行时的技能解析器 parser.rs 会对每个 SKILL.md 做严格校验:name 缺失时回退为目录名、超过 64 字符会报错;description 为必填字段,它决定了技能何时被模型选中;metadata.short-description 则用于界面展示。此外,agents/openai.yaml 为该技能提供了 display_name 与图标等界面元数据。

技能本体由三个 Python 辅助脚本组成:

skill-installer/
├── SKILL.md
├── agents/openai.yaml
├── assets/                       # 图标
└── scripts/
    ├── github_utils.py           # GitHub 请求公共工具
    ├── list-skills.py            # 列出可安装技能
    └── install-skill-from-github.py  # 安装技能

SKILL.md 的说明,技能默认从 openai/skills 仓库的 skills/.curated 目录安装精选技能;用户也可以指定其他任意 GitHub 仓库/路径(包括私有仓库)。实验性技能位于 skills/.experimental,安装方式相同。

列出可安装技能:list-skills.py

当用户询问"有哪些技能可以安装"、或触发该技能但没说明具体要做的事时,应运行列表脚本(参数相对技能目录):

scripts/list-skills.py                        # 默认列出 skills/.curated
scripts/list-skills.py --format json          # JSON 输出,便于程序消费
scripts/list-skills.py --path skills/.experimental   # 列出实验性技能

完整参数(来自 list-skills.py 的 argparse 定义):

参数 默认值 说明
--repo openai/skills 目标仓库,owner/repo 格式
--path skills/.curated 仓库内要列举的目录路径
--ref main Git 分支/标签/提交
--format text 输出格式,textjson

实现要点(见 list-skills.py#L50-L65):

  1. 通过 GitHub Contents API 拉取目标目录的条目列表(API 端点构造见 github_utils.py#L20-L21),只保留 type == "dir" 的条目,即"一个子目录 = 一个技能",结果按名称排序。
  2. 本地扫描 $CODEX_HOME/skillsCODEX_HOME 未设置时回退为 ~/.codex)下已有的子目录名,对已安装项在输出末尾追加 (already installed) 标注;JSON 模式则输出 {"name": ..., "installed": true/false} 数组。
  3. 出错时(如路径 404)向 stderr 打印 Error: ... 并以非零码退出——文档明确要求此时"解释错误并退出",而不是静默吞掉。

安装技能:install-skill-from-github.py

参数与典型用法

安装脚本支持两种互斥的源描述方式(--repo + 一个或多个 --path,或直接给一个 --url),核心参数定义见 install-skill-from-github.py#L247-L266

参数 默认值 说明
--repo <owner>/<repo> --path 搭配使用
--url <github.com URL> 形如 https://github.com/<owner>/<repo>/tree/<ref>/<path>,自动解析出 owner/repo/ref/path
--path <path> [...] 仓库内技能路径,可传多个,一次安装多个技能
--ref <ref> main 源 ref;--url 中若含 /tree/<ref>/ 则以 URL 中的 ref 为准
--dest <path> $CODEX_HOME/skills 安装根目录
--name <name> 路径 basename 目标技能目录名;仅在单路径时生效
--method auto|download|git auto 下载策略

文档给出的典型命令:

# 从 openai/skills 的实验性目录安装某个技能
scripts/install-skill-from-github.py --repo openai/skills --path skills/.experimental/<skill-name>

# 直接用一个 tree URL 安装
scripts/install-skill-from-github.py --url https://github.com/<owner>/<repo>/tree/<ref>/<path>

--path 传多个值时,每个路径的 basename 自动成为各自的目标技能名(因此 --name 只在单路径时生效,逻辑见 main 函数)。

三种获取方法与 fallback 链

下载策略的核心是 _prepare_repoinstall-skill-from-github.py#L187-L206),与文档"默认直连下载、鉴权失败回退 git"的描述一一对应:

  • download:请求 codeload.github.com/<owner>/<repo>/zip/<ref> 整仓压缩包,解压后要求顶层恰好只有一个目录(<repo>-<ref> 形态),否则报错;
  • git:使用 git clone --filter=blob:none --depth 1 --sparse --single-branch --branch <ref> 做浅层稀疏克隆,再 sparse-checkout set <paths> 只检出技能目录,最后 checkout <ref>——对大仓库非常省流量;
  • auto(默认):先尝试 download,若返回 HTTP 401/403/404(典型的鉴权/权限信号)则自动降级到 git;其他错误不降级。git 分支内部还有一次重试:先试 HTTPS 地址(https://github.com/<owner>/<repo>.git),失败后再试 SSH(git@github.com:<owner>/<repo>.git)。

私有仓库正是依赖这条链路工作:git 侧使用本机已有 git 凭据;download 侧则可读取 GITHUB_TOKENGH_TOKEN 环境变量——公共请求工具 github_utils.py#L10-L17 在检测到 token 时会自动附加 Authorization: token <token> 请求头,并携带 codex-skill-install/codex-skill-list 的 User-Agent。

内置的安全校验

安装过程包含多道防护,这也是脚本比"一行 curl"稳健的原因:

  • Zip Slip 防护:解压前逐条校验归档内每个条目 realpath 必须落在目标临时目录内,发现越界直接抛错(_safe_extract_zip);
  • 路径校验--path 必须是仓库内相对路径,拒绝绝对路径与 .. 上跳(_validate_relative_path);
  • 技能名校验:目标名必须是单一路径段且不能是 ./..
  • 技能完整性校验:每个候选目录必须是目录且内含 SKILL.md,否则该技能安装失败(_validate_skill)——这与上文提到的运行时 frontmatter 解析形成闭环,装进来的技能才能被正确识别;
  • 幂等保护:目标技能目录已存在则整体中止(Destination already exists),不做覆盖,避免误删用户修改过的技能;
  • 临时目录清理:下载发生在 mkdtemp 临时目录中,finally 分支保证无论成败都会清理。

沙箱网络提示

SKILL.md 特别指出:这些脚本全部走网络,因此当会话运行在沙箱中时,执行它们前应请求提权(escalation)出沙,而不是在受限网络中静默失败。

与运行时的协作:安装为何"下一轮生效",.system 为何免装

安装完成后,脚本打印 Installed <name> to <dest>,技能文档要求告知用户"该技能将在下一轮对话可用"。这与运行时的技能加载机制一致:技能元数据在每轮开始时从磁盘索引,新落盘的 SKILL.md 自然要到下一轮才被解析进上下文。

另外两个源码层面的佐证值得了解:

  1. 系统技能是内嵌分发的lib.rs#L49-L95 通过 include_dir!src/assets/samples 下的整套技能(含本技能)编译进二进制,启动时经 install_system_skills 写入 $CODEX_HOME/skills/.system;并用 .codex-system-skills.marker 记录内嵌目录指纹,指纹匹配即跳过重复写入。正因如此,文档说明 openai/skills 仓库中 skills/.system 下的技能已随产品预装,无需通过本技能安装;若用户坚持,才允许下载覆盖。
  2. 运行技能脚本会被识别为该技能的隐式调用invocation.rs#L16-L84 会对命令做词法切分,识别 python scripts/xxx.py 这类执行器 + 脚本扩展名组合,再沿路径向上匹配所属技能的 scripts/ 目录——所以本技能的辅助脚本在沙箱中运行时,运行时同样能把它关联回 skill-installer 这个技能本身,其权限与审批行为按技能策略执行。

交互规范小结

SKILL.md 的 Communication 一节,列表结果应组织为:

Skills from {repo}:
1. skill-1
2. skill-2 (already installed)
3. ...
Which ones would you like installed?

用户询问实验性技能时改从 .experimental 列举并相应标注来源;安装完成后明确告知"下一轮对话可用"。整个技能的设计可以概括为:用三个小脚本把"GitHub 目录浏览 + 受控下载 + 安全落盘"封装成模型可以直接驱动的能力,而参数表、fallback 链与安全校验的实现细节都能在上文列出的源码文件中逐一核对。

相关文件索引:

登录后查看全文
热门项目推荐
相关项目推荐