🔧 feat(skills): install to agents home
This commit is contained in:
parent
8b75747587
commit
872c1afc24
14
SKILLS.md
14
SKILLS.md
|
|
@ -4,8 +4,8 @@
|
||||||
并给出与本 Playbook(`docs/` + `rulesets/`)配套的技能编写建议与内置技能清单。
|
并给出与本 Playbook(`docs/` + `rulesets/`)配套的技能编写建议与内置技能清单。
|
||||||
|
|
||||||
> 提示:Codex skills 是“按用户安装”的(默认在
|
> 提示:Codex skills 是“按用户安装”的(默认在
|
||||||
> `~/.codex/skills`)。本仓库将 skills 以可分发的形式放在
|
> `~/.agents/skills`)。本仓库将 skills 以可分发的形式放在
|
||||||
> `codex/skills/`,并提供脚本一键安装到你的 `CODEX_HOME`。
|
> `codex/skills/`,并提供脚本一键安装到你的 `~/.agents`。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -38,14 +38,14 @@ codex/skills/
|
||||||
最终安装到本机后,对应路径为:
|
最终安装到本机后,对应路径为:
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
$CODEX_HOME/skills/<skill-name>/SKILL.md
|
~/.agents/skills/<skill-name>/SKILL.md
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. 安装到本机(推荐)
|
## 3. 安装到本机(推荐)
|
||||||
|
|
||||||
使用统一入口 `playbook.py` 安装 skills(会把 `codex/skills/*` 复制到 `$CODEX_HOME/skills/`):
|
使用统一入口 `playbook.py` 安装 skills(会把 `codex/skills/*` 复制到 `~/.agents/skills/`):
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
# playbook.toml
|
# playbook.toml
|
||||||
|
|
@ -54,7 +54,7 @@ project_root = "."
|
||||||
|
|
||||||
[install_skills]
|
[install_skills]
|
||||||
mode = "all" # list|all
|
mode = "all" # list|all
|
||||||
codex_home = "~/.codex"
|
agents_home = "~/.agents"
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -74,10 +74,10 @@ skills = ["style-cleanup", "commit-message"]
|
||||||
```toml
|
```toml
|
||||||
[install_skills]
|
[install_skills]
|
||||||
mode = "all"
|
mode = "all"
|
||||||
codex_home = "./.codex"
|
agents_home = "./.agents"
|
||||||
```
|
```
|
||||||
|
|
||||||
> 注意:Codex 只会从 `CODEX_HOME` 加载 skills;使用本地安装时,启动 Codex 需设置同样的 `CODEX_HOME`。
|
> 注意:Codex 默认从 `~/.agents/skills` 加载 skills;使用本地安装时,需要确保 Codex 能发现该路径。
|
||||||
|
|
||||||
如果你的项目通过 `git subtree` vendoring 本 Playbook(推荐前缀
|
如果你的项目通过 `git subtree` vendoring 本 Playbook(推荐前缀
|
||||||
`docs/standards/playbook`),则在目标项目里执行:
|
`docs/standards/playbook`),则在目标项目里执行:
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ description: Use when creating new skills, editing existing skills, or verifying
|
||||||
|
|
||||||
**Writing skills IS Test-Driven Development applied to process documentation.**
|
**Writing skills IS Test-Driven Development applied to process documentation.**
|
||||||
|
|
||||||
**Personal skills live in agent-specific directories (`~/.claude/skills` for Claude Code, `~/.codex/skills` for Codex)**
|
**Personal skills live in agent-specific directories (`~/.claude/skills` for Claude Code, `~/.agents/skills` for Codex)**
|
||||||
|
|
||||||
You write test cases (pressure scenarios with subagents), watch them fail (baseline behavior), write the skill (documentation), watch tests pass (agents comply), and refactor (close loopholes).
|
You write test cases (pressure scenarios with subagents), watch them fail (baseline behavior), write the skill (documentation), watch tests pass (agents comply), and refactor (close loopholes).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
[sync_rules]
|
[sync_rules]
|
||||||
# 同步 AGENT_RULES.md(配置节存在即启用)
|
# 同步 AGENT_RULES.md(配置节存在即启用)
|
||||||
# force = false # 可选:覆盖已有文件
|
# force = false # 可选:覆盖已有文件
|
||||||
|
# no_backup = false # 可选:跳过备份
|
||||||
|
|
||||||
[sync_memory_bank]
|
[sync_memory_bank]
|
||||||
# 同步 memory-bank/(配置节存在即启用)
|
# 同步 memory-bank/(配置节存在即启用)
|
||||||
|
|
@ -32,11 +33,12 @@
|
||||||
[sync_standards]
|
[sync_standards]
|
||||||
# langs = ["tsl", "cpp"] # 必填:要同步的语言
|
# langs = ["tsl", "cpp"] # 必填:要同步的语言
|
||||||
# gitattr_mode = "append" # append(补全缺失)|overwrite(覆盖)|block(插入块)|skip(跳过)
|
# gitattr_mode = "append" # append(补全缺失)|overwrite(覆盖)|block(插入块)|skip(跳过)
|
||||||
|
# no_backup = false # 可选:跳过备份(.agents/.gitattributes)
|
||||||
|
|
||||||
[install_skills]
|
[install_skills]
|
||||||
# mode = "list" # list|all
|
# mode = "list" # list|all
|
||||||
# skills = ["brainstorming"] # mode=list 时必填
|
# skills = ["brainstorming"] # mode=list 时必填
|
||||||
# codex_home = "~/.codex" # 可选:默认 ~/.codex
|
# agents_home = "~/.agents" # 可选:默认 ~/.agents
|
||||||
|
|
||||||
[format_md]
|
[format_md]
|
||||||
# tool = "prettier" # 仅支持 prettier
|
# tool = "prettier" # 仅支持 prettier
|
||||||
|
|
|
||||||
|
|
@ -1056,16 +1056,19 @@ def normalize_globs(raw: object) -> list[str]:
|
||||||
|
|
||||||
def install_skills_action(config: dict, context: dict) -> int:
|
def install_skills_action(config: dict, context: dict) -> int:
|
||||||
mode = str(config.get("mode", "list")).lower()
|
mode = str(config.get("mode", "list")).lower()
|
||||||
codex_home = Path(config.get("codex_home", "~/.codex")).expanduser()
|
if "codex_home" in config:
|
||||||
if not codex_home.is_absolute():
|
print("ERROR: codex_home is no longer supported; use agents_home", file=sys.stderr)
|
||||||
codex_home = (context["project_root"] / codex_home).resolve()
|
return 2
|
||||||
|
agents_home = Path(config.get("agents_home", "~/.agents")).expanduser()
|
||||||
|
if not agents_home.is_absolute():
|
||||||
|
agents_home = (context["project_root"] / agents_home).resolve()
|
||||||
|
|
||||||
skills_src_root = PLAYBOOK_ROOT / "codex/skills"
|
skills_src_root = PLAYBOOK_ROOT / "codex/skills"
|
||||||
if not skills_src_root.is_dir():
|
if not skills_src_root.is_dir():
|
||||||
print(f"ERROR: skills source not found: {skills_src_root}", file=sys.stderr)
|
print(f"ERROR: skills source not found: {skills_src_root}", file=sys.stderr)
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
skills_dst_root = codex_home / "skills"
|
skills_dst_root = agents_home / "skills"
|
||||||
ensure_dir(skills_dst_root)
|
ensure_dir(skills_dst_root)
|
||||||
|
|
||||||
if mode == "all":
|
if mode == "all":
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,27 @@ langs = ["tsl"]
|
||||||
self.assertEqual(block[bullet_idx - 1], "")
|
self.assertEqual(block[bullet_idx - 1], "")
|
||||||
|
|
||||||
def test_install_skills(self):
|
def test_install_skills(self):
|
||||||
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||||
|
target = Path(tmp_dir) / "agents"
|
||||||
|
config_body = f"""
|
||||||
|
[playbook]
|
||||||
|
project_root = "{tmp_dir}"
|
||||||
|
|
||||||
|
[install_skills]
|
||||||
|
agents_home = "{target}"
|
||||||
|
mode = "list"
|
||||||
|
skills = ["brainstorming"]
|
||||||
|
"""
|
||||||
|
config_path = Path(tmp_dir) / "playbook.toml"
|
||||||
|
config_path.write_text(config_body, encoding="utf-8")
|
||||||
|
|
||||||
|
result = run_cli("-config", str(config_path))
|
||||||
|
|
||||||
|
skill_file = target / "skills/brainstorming/SKILL.md"
|
||||||
|
self.assertEqual(result.returncode, 0)
|
||||||
|
self.assertTrue(skill_file.is_file())
|
||||||
|
|
||||||
|
def test_install_skills_rejects_codex_home(self):
|
||||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||||
target = Path(tmp_dir) / "codex"
|
target = Path(tmp_dir) / "codex"
|
||||||
config_body = f"""
|
config_body = f"""
|
||||||
|
|
@ -142,9 +163,8 @@ skills = ["brainstorming"]
|
||||||
|
|
||||||
result = run_cli("-config", str(config_path))
|
result = run_cli("-config", str(config_path))
|
||||||
|
|
||||||
skill_file = target / "skills/brainstorming/SKILL.md"
|
self.assertNotEqual(result.returncode, 0)
|
||||||
self.assertEqual(result.returncode, 0)
|
self.assertIn("codex_home", result.stdout + result.stderr)
|
||||||
self.assertTrue(skill_file.is_file())
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue