super-skill-cli 0.9.2__tar.gz → 0.10.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/.claude-plugin/marketplace.json +2 -2
  2. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/.claude-plugin/plugin.json +1 -1
  3. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/CHANGELOG.md +20 -0
  4. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/PKG-INFO +14 -10
  5. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/README.md +13 -9
  6. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/README.zh-CN.md +10 -6
  7. super_skill_cli-0.10.0/codex/README.md +43 -0
  8. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/codex/install.sh +3 -2
  9. super_skill_cli-0.10.0/codex/skills/super-skill/agents/openai.yaml +12 -0
  10. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/pyproject.toml +1 -1
  11. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/cli.py +60 -10
  12. super_skill_cli-0.10.0/super_skill/config.py +44 -0
  13. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_codex_package.py +2 -0
  14. super_skill_cli-0.10.0/tests/test_target_adapter.py +99 -0
  15. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/uv.lock +1 -1
  16. super_skill_cli-0.9.2/codex/README.md +0 -43
  17. super_skill_cli-0.9.2/super_skill/config.py +0 -25
  18. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/.gitignore +0 -0
  19. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/LICENSE +0 -0
  20. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/codex/skills/super-skill/SKILL.md +0 -0
  21. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/commands/candidates.md +0 -0
  22. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/commands/doctor.md +0 -0
  23. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/commands/mine.md +0 -0
  24. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/commands/seed.md +0 -0
  25. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/commands/status.md +0 -0
  26. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/README.md +0 -0
  27. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/cases/case1/PROMPT.md +0 -0
  28. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/cases/case1/broken.py +0 -0
  29. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/cases/case1/fixed.py +0 -0
  30. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/cases/case1/verify_test.py +0 -0
  31. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/cases/case2/PROMPT.md +0 -0
  32. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/cases/case2/broken.py +0 -0
  33. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/cases/case2/fixed.py +0 -0
  34. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/cases/case2/verify_test.py +0 -0
  35. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/cases/case3/PROMPT.md +0 -0
  36. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/cases/case3/broken.py +0 -0
  37. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/cases/case3/fixed.py +0 -0
  38. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/cases/case3/verify_test.py +0 -0
  39. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/gate2_report.py +0 -0
  40. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/grader.py +0 -0
  41. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/handwritten/SKILL.md +0 -0
  42. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/evals/test-fix-family/results.template.json +0 -0
  43. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/hooks/hooks.json +0 -0
  44. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/skills/super-skill/SKILL.md +0 -0
  45. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/__init__.py +0 -0
  46. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/candidate.py +0 -0
  47. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/capture.py +0 -0
  48. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/doctor.py +0 -0
  49. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/evallite.py +0 -0
  50. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/gate.py +0 -0
  51. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/hooks.py +0 -0
  52. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/mine.py +0 -0
  53. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/minestate.py +0 -0
  54. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/redact.py +0 -0
  55. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/registry.py +0 -0
  56. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/schemas.py +0 -0
  57. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/seed.py +0 -0
  58. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/super_skill/skillmd.py +0 -0
  59. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_candidate.py +0 -0
  60. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_capture.py +0 -0
  61. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_cli.py +0 -0
  62. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_doctor.py +0 -0
  63. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_evallite.py +0 -0
  64. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_gate.py +0 -0
  65. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_gate2_harness.py +0 -0
  66. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_hooks.py +0 -0
  67. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_minestate.py +0 -0
  68. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_plugin_manifest.py +0 -0
  69. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_redact.py +0 -0
  70. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_registry.py +0 -0
  71. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_seed.py +0 -0
  72. {super_skill_cli-0.9.2 → super_skill_cli-0.10.0}/tests/test_skillmd.py +0 -0
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "super-skill: personal Agent-Skill package manager (versioned registry, rollback, mining).",
9
- "version": "0.9.2"
9
+ "version": "0.10.0"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "super-skill",
14
14
  "source": "./",
15
15
  "description": "Git-backed versioned registry for your Claude Code skills: seed import, explain/provenance, one-command rollback, integrity doctor, and opportunity mining. Wraps the `super-skill` CLI (pip/uv installable as super-skill-cli).",
16
- "version": "0.9.2",
16
+ "version": "0.10.0",
17
17
  "category": "development"
18
18
  }
19
19
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "super-skill",
3
- "version": "0.9.2",
3
+ "version": "0.10.0",
4
4
  "description": "Personal Agent-Skill package manager: a git-backed, versioned registry for your Claude Code skills with seed import, provenance/explain, one-command rollback, integrity doctor, and opportunity mining from captured sessions.",
5
5
  "author": {
6
6
  "name": "sdsrss",
@@ -3,6 +3,26 @@
3
3
  All notable changes to this project are documented here. Format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/); this project uses semantic versioning.
5
5
 
