feat: support codex sh download
This commit is contained in:
parent
cc093d5f90
commit
6da34c4869
16
README.md
16
README.md
@ -54,10 +54,13 @@ RequirementsDoc ──▶ PRD ──▶ FeatureSummary ──▶ DevelopmentPlan
|
|||||||
一行命令搞定安装和更新。脚本会智能处理:新 skill 直接装,已有的对比更新,本地魔改自动备份。
|
一行命令搞定安装和更新。脚本会智能处理:新 skill 直接装,已有的对比更新,本地魔改自动备份。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Codex(默认)
|
# Claude Code + Codex(推荐)
|
||||||
|
bash <(curl -sL https://git.internal.intelligrow.cn/zhangfucai/spec-coding-skills/raw/branch/main/install.sh) both
|
||||||
|
|
||||||
|
# Codex only
|
||||||
bash <(curl -sL https://git.internal.intelligrow.cn/zhangfucai/spec-coding-skills/raw/branch/main/install.sh) codex
|
bash <(curl -sL https://git.internal.intelligrow.cn/zhangfucai/spec-coding-skills/raw/branch/main/install.sh) codex
|
||||||
|
|
||||||
# Claude Code
|
# Claude Code only
|
||||||
bash <(curl -sL https://git.internal.intelligrow.cn/zhangfucai/spec-coding-skills/raw/branch/main/install.sh) claude
|
bash <(curl -sL https://git.internal.intelligrow.cn/zhangfucai/spec-coding-skills/raw/branch/main/install.sh) claude
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -65,15 +68,22 @@ bash <(curl -sL https://git.internal.intelligrow.cn/zhangfucai/spec-coding-skill
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -sL https://git.internal.intelligrow.cn/zhangfucai/spec-coding-skills/raw/branch/main/install.sh -o /tmp/install-skills.sh
|
curl -sL https://git.internal.intelligrow.cn/zhangfucai/spec-coding-skills/raw/branch/main/install.sh -o /tmp/install-skills.sh
|
||||||
bash /tmp/install-skills.sh codex
|
bash /tmp/install-skills.sh both
|
||||||
```
|
```
|
||||||
|
|
||||||
### 安装脚本行为
|
### 安装脚本行为
|
||||||
|
|
||||||
|
- `both` 模式:同时安装 `.codex/skills/` 和 `.claude/skills/`,并生成 `AGENTS.md` + `CLAUDE.md`
|
||||||
- `codex` 模式:安装到 `.codex/skills/`,并在项目根目录生成或更新 `AGENTS.md`
|
- `codex` 模式:安装到 `.codex/skills/`,并在项目根目录生成或更新 `AGENTS.md`
|
||||||
- `claude` 模式:安装到 `.claude/skills/`,并在项目根目录生成或更新 `CLAUDE.md`
|
- `claude` 模式:安装到 `.claude/skills/`,并在项目根目录生成或更新 `CLAUDE.md`
|
||||||
- 如果传入自定义目标目录,脚本会优先安装 Codex 版 skills;目标路径包含 `.claude/skills` 时自动切到 Claude 版
|
- 如果传入自定义目标目录,脚本会优先安装 Codex 版 skills;目标路径包含 `.claude/skills` 时自动切到 Claude 版
|
||||||
|
|
||||||
|
### 推荐用法
|
||||||
|
|
||||||
|
- 团队项目、模板仓库:用 `both`,一次安装双端,最省心
|
||||||
|
- 只有你自己在 Codex 里用:用 `codex`
|
||||||
|
- 仓库明确只服务 Claude Code:用 `claude`
|
||||||
|
|
||||||
### 更新策略
|
### 更新策略
|
||||||
|
|
||||||
| 情况 | 处理方式 |
|
| 情况 | 处理方式 |
|
||||||
|
|||||||
202
install.sh
202
install.sh
@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# spec-coding-skills 安装/更新脚本
|
# spec-coding-skills 安装/更新脚本
|
||||||
# 用法: bash <(curl -sL <raw-url>/install.sh) [codex|claude]
|
# 用法: bash <(curl -sL <raw-url>/install.sh) [codex|claude|both]
|
||||||
# 或: bash install.sh [codex|claude|目标目录]
|
# 或: bash install.sh [codex|claude|both|目标目录]
|
||||||
# ============================================================
|
# ============================================================
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@ -19,6 +19,11 @@ TARGET=""
|
|||||||
SKILLS_SRC=""
|
SKILLS_SRC=""
|
||||||
GUIDE_SRC=""
|
GUIDE_SRC=""
|
||||||
GUIDE_DST=""
|
GUIDE_DST=""
|
||||||
|
REQUEST="${1:-$DEFAULT_MODE}"
|
||||||
|
TOTAL_NEW=0
|
||||||
|
TOTAL_UPDATED=0
|
||||||
|
TOTAL_SKIPPED=0
|
||||||
|
INSTALLED_TARGETS=""
|
||||||
|
|
||||||
resolve_layout() {
|
resolve_layout() {
|
||||||
local input="$1"
|
local input="$1"
|
||||||
@ -38,6 +43,10 @@ resolve_layout() {
|
|||||||
GUIDE_SRC="CLAUDE.md.template"
|
GUIDE_SRC="CLAUDE.md.template"
|
||||||
GUIDE_DST="CLAUDE.md"
|
GUIDE_DST="CLAUDE.md"
|
||||||
;;
|
;;
|
||||||
|
both)
|
||||||
|
log_warn "both 不是单一布局,请在主流程中单独处理"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
TARGET="$input"
|
TARGET="$input"
|
||||||
case "$TARGET" in
|
case "$TARGET" in
|
||||||
@ -58,10 +67,92 @@ resolve_layout() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve_layout "${1:-$DEFAULT_MODE}"
|
|
||||||
TMP_DIR=$(mktemp -d)
|
TMP_DIR=$(mktemp -d)
|
||||||
trap "rm -rf $TMP_DIR" EXIT
|
trap "rm -rf $TMP_DIR" EXIT
|
||||||
|
|
||||||
|
sync_file() {
|
||||||
|
local src="$1"
|
||||||
|
local dst="$2"
|
||||||
|
local create_msg="$3"
|
||||||
|
local update_msg="$4"
|
||||||
|
|
||||||
|
if [ ! -f "$dst" ]; then
|
||||||
|
mkdir -p "$(dirname "$dst")"
|
||||||
|
cp "$src" "$dst"
|
||||||
|
log_info "$create_msg"
|
||||||
|
TOTAL_NEW=$((TOTAL_NEW + 1))
|
||||||
|
elif ! diff -q "$src" "$dst" >/dev/null 2>&1; then
|
||||||
|
cp "$dst" "$dst.local.bak"
|
||||||
|
cp "$src" "$dst"
|
||||||
|
log_warn "$update_msg"
|
||||||
|
TOTAL_UPDATED=$((TOTAL_UPDATED + 1))
|
||||||
|
else
|
||||||
|
TOTAL_SKIPPED=$((TOTAL_SKIPPED + 1))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_layout() {
|
||||||
|
local input="$1"
|
||||||
|
local skill_dir
|
||||||
|
local skill_name
|
||||||
|
local src_file
|
||||||
|
local dst_dir
|
||||||
|
local dst_file
|
||||||
|
local tpl_file
|
||||||
|
local tpl_name
|
||||||
|
local dst
|
||||||
|
local guide_src_path
|
||||||
|
|
||||||
|
resolve_layout "$input"
|
||||||
|
|
||||||
|
if [ ! -d "$TMP_DIR/$SKILLS_SRC" ]; then
|
||||||
|
log_warn "上游仓库中不存在技能目录: $SKILLS_SRC"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "同步 $MODE: $TARGET"
|
||||||
|
mkdir -p "$TARGET"
|
||||||
|
|
||||||
|
for skill_dir in "$TMP_DIR/$SKILLS_SRC"/*/; do
|
||||||
|
[ -d "$skill_dir" ] || continue
|
||||||
|
skill_name=$(basename "$skill_dir")
|
||||||
|
src_file="$skill_dir/SKILL.md"
|
||||||
|
dst_dir="$TARGET/$skill_name"
|
||||||
|
dst_file="$dst_dir/SKILL.md"
|
||||||
|
|
||||||
|
[ -f "$src_file" ] || continue
|
||||||
|
|
||||||
|
sync_file \
|
||||||
|
"$src_file" \
|
||||||
|
"$dst_file" \
|
||||||
|
"✨ 新增: $skill_name ($MODE)" \
|
||||||
|
"🔄 更新: $skill_name ($MODE) (本地版本已备份为 SKILL.md.local.bak)"
|
||||||
|
done
|
||||||
|
|
||||||
|
for tpl_file in "$TMP_DIR/$SKILLS_SRC"/*.template "$TMP_DIR/$SKILLS_SRC"/*.md; do
|
||||||
|
[ -f "$tpl_file" ] || continue
|
||||||
|
tpl_name=$(basename "$tpl_file")
|
||||||
|
dst="$TARGET/$tpl_name"
|
||||||
|
|
||||||
|
sync_file \
|
||||||
|
"$tpl_file" \
|
||||||
|
"$dst" \
|
||||||
|
"✨ 新增模板: $tpl_name ($MODE)" \
|
||||||
|
"🔄 更新模板: $tpl_name ($MODE) (本地版本已备份为 ${tpl_name}.local.bak)"
|
||||||
|
done
|
||||||
|
|
||||||
|
guide_src_path="$TMP_DIR/$GUIDE_SRC"
|
||||||
|
if [ -f "$guide_src_path" ]; then
|
||||||
|
sync_file \
|
||||||
|
"$guide_src_path" \
|
||||||
|
"$GUIDE_DST" \
|
||||||
|
"✨ 新增项目引导: $GUIDE_DST" \
|
||||||
|
"🔄 更新项目引导: $GUIDE_DST (本地版本已备份为 ${GUIDE_DST}.local.bak)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
INSTALLED_TARGETS="${INSTALLED_TARGETS}${INSTALLED_TARGETS:+, }$TARGET"
|
||||||
|
}
|
||||||
|
|
||||||
# ---------- 拉取最新 ----------
|
# ---------- 拉取最新 ----------
|
||||||
log_title "📦 spec-coding-skills 安装/更新"
|
log_title "📦 spec-coding-skills 安装/更新"
|
||||||
echo ""
|
echo ""
|
||||||
@ -70,102 +161,35 @@ git clone --depth 1 --quiet "$REPO_URL" "$TMP_DIR"
|
|||||||
|
|
||||||
VERSION=$(git -C "$TMP_DIR" describe --tags --always 2>/dev/null || git -C "$TMP_DIR" rev-parse --short HEAD)
|
VERSION=$(git -C "$TMP_DIR" describe --tags --always 2>/dev/null || git -C "$TMP_DIR" rev-parse --short HEAD)
|
||||||
log_info "版本: $VERSION"
|
log_info "版本: $VERSION"
|
||||||
log_info "模式: $MODE"
|
|
||||||
|
|
||||||
if [ ! -d "$TMP_DIR/$SKILLS_SRC" ]; then
|
case "$REQUEST" in
|
||||||
log_warn "上游仓库中不存在技能目录: $SKILLS_SRC"
|
both)
|
||||||
exit 1
|
log_info "模式: both"
|
||||||
fi
|
install_layout codex
|
||||||
|
install_layout claude
|
||||||
# ---------- 统计变更 ----------
|
;;
|
||||||
NEW=0
|
*)
|
||||||
UPDATED=0
|
resolve_layout "$REQUEST"
|
||||||
SKIPPED=0
|
log_info "模式: $MODE"
|
||||||
KEPT=0
|
install_layout "$REQUEST"
|
||||||
|
;;
|
||||||
mkdir -p "$TARGET"
|
esac
|
||||||
|
|
||||||
# 遍历上游 skill 目录
|
|
||||||
for skill_dir in "$TMP_DIR/$SKILLS_SRC"/*/; do
|
|
||||||
[ -d "$skill_dir" ] || continue
|
|
||||||
skill_name=$(basename "$skill_dir")
|
|
||||||
src_file="$skill_dir/SKILL.md"
|
|
||||||
dst_dir="$TARGET/$skill_name"
|
|
||||||
dst_file="$dst_dir/SKILL.md"
|
|
||||||
|
|
||||||
[ -f "$src_file" ] || continue
|
|
||||||
|
|
||||||
if [ ! -f "$dst_file" ]; then
|
|
||||||
# 新 skill,直接复制
|
|
||||||
mkdir -p "$dst_dir"
|
|
||||||
cp "$src_file" "$dst_file"
|
|
||||||
log_info "✨ 新增: $skill_name"
|
|
||||||
NEW=$((NEW + 1))
|
|
||||||
elif diff -q "$src_file" "$dst_file" >/dev/null 2>&1; then
|
|
||||||
# 内容一致,跳过
|
|
||||||
SKIPPED=$((SKIPPED + 1))
|
|
||||||
else
|
|
||||||
# 内容不同:上游有更新 或 用户本地修改过
|
|
||||||
# 策略:备份本地版本,写入上游新版本
|
|
||||||
cp "$dst_file" "$dst_file.local.bak"
|
|
||||||
cp "$src_file" "$dst_file"
|
|
||||||
log_warn "🔄 更新: $skill_name (本地版本已备份为 SKILL.md.local.bak)"
|
|
||||||
UPDATED=$((UPDATED + 1))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# 复制模板文件(非 skill 目录的文件)
|
|
||||||
for tpl_file in "$TMP_DIR/$SKILLS_SRC"/*.template "$TMP_DIR/$SKILLS_SRC"/*.md; do
|
|
||||||
[ -f "$tpl_file" ] || continue
|
|
||||||
tpl_name=$(basename "$tpl_file")
|
|
||||||
dst="$TARGET/$tpl_name"
|
|
||||||
|
|
||||||
if [ ! -f "$dst" ]; then
|
|
||||||
cp "$tpl_file" "$dst"
|
|
||||||
log_info "✨ 新增模板: $tpl_name"
|
|
||||||
NEW=$((NEW + 1))
|
|
||||||
elif ! diff -q "$tpl_file" "$dst" >/dev/null 2>&1; then
|
|
||||||
cp "$dst" "$dst.local.bak"
|
|
||||||
cp "$tpl_file" "$dst"
|
|
||||||
log_warn "🔄 更新模板: $tpl_name (本地版本已备份为 ${tpl_name}.local.bak)"
|
|
||||||
UPDATED=$((UPDATED + 1))
|
|
||||||
else
|
|
||||||
SKIPPED=$((SKIPPED + 1))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# 安装项目根目录引导文件
|
|
||||||
guide_src_path="$TMP_DIR/$GUIDE_SRC"
|
|
||||||
if [ -f "$guide_src_path" ]; then
|
|
||||||
if [ ! -f "$GUIDE_DST" ]; then
|
|
||||||
cp "$guide_src_path" "$GUIDE_DST"
|
|
||||||
log_info "✨ 新增项目引导: $GUIDE_DST"
|
|
||||||
NEW=$((NEW + 1))
|
|
||||||
elif ! diff -q "$guide_src_path" "$GUIDE_DST" >/dev/null 2>&1; then
|
|
||||||
cp "$GUIDE_DST" "$GUIDE_DST.local.bak"
|
|
||||||
cp "$guide_src_path" "$GUIDE_DST"
|
|
||||||
log_warn "🔄 更新项目引导: $GUIDE_DST (本地版本已备份为 ${GUIDE_DST}.local.bak)"
|
|
||||||
UPDATED=$((UPDATED + 1))
|
|
||||||
else
|
|
||||||
SKIPPED=$((SKIPPED + 1))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ---------- 汇总 ----------
|
# ---------- 汇总 ----------
|
||||||
echo ""
|
echo ""
|
||||||
log_title "✅ 完成!"
|
log_title "✅ 完成!"
|
||||||
echo ""
|
echo ""
|
||||||
echo " 🧭 模式: $MODE"
|
echo " 🧭 模式: $REQUEST"
|
||||||
echo " 📁 目标目录: $TARGET"
|
echo " 📁 目标目录: $INSTALLED_TARGETS"
|
||||||
echo " 📦 版本: $VERSION"
|
echo " 📦 版本: $VERSION"
|
||||||
echo ""
|
echo ""
|
||||||
echo " ✨ 新增: $NEW"
|
echo " ✨ 新增: $TOTAL_NEW"
|
||||||
echo " 🔄 更新: $UPDATED(本地版本已备份为 .local.bak)"
|
echo " 🔄 更新: $TOTAL_UPDATED(本地版本已备份为 .local.bak)"
|
||||||
echo " ⏭️ 无变化: $SKIPPED"
|
echo " ⏭️ 无变化: $TOTAL_SKIPPED"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
if [ "$UPDATED" -gt 0 ]; then
|
if [ "$TOTAL_UPDATED" -gt 0 ]; then
|
||||||
log_warn "有 $UPDATED 个文件被更新,本地修改已备份为 .local.bak"
|
log_warn "有 $TOTAL_UPDATED 个文件被更新,本地修改已备份为 .local.bak"
|
||||||
log_warn "如需恢复本地版本: mv SKILL.md.local.bak SKILL.md"
|
log_warn "如需恢复本地版本: mv SKILL.md.local.bak SKILL.md"
|
||||||
log_warn "如需对比差异: diff SKILL.md SKILL.md.local.bak"
|
log_warn "如需对比差异: diff SKILL.md SKILL.md.local.bak"
|
||||||
fi
|
fi
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user