From eb2cb6de9f988ea2acac988f7f1fb782a25a39ba Mon Sep 17 00:00:00 2001 From: satyaborg Date: Fri, 29 May 2026 13:59:36 +1000 Subject: [PATCH] feat!: install skills for codex and claude --- README.md | 7 ++++--- skill_helpers.sh | 44 +++++++++++++++++++++++++++++++++++++------ tests/devloop_test.sh | 29 ++++++++++++++++------------ 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 9fc8030..f9645ac 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ Run without installing: ./devloop --help ``` -`install.sh` also installs the bundled Agent Skills globally under `~/.agents/skills`. +`install.sh` also installs the bundled Agent Skills globally for Codex under `~/.agents/skills` +and Claude Code under `~/.claude/skills`. After install or update, verify the local setup: ```sh @@ -126,8 +127,8 @@ When stdout is a terminal, running `devloop` without arguments opens a menu: bash -n devloop install.sh ./devloop --help tmp="$(mktemp -d)" -DEVLOOP_BIN_DIR="$tmp/bin" DEVLOOP_SKILLS_DIR="$tmp/skills" ./install.sh -PATH="$tmp/bin:$PATH" DEVLOOP_SKILLS_DIR="$tmp/skills" devloop doctor +DEVLOOP_BIN_DIR="$tmp/bin" HOME="$tmp/home" ./install.sh +PATH="$tmp/bin:$PATH" HOME="$tmp/home" devloop doctor ``` The supported runtime is the root [`devloop`](devloop) Bash script. diff --git a/skill_helpers.sh b/skill_helpers.sh index 1ddd1e4..6ec51e0 100644 --- a/skill_helpers.sh +++ b/skill_helpers.sh @@ -1,7 +1,8 @@ #!/usr/bin/env bash -devloop_skills_dir() { - printf '%s\n' "${DEVLOOP_SKILLS_DIR:-$HOME/.agents/skills}" +devloop_skills_dirs() { + printf '%s\n' "$HOME/.agents/skills" + printf '%s\n' "$HOME/.claude/skills" } devloop_checksum_file() { @@ -59,8 +60,7 @@ devloop_can_replace_skill() { devloop_install_skills() { local root="$1" - local skills_dir mode source name dest checksum status - skills_dir="$(devloop_skills_dir)" + local skills_dir mode status mode="${DEVLOOP_SKILL_INSTALL:-copy}" status=0 @@ -72,6 +72,23 @@ devloop_install_skills() { ;; esac + while IFS= read -r skills_dir; do + if [ -z "$skills_dir" ]; then continue; fi + devloop_install_skills_to_dir "$root" "$skills_dir" "$mode" || status=1 + done <&2 return 1 @@ -153,8 +170,23 @@ devloop_doctor_optional_command() { devloop_doctor_skills() { local root="$1" - local skills_dir source name dest declared bundled installed status - skills_dir="$(devloop_skills_dir)" + local skills_dir status + status=0 + + while IFS= read -r skills_dir; do + if [ -z "$skills_dir" ]; then continue; fi + devloop_doctor_skills_in_dir "$root" "$skills_dir" || status=1 + done </tmp/devloop-install-test.out +install_home="$work/install-home" +DEVLOOP_BIN_DIR="$bin_dir" HOME="$install_home" "$ROOT/install.sh" >/tmp/devloop-install-test.out [[ -x "$ROOT/devloop" ]] || fail "devloop is not executable" [[ -L "$bin_dir/devloop" ]] || fail "installer did not create symlink" -[[ -f "$skills_dir/devloop-spec/SKILL.md" ]] || fail "installer did not install spec skill" -[[ -f "$skills_dir/devloop-spec/references/spec-template.md" ]] || fail "installer did not install spec template reference" -[[ -f "$skills_dir/devloop-review/SKILL.md" ]] || fail "installer did not install review skill" -[[ -f "$skills_dir/devloop-review/.devloop-checksum" ]] || fail "installer did not write checksum" +[[ -f "$install_home/.agents/skills/devloop-spec/SKILL.md" ]] || fail "installer did not install Codex spec skill" +[[ -f "$install_home/.agents/skills/devloop-spec/references/spec-template.md" ]] || fail "installer did not install Codex spec template reference" +[[ -f "$install_home/.agents/skills/devloop-review/SKILL.md" ]] || fail "installer did not install Codex review skill" +[[ -f "$install_home/.agents/skills/devloop-review/.devloop-checksum" ]] || fail "installer did not write Codex checksum" +[[ -f "$install_home/.claude/skills/devloop-spec/SKILL.md" ]] || fail "installer did not install Claude spec skill" +[[ -f "$install_home/.claude/skills/devloop-review/SKILL.md" ]] || fail "installer did not install Claude review skill" +[[ -f "$install_home/.claude/skills/devloop-review/.devloop-checksum" ]] || fail "installer did not write Claude checksum" "$bin_dir/devloop" --help >/tmp/devloop-help-test.out contains "$(cat /tmp/devloop-help-test.out)" "Spec-driven code and review loop." "installed help" ok "installer" -printf '%s\n' "user edit" >> "$skills_dir/devloop-review/SKILL.md" -DEVLOOP_BIN_DIR="$bin_dir" DEVLOOP_SKILLS_DIR="$skills_dir" "$ROOT/install.sh" >/tmp/devloop-install-skip.out 2>&1 +printf '%s\n' "user edit" >> "$install_home/.agents/skills/devloop-review/SKILL.md" +DEVLOOP_BIN_DIR="$bin_dir" HOME="$install_home" "$ROOT/install.sh" >/tmp/devloop-install-skip.out 2>&1 contains "$(cat /tmp/devloop-install-skip.out)" "skipping modified skill" "installer modified skill guard" contains "$(cat /tmp/devloop-install-skip.out)" "try: devloop doctor" "installer guidance after skill skip" -contains "$(cat "$skills_dir/devloop-review/SKILL.md")" "user edit" "installer modified skill preserved" -DEVLOOP_FORCE=1 DEVLOOP_BIN_DIR="$bin_dir" DEVLOOP_SKILLS_DIR="$skills_dir" "$ROOT/install.sh" >/tmp/devloop-install-force.out -if grep -q "user edit" "$skills_dir/devloop-review/SKILL.md"; then fail "installer force did not restore skill"; fi +contains "$(cat "$install_home/.agents/skills/devloop-review/SKILL.md")" "user edit" "installer modified skill preserved" +DEVLOOP_FORCE=1 DEVLOOP_BIN_DIR="$bin_dir" HOME="$install_home" "$ROOT/install.sh" >/tmp/devloop-install-force.out +if grep -q "user edit" "$install_home/.agents/skills/devloop-review/SKILL.md"; then fail "installer force did not restore skill"; fi ok "installer skill updates" fake_bin="$work/fake-bin" @@ -237,10 +240,12 @@ mkdir -p "$fake_bin" printf '#!/usr/bin/env bash\nexit 0\n' > "$fake_bin/codex" printf '#!/usr/bin/env bash\nexit 0\n' > "$fake_bin/claude" chmod +x "$fake_bin/codex" "$fake_bin/claude" -doctor_output="$(DEVLOOP_SKILLS_DIR="$skills_dir" PATH="$bin_dir:$fake_bin:$PATH" "$bin_dir/devloop" doctor 2>&1)" +doctor_output="$(HOME="$install_home" PATH="$bin_dir:$fake_bin:$PATH" "$bin_dir/devloop" doctor 2>&1)" contains "$doctor_output" "devloop doctor: ready" "doctor" contains "$doctor_output" "[ok] skill devloop-spec" "doctor" contains "$doctor_output" "Optional UI" "doctor" +contains "$doctor_output" "$install_home/.agents/skills/devloop-spec" "doctor Codex skill" +contains "$doctor_output" "$install_home/.claude/skills/devloop-spec" "doctor Claude skill" ok "doctor" agent="$work/spec-agent"