6
+ ## [0.10.0] - 2026-07-12
7
+
8
+ ### Added
9
+ - **Codex Target Adapter** (docs/01 FR-PUB-2) — the CLI now distributes to more
10
+ than one host. `seed`, `approve`, `rollback`, and a new `materialize` command
11
+ take `--host claude | codex | all`; `codex` reads/writes `~/.agents/skills`
12
+ (override with `SUPER_SKILL_CODEX_SKILLS`), `all` targets both hosts. Defaults
13
+ stay `claude`, so existing behavior is unchanged.
14
+ - **`materialize [skill_id] --host …`** — explicitly (re)distribute one skill, or
15
+ all active skills, to Claude Code and/or Codex.
16
+ - **`codex/agents/openai.yaml`** — an optional Codex host-extension shipped with
17
+ the meta-skill (`interface` display name + `policy.allow_implicit_invocation`),
18
+ installed alongside `SKILL.md` by `codex/install.sh`. Schema per the Codex
19
+ build-skills docs; kept to the fields super-skill needs.
20
+
21
+ ### Notes
22
+ - Self-learning (M1–M5) remains gated off by the H1 falsification GATE — not
23
+ built. The Codex adapter here is packaging/distribution (FR-PUB-2), not the
24
+ self-learning track.
25
+
6
26
  ## [0.9.2] - 2026-07-12
7
27
 
8
28
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: super-skill-cli
3
- Version: 0.9.2
3
+ Version: 0.10.0
4
4
  Summary: Personal Agent-Skill package manager: versioned registry, seed import, explain, rollback (M0+WS scope).
5
5
  Project-URL: Homepage, https://github.com/sdsrss/super-skill
6
6
  Project-URL: Repository, https://github.com/sdsrss/super-skill
@@ -93,8 +93,9 @@ pipx install super-skill-cli
93
93
  codex/install.sh # drops the meta-skill into ~/.agents/skills
94
94
  ```
95
95
 
96
- Point the CLI at the Codex directory with `SUPER_SKILL_HOST_SKILLS=~/.agents/skills`.
97
- See [`codex/README.md`](codex/README.md).
96
+ The CLI speaks Codex natively via `--host codex` — `super-skill seed --host codex`,
97
+ `super-skill materialize --host codex` (or `--host all` for both hosts). See
98
+ [`codex/README.md`](codex/README.md).
98
99
 
99
100
  ## Features
100
101
 
@@ -104,7 +105,8 @@ See [`codex/README.md`](codex/README.md).
104
105
  | `status` / `list` | Registry summary (skills, versions, events, candidates) and the skill list. |
105
106
  | `show <id>` | Frontmatter, version history, and content hashes for one skill. |
106
107
  | `explain <id>` | Provenance chain + audit trail + the exact rollback command. |
107
- | `rollback <id> [--to vN]` | Switch the active version and re-materialize it to the host. |
108
+ | `rollback <id> [--to vN]` | Switch the active version and re-materialize it to the host(s). |
109
+ | `materialize [id] --host claude\|codex\|all` | Distribute active skill(s) to Claude Code and/or Codex (the Codex Target Adapter). |
108
110
  | `doctor` / `doctor --fix` | Integrity check (hashes, active pointer, host sync); `--fix` restores git-recoverable versions and re-materializes drift, then re-verifies. |
109
111
  | `capture` | Append a host event to the redacted WAL — reads hook JSON on stdin, never fails the session. |
110
112
  | `mine` | Surface task families recurring across ≥3 distinct sessions; nudges you once enough new sessions accumulate. |
@@ -161,7 +163,8 @@ super-skill candidate approve <id>
161
163
  | Env var | Default | Purpose |
162
164
  |---|---|---|
163
165
  | `SUPER_SKILL_HOME` | `~/.super-skill` | Registry + control state (a git repo). |
164
- | `SUPER_SKILL_HOST_SKILLS` | `~/.claude/skills` | Skills directory to seed/materialize (set to `~/.agents/skills` for Codex). |
166
+ | `SUPER_SKILL_HOST_SKILLS` | `~/.claude/skills` | Claude Code skills directory (`--host claude`). |
167
+ | `SUPER_SKILL_CODEX_SKILLS` | `~/.agents/skills` | Codex skills directory (`--host codex`). |
165
168
  | `SUPER_SKILL_MINE_REMINDER` | `3` | Distinct unmined sessions before `status` nudges you to mine. |
166
169
 
167
170
  ## Scope
@@ -189,13 +192,14 @@ Redaction runs *before* any write: secret values and private paths never reach t
189
192
  log. Capture is off until you wire it (`super-skill hooks-config`).
190
193
 
191
194
  **Do I need PyPI for the plugin to work?**
192
- The plugin calls the `super-skill` CLI on your PATH. Until the PyPI release,
193
- install the CLI from source: `uv tool install git+https://github.com/sdsrss/super-skill`.
195
+ The plugin calls the `super-skill` CLI on your PATH. Install it from PyPI:
196
+ `uv tool install super-skill-cli` (or `pipx install super-skill-cli`).
194
197
 
195
198
  **Does it support Codex?**
