fix(install): link skills where codex looks
Codex 0.148 discovers skills under $CODEX_HOME/skills only, so every skill in this repo was invisible to codex sessions — review sessions run by a codex reviewer reported review-pr as an unavailable skill and fell back to improvising a review. Both installers now link each skill into ~/.codex/skills as well. The nix module links one symlink per skill dir instead of recursive=true: codex skips any skill whose SKILL.md is itself a symlink, which is what a per-file link produces.
This commit is contained in:
@@ -17,7 +17,7 @@ nix/home.nix # home-manager module for NixOS machines
|
|||||||
flake.nix # exposes homeModules.default
|
flake.nix # exposes homeModules.default
|
||||||
```
|
```
|
||||||
|
|
||||||
Skills are portable: only `name`+`description` frontmatter is required by any of the tools; Claude-only fields (`user-invocable`, `args`) are ignored elsewhere. Claude Code reads them from `~/.claude/skills`, Codex and Pi from `~/.agents/skills`, and opencode auto-loads both — so the two links cover all four. Cross-skill refs use root-relative paths (`tracker-common/COMMON.md`), so they resolve under either root.
|
Skills are portable: only `name`+`description` frontmatter is required by any of the tools; Claude-only fields (`user-invocable`, `args`) are ignored elsewhere. Claude Code reads them from `~/.claude/skills`, Pi from `~/.agents/skills`, Codex from `~/.codex/skills` (and only there — `~/.agents/skills` is invisible to it), and opencode auto-loads the first two. Cross-skill refs use root-relative paths (`tracker-common/COMMON.md`), so they resolve under either root.
|
||||||
|
|
||||||
Context files differ: Claude Code and Codex support `@file` imports, so their entry files import the shared fragments by path. Pi and opencode do not, so each gets a single `AGENTS.md` generated by concatenating the same fragments — on NixOS the home-manager module builds it in the store, elsewhere `bin/link.sh` writes it (idempotent; set `MACHINE=name` to pick a `claude-md/machines/` profile, default is `default`).
|
Context files differ: Claude Code and Codex support `@file` imports, so their entry files import the shared fragments by path. Pi and opencode do not, so each gets a single `AGENTS.md` generated by concatenating the same fragments — on NixOS the home-manager module builds it in the store, elsewhere `bin/link.sh` writes it (idempotent; set `MACHINE=name` to pick a `claude-md/machines/` profile, default is `default`).
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ git clone https://git.naps.pt/yolo/agent-skills.git ~/tea/agent-skills
|
|||||||
~/tea/agent-skills/bin/link.sh
|
~/tea/agent-skills/bin/link.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Symlinks each skill into `~/.claude/skills/` and `~/.agents/skills/`, commands into `~/.claude/commands/` and `~/.config/opencode/commands/`, hooks into `~/.claude/hooks/`, `claude-md/` fragments into `~/.claude/`, and generates `~/.pi/agent/AGENTS.md` and `~/.config/opencode/AGENTS.md` from the fragments. Idempotent; any pre-existing real dir (or non-generated AGENTS.md) is moved to `~/.agent-skills-backup/` (outside the discovery path, so it isn't picked up as a duplicate skill). Re-run after adding a skill.
|
Symlinks each skill into `~/.claude/skills/`, `~/.agents/skills/` and `~/.codex/skills/`, commands into `~/.claude/commands/` and `~/.config/opencode/commands/`, hooks into `~/.claude/hooks/`, `claude-md/` fragments into `~/.claude/`, and generates `~/.pi/agent/AGENTS.md` and `~/.config/opencode/AGENTS.md` from the fragments. Idempotent; any pre-existing real dir (or non-generated AGENTS.md) is moved to `~/.agent-skills-backup/` (outside the discovery path, so it isn't picked up as a duplicate skill). Re-run after adding a skill.
|
||||||
|
|
||||||
Hooks still need one manual step: the `settings.json` snippet in `hooks/README.md`. Entry files are linked automatically — `entry/CLAUDE.md` and `entry/codex-AGENTS.md` hold the machine-local sections and `@import` the shared fragments, so both tools read the same rules with no copy and no drift.
|
Hooks still need one manual step: the `settings.json` snippet in `hooks/README.md`. Entry files are linked automatically — `entry/CLAUDE.md` and `entry/codex-AGENTS.md` hold the machine-local sections and `@import` the shared fragments, so both tools read the same rules with no copy and no drift.
|
||||||
|
|
||||||
|
|||||||
+8
-4
@@ -7,10 +7,13 @@ set -euo pipefail
|
|||||||
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
|
||||||
# targets: agent config skill roots. Claude Code reads ~/.claude/skills,
|
# targets: agent config skill roots. Claude Code reads ~/.claude/skills,
|
||||||
# Codex and Pi read ~/.agents/skills, opencode auto-loads both dirs.
|
# Pi reads ~/.agents/skills, opencode auto-loads both dirs, and Codex reads
|
||||||
# All four consume the same SKILL.md dirs.
|
# $CODEX_HOME/skills and nothing else -- ~/.agents/skills is invisible to it,
|
||||||
|
# which is how review sessions ended up reporting an unavailable review-pr
|
||||||
|
# skill. All four consume the same SKILL.md dirs.
|
||||||
CLAUDE_SKILLS="$HOME/.claude/skills"
|
CLAUDE_SKILLS="$HOME/.claude/skills"
|
||||||
CODEX_SKILLS="$HOME/.agents/skills"
|
AGENTS_SKILLS="$HOME/.agents/skills"
|
||||||
|
CODEX_SKILLS="$HOME/.codex/skills"
|
||||||
CLAUDE_CMDS="$HOME/.claude/commands" # commands are Claude-only; Codex ignores
|
CLAUDE_CMDS="$HOME/.claude/commands" # commands are Claude-only; Codex ignores
|
||||||
OPENCODE_CMDS="${XDG_CONFIG_HOME:-$HOME/.config}/opencode/commands"
|
OPENCODE_CMDS="${XDG_CONFIG_HOME:-$HOME/.config}/opencode/commands"
|
||||||
CLAUDE_HOOKS="$HOME/.claude/hooks" # hooks are Claude-only
|
CLAUDE_HOOKS="$HOME/.claude/hooks" # hooks are Claude-only
|
||||||
@@ -62,11 +65,12 @@ gen() { # gen <dst> <fragment...> — writes a generated (concatenated) file
|
|||||||
|
|
||||||
GEN_MARK="<!-- generated by agent-skills/bin/link.sh — edit fragments, re-run -->"
|
GEN_MARK="<!-- generated by agent-skills/bin/link.sh — edit fragments, re-run -->"
|
||||||
|
|
||||||
mkdir -p "$CLAUDE_SKILLS" "$CODEX_SKILLS" "$CLAUDE_CMDS" "$CLAUDE_HOOKS" "$CLAUDE_SCRIPTS" "$CLAUDE_RULES" "$CODEX_HOME" "$PI_HOME" "$OPENCODE_CMDS"
|
mkdir -p "$CLAUDE_SKILLS" "$AGENTS_SKILLS" "$CODEX_SKILLS" "$CLAUDE_CMDS" "$CLAUDE_HOOKS" "$CLAUDE_SCRIPTS" "$CLAUDE_RULES" "$CODEX_HOME" "$PI_HOME" "$OPENCODE_CMDS"
|
||||||
|
|
||||||
for d in "$REPO"/skills/*/; do
|
for d in "$REPO"/skills/*/; do
|
||||||
name="$(basename "$d")"
|
name="$(basename "$d")"
|
||||||
link "$d" "$CLAUDE_SKILLS/$name"
|
link "$d" "$CLAUDE_SKILLS/$name"
|
||||||
|
link "$d" "$AGENTS_SKILLS/$name"
|
||||||
link "$d" "$CODEX_SKILLS/$name"
|
link "$d" "$CODEX_SKILLS/$name"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
+17
-1
@@ -40,6 +40,22 @@ let
|
|||||||
repo = cfg.repoPath;
|
repo = cfg.repoPath;
|
||||||
|
|
||||||
mkEnable = what: lib.mkEnableOption "the ${what} user unit";
|
mkEnable = what: lib.mkEnableOption "the ${what} user unit";
|
||||||
|
|
||||||
|
# Codex reads $CODEX_HOME/skills and nothing else -- ~/.agents/skills reaches
|
||||||
|
# pi and opencode but not codex, which is why codex review sessions reported
|
||||||
|
# review-pr as an unavailable skill. One symlink per skill dir rather than
|
||||||
|
# recursive=true: codex skips any skill whose SKILL.md is itself a symlink,
|
||||||
|
# which is exactly what a per-file link produces. Per-skill also leaves
|
||||||
|
# codex's own ~/.codex/skills/.system in place, which a whole-dir link would
|
||||||
|
# replace.
|
||||||
|
skillNames = builtins.attrNames (
|
||||||
|
lib.filterAttrs (_: type: type == "directory") (builtins.readDir "${agent-skills}/skills")
|
||||||
|
);
|
||||||
|
codexSkills = lib.listToAttrs (
|
||||||
|
map (name: lib.nameValuePair ".codex/skills/${name}" {
|
||||||
|
source = "${agent-skills}/skills/${name}";
|
||||||
|
}) skillNames
|
||||||
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.programs.agentSkills = {
|
options.programs.agentSkills = {
|
||||||
@@ -71,7 +87,7 @@ in
|
|||||||
weekReview.enable = mkEnable "weekly review timer";
|
weekReview.enable = mkEnable "weekly review timer";
|
||||||
};
|
};
|
||||||
|
|
||||||
config.home.file = {
|
config.home.file = codexSkills // {
|
||||||
".claude/skills" = {
|
".claude/skills" = {
|
||||||
source = "${agent-skills}/skills";
|
source = "${agent-skills}/skills";
|
||||||
recursive = true;
|
recursive = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user