196
- Yes — the same CLI plus a `codex/` install package for `~/.agents/skills`. A Codex
197
- *Target Adapter inside the CLI* is a later item; distributing skills to Codex needs
198
- no extra step since they already live in `~/.agents/skills`.
199
+ Yes — the same CLI plus a `codex/` install package for `~/.agents/skills`. The CLI
200
+ has a Codex Target Adapter: `--host codex` (and `--host all`) on `seed`, `approve`,
201
+ `rollback`, and `materialize` reads from and writes to Codex's `~/.agents/skills`.
202
+ The Codex package also ships an optional `agents/openai.yaml` host extension.
199
203
 
200
204
  ## Develop
201
205
 
@@ -72,8 +72,9 @@ pipx install super-skill-cli
72
72
  codex/install.sh # drops the meta-skill into ~/.agents/skills
73
73
  ```
74
74
 
75
- Point the CLI at the Codex directory with `SUPER_SKILL_HOST_SKILLS=~/.agents/skills`.
76
- See [`codex/README.md`](codex/README.md).
75
+ The CLI speaks Codex natively via `--host codex` — `super-skill seed --host codex`,
76
+ `super-skill materialize --host codex` (or `--host all` for both hosts). See
77
+ [`codex/README.md`](codex/README.md).
77
78
 
78
79
  ## Features
79
80
 
@@ -83,7 +84,8 @@ See [`codex/README.md`](codex/README.md).
83
84
  | `status` / `list` | Registry summary (skills, versions, events, candidates) and the skill list. |
84
85
  | `show <id>` | Frontmatter, version history, and content hashes for one skill. |
85
86
  | `explain <id>` | Provenance chain + audit trail + the exact rollback command. |
86
- | `rollback <id> [--to vN]` | Switch the active version and re-materialize it to the host. |
87
+ | `rollback <id> [--to vN]` | Switch the active version and re-materialize it to the host(s). |
88
+ | `materialize [id] --host claude\|codex\|all` | Distribute active skill(s) to Claude Code and/or Codex (the Codex Target Adapter). |
87
89
  | `doctor` / `doctor --fix` | Integrity check (hashes, active pointer, host sync); `--fix` restores git-recoverable versions and re-materializes drift, then re-verifies. |
88
90
  | `capture` | Append a host event to the redacted WAL — reads hook JSON on stdin, never fails the session. |
89
91
  | `mine` | Surface task families recurring across ≥3 distinct sessions; nudges you once enough new sessions accumulate. |
@@ -140,7 +142,8 @@ super-skill candidate approve <id>
140
142
  | Env var | Default | Purpose |
141
143
  |---|---|---|
142
144
  | `SUPER_SKILL_HOME` | `~/.super-skill` | Registry + control state (a git repo). |
143
- | `SUPER_SKILL_HOST_SKILLS` | `~/.claude/skills` | Skills directory to seed/materialize (set to `~/.agents/skills` for Codex). |
145
+ | `SUPER_SKILL_HOST_SKILLS` | `~/.claude/skills` | Claude Code skills directory (`--host claude`). |
146
+ | `SUPER_SKILL_CODEX_SKILLS` | `~/.agents/skills` | Codex skills directory (`--host codex`). |
144
147
  | `SUPER_SKILL_MINE_REMINDER` | `3` | Distinct unmined sessions before `status` nudges you to mine. |
145
148
 
146
149
  ## Scope
@@ -168,13 +171,14 @@ Redaction runs *before* any write: secret values and private paths never reach t
168
171
  log. Capture is off until you wire it (`super-skill hooks-config`).
169
172
 
170
173
  **Do I need PyPI for the plugin to work?**
171
- The plugin calls the `super-skill` CLI on your PATH. Until the PyPI release,
172
- install the CLI from source: `uv tool install git+https://github.com/sdsrss/super-skill`.
174
+ The plugin calls the `super-skill` CLI on your PATH. Install it from PyPI:
175
+ `uv tool install super-skill-cli` (or `pipx install super-skill-cli`).
173
176
 
174
177
  **Does it support Codex?**
175
- Yes — the same CLI plus a `codex/` install package for `~/.agents/skills`. A Codex
176
- *Target Adapter inside the CLI* is a later item; distributing skills to Codex needs
177
- no extra step since they already live in `~/.agents/skills`.
178
+ Yes — the same CLI plus a `codex/` install package for `~/.agents/skills`. The CLI
179
+ has a Codex Target Adapter: `--host codex` (and `--host all`) on `seed`, `approve`,
180
+ `rollback`, and `materialize` reads from and writes to Codex's `~/.agents/skills`.
181
+ The Codex package also ships an optional `agents/openai.yaml` host extension.
178
182
 
179
183
  ## Develop
180
184
 
@@ -59,7 +59,8 @@ pipx install super-skill-cli
59
59
  codex/install.sh # 把元技能装进 ~/.agents/skills
60
60
  ```
61
61
 
62
- `SUPER_SKILL_HOST_SKILLS=~/.agents/skills` CLI 指向 Codex 目录。详见
62
+ CLI 原生支持 Codex——`--host codex`:`super-skill seed --host codex`、
63
+ `super-skill materialize --host codex`(或 `--host all` 同时分发两个宿主)。详见
63
64
  [`codex/README.md`](codex/README.md)。
64
65
 
65
66
  ## 功能
@@ -71,6 +72,7 @@ codex/install.sh # 把元技能装进 ~/.agents/skills
71
72
  | `show <id>` | 某技能的 frontmatter、版本历史与内容哈希。 |
72
73
  | `explain <id>` | 来源链 + 审计记录 + 精确回滚命令。 |
73
74
  | `rollback <id> [--to vN]` | 切换活动版本并重新落地到宿主。 |
75
+ | `materialize [id] --host claude\|codex\|all` | 把活动技能分发到 Claude Code 与/或 Codex(Codex Target Adapter)。 |
74
76
  | `doctor` / `doctor --fix` | 完整性校验(哈希、活动指针、宿主同步);`--fix` 从 git 恢复版本、重落地漂移,再复验。 |
75
77
  | `capture` | 把一条宿主事件追加进脱敏 WAL——从 stdin 读 hook JSON,绝不让会话失败。 |
76
78
  | `mine` | 挖掘跨 ≥3 个去重会话复现的任务家族;攒够新会话时提醒你挖掘。 |
@@ -124,7 +126,8 @@ super-skill candidate approve <id>
124
126
  | 环境变量 | 默认 | 用途 |
125
127
  |---|---|---|
126
128
  | `SUPER_SKILL_HOME` | `~/.super-skill` | 注册表 + 控制状态(git 仓库)。 |
127
- | `SUPER_SKILL_HOST_SKILLS` | `~/.claude/skills` | seed/落地的技能目录(Codex 设为 `~/.agents/skills`)。 |
129
+ | `SUPER_SKILL_HOST_SKILLS` | `~/.claude/skills` | Claude Code 技能目录(`--host claude`)。 |
130
+ | `SUPER_SKILL_CODEX_SKILLS` | `~/.agents/skills` | Codex 技能目录(`--host codex`)。 |
128
131
  | `SUPER_SKILL_MINE_REMINDER` | `3` | `status` 提醒挖掘前的去重未挖掘会话数阈值。 |
129
132
 
130
133
  ## 范围
@@ -146,12 +149,13 @@ super-skill 刻意停在**包管理器**形态(里程碑 M0 + WS)。自学习闭
146
149
  脱敏在*任何写入之前*运行:密钥值与私有路径永不进日志。捕获默认关闭,需你接线(`super-skill hooks-config`)。
147
150
 
148
151
  **插件必须依赖 PyPI 才能用吗?**
149
- 插件调用 PATH 上的 `super-skill` CLIPyPI 发布前,从源码装 CLI:
150
- `uv tool install git+https://github.com/sdsrss/super-skill`。
152
+ 插件调用 PATH 上的 `super-skill` CLI。从 PyPI 安装:
153
+ `uv tool install super-skill-cli`(或 `pipx install super-skill-cli`)。
151
154
 
152
155
  **支持 Codex 吗?**
153
- 支持——同一个 CLI 加一个面向 `~/.agents/skills` 的 `codex/` 安装包。CLI *内部的* Codex Target
154
- Adapter 是后续项;把技能分发给 Codex 无需额外步骤,因为它们本就在 `~/.agents/skills`。
156
+ 支持——同一个 CLI 加一个面向 `~/.agents/skills` 的 `codex/` 安装包。CLI 已内置 Codex Target
157
+ Adapter:`seed`、`approve`、`rollback`、`materialize` `--host codex`(及 `--host all`)会从
158
+ Codex 的 `~/.agents/skills` 读取并写入。Codex 包还附带一个可选的 `agents/openai.yaml` 宿主扩展。
155
159
 
156
160
  ## 开发
157
161
 
@@ -0,0 +1,43 @@
1
+ # super-skill for Codex
2
+
3
+ Codex adopted the [Agent Skills](https://agentskills.io) open standard: it reads
4
+ `SKILL.md` from `~/.agents/skills` (user-level) and `.agents/skills` (repo-level).
5
+ There is no marketplace/plugin install like Claude Code — a skill is just its
6
+ `SKILL.md` placed in the skills directory. This package is that skill plus a
7
+ one-line installer.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ # 1. Install the host-agnostic CLI (the command stays `super-skill`)
13
+ pipx install super-skill-cli # or: uv tool install super-skill-cli
14
+
15
+ # 2. Install the meta-skill into ~/.agents/skills (idempotent)
16
+ codex/install.sh
17
+ ```
18
+
19
+ `install.sh` copies `skills/super-skill/SKILL.md` into
20
+ `~/.agents/skills/super-skill/`. Re-running it is safe.
21
+
22
+ ## Use
23
+
24
+ super-skill manages the skills in your skills directory (version, explain,
25
+ rollback, integrity `doctor`, opportunity `mine`). The CLI has a **Codex Target
26
+ Adapter** — use `--host codex` (or `--host all`) to read from and write to Codex's
27
+ `~/.agents/skills`:
28
+
29
+ ```bash
30
+ super-skill seed --host codex # import from ~/.agents/skills (read-only)
31
+ super-skill materialize --host codex # distribute active skills to Codex
32
+ super-skill materialize <id> --host all # push one skill to both hosts
33
+ ```
34
+
35
+ `~/.agents/skills` is super-skill's canonical Codex source — Codex reads promoted
36
+ skills there directly (zero-copy). Override the path with `SUPER_SKILL_CODEX_SKILLS`.
37
+
38
+ ## `agents/openai.yaml`
39
+
40
+ This package ships an optional `agents/openai.yaml` host extension (installed
41
+ alongside `SKILL.md`) with Codex UI + invocation-policy hints (`interface`,
42
+ `policy`). Only the open-standard `SKILL.md` is required; edit or remove the YAML
43
+ per your current Codex version's docs.
@@ -14,8 +14,9 @@ if [ ! -f "${SRC}/SKILL.md" ]; then
14
14
  fi
15
15
 
16
16
  mkdir -p "${DEST}"
17
- cp "${SRC}/SKILL.md" "${DEST}/SKILL.md"
18
- echo "installed super-skill meta-skill -> ${DEST}/SKILL.md"
17
+ # Copy the whole skill tree: SKILL.md + optional agents/openai.yaml (host extension).
18
+ cp -R "${SRC}/." "${DEST}/"
19
+ echo "installed super-skill meta-skill -> ${DEST}/ (SKILL.md + agents/openai.yaml)"
19
20
 
20
21
  if ! command -v super-skill >/dev/null 2>&1; then
21
22
  echo "note: the 'super-skill' CLI is not on PATH — install it with:" >&2
@@ -0,0 +1,12 @@
1
+ # Codex host-extension metadata (OPTIONAL). Only SKILL.md is required; this file
2
+ # adds Codex-specific UI + invocation hints. Schema per the Codex build-skills
3
+ # docs (learn.chatgpt.com/docs/build-skills): interface / policy / dependencies.
4
+ # Kept to the fields super-skill actually needs — a CLI-driven manager, not an
5
+ # MCP tool, so no dependencies block.
6
+ interface:
7
+ display_name: super-skill
8
+ short_description: Version, roll back, and audit your Agent Skills.
9
+ policy:
10
+ # true = Codex may auto-select this skill from the user's prompt;
11
+ # false would require an explicit $super-skill invocation.
12
+ allow_implicit_invocation: true
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "super-skill-cli"
3
- version = "0.9.2"
3
+ version = "0.10.0"
4
4
  description = "Personal Agent-Skill package manager: versioned registry, seed import, explain, rollback (M0+WS scope)."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -37,19 +37,54 @@ def _short(text: str, n: int = 60) -> str:
37
37
 
38
38
 
39
39
  @app.command()
40
- def seed() -> None:
40
+ def seed(host: str = typer.Option("claude", "--host", help="source host: claude | codex")) -> None:
41
41
  """Import existing host skills into the registry (idempotent, read-only on host)."""
42
+ if host not in config.HOSTS:
43
+ typer.echo(f"unknown host {host!r} (expected: {', '.join(config.HOSTS)})", err=True)
44
+ raise typer.Exit(1)
42
45
  reg = _registry()
43
- report = seed_from_host(reg, config.host_skills_dir())
46
+ src = config.host_skills_dir(host)
47
+ report = seed_from_host(reg, src)
44
48
  typer.echo(
45
49
  f"seed: {len(report.imported)} imported, {len(report.updated)} updated, "
46
50
  f"{len(report.unchanged)} unchanged, {len(report.skipped)} skipped "
47
- f"(host={config.host_skills_dir()})"
51
+ f"(host={src})"
48
52
  )
49
53
  for name, reason in report.skipped:
50
54
  typer.echo(f" skipped {name}: {reason}")
51
55
 
52
56
 
57
+ @app.command()
58
+ def materialize(
59
+ skill_id: str = typer.Argument("", help="skill to distribute; empty = all active skills"),
60
+ host: str = typer.Option("claude", "--host", help="target host: claude | codex | all"),
61
+ ) -> None:
62
+ """Distribute active skill(s) to a host skills dir — Claude Code and/or Codex (FR-PUB-2)."""
63
+ reg = _registry()
64
+ try:
65
+ hosts = config.resolve_hosts(host)
66
+ except ValueError as e:
67
+ typer.echo(str(e), err=True)
68
+ raise typer.Exit(1) from e
69
+ ids = [skill_id] if skill_id else [
70
+ r.skill.skill_id for r in reg.list_skills() if r.skill.active_version
71
+ ]
72
+ if not ids:
73
+ typer.echo("no active skills to materialize")
74
+ return
75
+ failed = False
76
+ for sid in ids:
77
+ for h in hosts:
78
+ try:
79
+ dest = reg.materialize(sid, config.host_skills_dir(h))
80
+ typer.echo(f"{sid} -> {h}: {dest}")
81
+ except RegistryError as e:
82
+ typer.echo(f"{sid} -> {h}: {e}", err=True)
83
+ failed = True
84
+ if failed:
85
+ raise typer.Exit(1)
86
+
87
+
53
88
  @app.command()
54
89
  def capture(
55
90
  event_type: str = typer.Option("", "--event-type", help="override hook_event_name"),
@@ -189,9 +224,15 @@ def rollback(
189
224
  skill_id: str,
190
225
  to: str = typer.Option("", "--to", help="target version; default = previous"),
191
226
  reason: str = typer.Option("", "--reason"),
227
+ host: str = typer.Option("claude", "--host", help="re-materialize to: claude | codex | all"),
192
228
  ) -> None:
193
- """Switch the active pointer to an older version and re-materialize to the host."""
229
+ """Switch the active pointer to an older version and re-materialize to the host(s)."""
194
230
  reg = _registry()
231
+ try:
232
+ hosts = config.resolve_hosts(host)
233
+ except ValueError as e:
234
+ typer.echo(str(e), err=True)
235
+ raise typer.Exit(1) from e
195
236
  rec = reg.get(skill_id)
196
237
  if rec is None:
197
238
  typer.echo(f"unknown skill: {skill_id}", err=True)
@@ -205,11 +246,11 @@ def rollback(
205
246
  to = versions[idx - 1]
206
247
  try:
207
248
  reg.set_active(skill_id, to, op=OperationType.ROLLBACK, reason=reason or None)
208
- dest = reg.materialize(skill_id, config.host_skills_dir())
249
+ dests = [reg.materialize(skill_id, config.host_skills_dir(h)) for h in hosts]
209
250
  except RegistryError as e:
210
251
  typer.echo(str(e), err=True)
211
252
  raise typer.Exit(1) from e
212
- typer.echo(f"rolled back {skill_id} -> {to}; materialized {dest}")
253
+ typer.echo(f"rolled back {skill_id} -> {to}; materialized {', '.join(str(d) for d in dests)}")
213
254
 
214
255
 
215
256
  @app.command()
@@ -338,12 +379,21 @@ def candidate_show(candidate_id: str) -> None:
338
379
  def candidate_approve(
339
380
  candidate_id: str,
340
381
  reason: str = typer.Option("", "--reason"),
382
+ host: str = typer.Option("claude", "--host", help="materialize to: claude | codex | all"),
341
383
  ) -> None:
342
- """Approve a candidate: promote to the registry and materialize to the host."""
384
+ """Approve a candidate: promote to the registry and materialize to the host(s)."""
343
385
  store = CandidateStore(config.state_root())
344
386
  reg = _registry()
345
387
  try:
346
- sv = approve(store, reg, candidate_id, config.host_skills_dir(), reason=reason or None)
388
+ hosts = config.resolve_hosts(host)
389
+ except ValueError as e:
390
+ typer.echo(str(e), err=True)
391
+ raise typer.Exit(1) from e
392
+ try:
393
+ sv = approve(store, reg, candidate_id, config.host_skills_dir(hosts[0]),
394
+ reason=reason or None)
395
+ for extra in hosts[1:]:
396
+ reg.materialize(sv.skill_id, config.host_skills_dir(extra))
347
397
  except InstructionGateError as e:
348
398
  typer.echo(str(e), err=True)
349
399
  for f in e.findings:
@@ -359,9 +409,9 @@ def candidate_approve(
359
409
  except (CandidateError, RegistryError, SkillMdError) as e:
360
410
  typer.echo(str(e), err=True)
361
411
  raise typer.Exit(1) from e
412
+ dests = ", ".join(str(config.host_skills_dir(h) / sv.skill_id) for h in hosts)
362
413
  typer.echo(
363
- f"approved {candidate_id} -> {sv.skill_id}@{sv.version}; "
364
- f"materialized to {config.host_skills_dir() / sv.skill_id}"
414
+ f"approved {candidate_id} -> {sv.skill_id}@{sv.version}; materialized to {dests}"
365
415
  )
366
416
 
367
417
 
@@ -0,0 +1,44 @@
1
+ """Path resolution. All roots are env-overridable so tests never touch the real
2
+ ~/.super-skill state or the host's ~/.claude/skills directory."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import os
7
+ from pathlib import Path
8
+
9
+
10
+ def state_root() -> Path:
11
+ """Registry + control state (git-backed in WS). docs/02 §4.1."""
12
+ return Path(os.environ.get("SUPER_SKILL_HOME", "~/.super-skill")).expanduser()
13
+
14
+
15
+ # Host distribution targets (docs/01 FR-PUB-2). Claude Code is the v1 default;
16
+ # Codex reads the open-standard ~/.agents/skills directly (docs/05 ADR-008).
17
+ HOSTS = ("claude", "codex")
18
+
19
+
20
+ def host_skills_dir(host: str = "claude") -> Path:
21
+ """Skills directory for a host distribution target (env-overridable).
22
+
23
+ claude -> ~/.claude/skills (SUPER_SKILL_HOST_SKILLS);
24
+ codex -> ~/.agents/skills (SUPER_SKILL_CODEX_SKILLS)."""
25
+ if host == "codex":
26
+ return Path(os.environ.get("SUPER_SKILL_CODEX_SKILLS", "~/.agents/skills")).expanduser()
27
+ return Path(os.environ.get("SUPER_SKILL_HOST_SKILLS", "~/.claude/skills")).expanduser()
28
+
29
+
30
+ def resolve_hosts(host: str) -> list[str]:
31
+ """Expand a --host selector (claude | codex | all) to concrete host names."""
32
+ if host == "all":
33
+ return list(HOSTS)
34
+ if host not in HOSTS:
35
+ raise ValueError(f"unknown host {host!r} (expected one of: {', '.join(HOSTS)}, all)")
36
+ return [host]
37
+
38
+
39
+ def registry_dir() -> Path:
40
+ return state_root() / "registry"
41
+
42
+
43
+ def skills_dir() -> Path:
44
+ return registry_dir() / "skills"
@@ -52,6 +52,8 @@ def test_install_script_installs_into_sandbox_home():
52
52
  installed = Path(tmp) / ".agents/skills/super-skill/SKILL.md"
53
53
  assert installed.exists()
54
54
  assert "name: super-skill" in installed.read_text(encoding="utf-8")
55
+ # the host-extension travels with the skill
56
+ assert (Path(tmp) / ".agents/skills/super-skill/agents/openai.yaml").exists()
55
57
  # idempotent: a second run still succeeds
56
58
  r2 = subprocess.run(["bash", str(sh)], env=env, capture_output=True, text=True)
57
59
  assert r2.returncode == 0, r2.stderr
@@ -0,0 +1,99 @@
1
+ """Codex Target Adapter (docs/01 FR-PUB-2): the CLI can resolve and distribute
2
+ active skills to more than one host — Claude Code (~/.claude/skills) and Codex
3
+ (~/.agents/skills) — via a --host selector, without disturbing the single-host
4
+ default behavior.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import pytest
10
+ from typer.testing import CliRunner
11
+
12
+ from super_skill import config
13
+ from super_skill.cli import app
14
+
15
+ runner = CliRunner()
16
+
17
+
18
+ def test_host_skills_dir_resolves_per_host(monkeypatch):
19
+ monkeypatch.delenv("SUPER_SKILL_HOST_SKILLS", raising=False)
20
+ monkeypatch.delenv("SUPER_SKILL_CODEX_SKILLS", raising=False)
21
+ assert config.host_skills_dir().name == "skills"
22
+ assert str(config.host_skills_dir("claude")).endswith(".claude/skills")
23
+ assert str(config.host_skills_dir("codex")).endswith(".agents/skills")
24
+
25
+
26
+ def test_host_skills_dir_env_overrides(monkeypatch, tmp_path):
27
+ monkeypatch.setenv("SUPER_SKILL_CODEX_SKILLS", str(tmp_path / "cdx"))
28
+ assert config.host_skills_dir("codex") == tmp_path / "cdx"
29
+
30
+
31
+ def test_resolve_hosts():
32
+ assert config.resolve_hosts("claude") == ["claude"]
33
+ assert config.resolve_hosts("codex") == ["codex"]
34
+ assert config.resolve_hosts("all") == ["claude", "codex"]
35
+ with pytest.raises(ValueError):
36
+ config.resolve_hosts("nope")
37
+
38
+
39
+ @pytest.fixture
40
+ def env(tmp_path, monkeypatch):
41
+ claude = tmp_path / "claude"
42
+ codex = tmp_path / "codex"
43
+ claude.mkdir()
44
+ monkeypatch.setenv("SUPER_SKILL_HOME", str(tmp_path / "state"))
45
+ monkeypatch.setenv("SUPER_SKILL_HOST_SKILLS", str(claude))
46
+ monkeypatch.setenv("SUPER_SKILL_CODEX_SKILLS", str(codex))
47
+ return claude, codex
48
+
49
+
50
+ def _seed_one(claude):
51
+ d = claude / "alpha"
52
+ d.mkdir(parents=True)
53
+ (d / "SKILL.md").write_text("---\nname: alpha\ndescription: a skill\n---\nbody\n")
54
+ assert runner.invoke(app, ["seed"]).exit_code == 0
55
+
56
+
57
+ def test_materialize_to_codex_host(env):
58
+ claude, codex = env
59
+ _seed_one(claude)
60
+ r = runner.invoke(app, ["materialize", "alpha", "--host", "codex"])
61
+ assert r.exit_code == 0, r.output
62
+ assert (codex / "alpha" / "SKILL.md").exists()
63
+
64
+
65
+ def test_materialize_all_hosts_all_skills(env):
66
+ claude, codex = env
67
+ _seed_one(claude)
68
+ # no skill_id -> all active skills; --host all -> both dirs
69
+ r = runner.invoke(app, ["materialize", "--host", "all"])
70
+ assert r.exit_code == 0, r.output
71
+ assert (claude / "alpha" / "SKILL.md").exists()
72
+ assert (codex / "alpha" / "SKILL.md").exists()
73
+
74
+
75
+ def test_seed_reads_from_codex_host(env):
76
+ _, codex = env
77
+ d = codex / "beta"
78
+ d.mkdir(parents=True)
79
+ (d / "SKILL.md").write_text("---\nname: beta\ndescription: from codex\n---\nx\n")
80
+ r = runner.invoke(app, ["seed", "--host", "codex"])
81
+ assert r.exit_code == 0, r.output
82
+ r = runner.invoke(app, ["list"])
83
+ assert "beta" in r.output
84
+
85
+
86
+ def test_bad_host_exits_1(env):
87
+ r = runner.invoke(app, ["materialize", "--host", "bogus"])
88
+ assert r.exit_code == 1
89
+
90
+
91
+ def test_openai_yaml_shipped_and_valid():
92
+ from pathlib import Path
93
+
94
+ import yaml
95
+ p = Path(__file__).resolve().parent.parent / "codex/skills/super-skill/agents/openai.yaml"
96
+ data = yaml.safe_load(p.read_text(encoding="utf-8"))
97
+ assert "interface" in data
98
+ assert data["interface"]["display_name"]
99
+ assert data["policy"]["allow_implicit_invocation"] is True
@@ -457,7 +457,7 @@ wheels = [
457
457
 
458
458
  [[package]]
459
459
  name = "super-skill-cli"
460
- version = "0.9.2"
460
+ version = "0.10.0"
461
461
  source = { editable = "." }
462
462
  dependencies = [
463
463
  { name = "pydantic" },
@@ -1,43 +0,0 @@
1
- # super-skill for Codex
2
-
3
- Codex adopted the [Agent Skills](https://agentskills.io) open standard: it reads
4
- `SKILL.md` from `~/.agents/skills` (user-level) and `.agents/skills` (repo-level).
5
- There is no marketplace/plugin install like Claude Code — a skill is just its
6
- `SKILL.md` placed in the skills directory. This package is that skill plus a
7
- one-line installer.
8
-
9
- ## Install
10
-
11
- ```bash
12
- # 1. Install the host-agnostic CLI (the command stays `super-skill`)
13
- pipx install super-skill-cli # or: uv tool install super-skill-cli
14
-
15
- # 2. Install the meta-skill into ~/.agents/skills (idempotent)
16
- codex/install.sh
17
- ```
18
-
19
- `install.sh` copies `skills/super-skill/SKILL.md` into
20
- `~/.agents/skills/super-skill/`. Re-running it is safe.
21
-
22
- ## Use
23
-
24
- super-skill manages the skills in your skills directory (version, explain,
25
- rollback, integrity `doctor`, opportunity `mine`). Point it at the Codex dir:
26
-
27
- ```bash
28
- SUPER_SKILL_HOST_SKILLS=~/.agents/skills super-skill seed # import, read-only
29
- SUPER_SKILL_HOST_SKILLS=~/.agents/skills super-skill status
30
- ```
31
-
32
- Since `~/.agents/skills` is super-skill's canonical source, Codex reads promoted
33
- skills there directly — zero-copy.
34
-
35
- ## Not included
36
-
37
- - `agents/openai.yaml` (Codex host-extension metadata) is **optional** and its
38
- exact schema is Codex-version-specific — add one per the current Codex docs if
39
- you want custom UI metadata / invocation policy. This package intentionally
40
- ships only the open-standard `SKILL.md`, which every Codex version reads.
41
- - Distributing super-skill's *produced* skills to Codex needs no extra step
42
- (they live in `~/.agents/skills` already). A dedicated Codex Target Adapter in
43
- the CLI (docs/01 FR-PUB-2) remains a P1 item.
@@ -1,25 +0,0 @@
1
- """Path resolution. All roots are env-overridable so tests never touch the real
2
- ~/.super-skill state or the host's ~/.claude/skills directory."""
3
-
4
- from __future__ import annotations
5
-
6
- import os
7
- from pathlib import Path
8
-
9
-
10
- def state_root() -> Path:
11
- """Registry + control state (git-backed in WS). docs/02 §4.1."""
12
- return Path(os.environ.get("SUPER_SKILL_HOME", "~/.super-skill")).expanduser()
13
-
14
-
15
- def host_skills_dir() -> Path:
16
- """Claude Code personal skills dir — v1 direct distribution target (R-SCOPE-3)."""
17
- return Path(os.environ.get("SUPER_SKILL_HOST_SKILLS", "~/.claude/skills")).expanduser()
18
-
19
-
20
- def registry_dir() -> Path:
21
- return state_root() / "registry"
22
-
23
-
24
- def skills_dir() -> Path:
25
- return registry_dir() / "skills"