Skip to content

Commit 6878383

Browse files
authored
Merge pull request #35 from taptap/fix/codex-statusline-improvements
feat: add Codex skills sync via ~/.agents/skills/ symlinks
2 parents 9462551 + 9ff0191 commit 6878383

File tree

8 files changed

+226
-5
lines changed

8 files changed

+226
-5
lines changed

.claude-plugin/marketplace.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"metadata": {
88
"description": "TapTap Claude Code 插件库 - 提供开发工作流自动化插件",
9-
"version": "0.1.24",
9+
"version": "0.1.25",
1010
"pluginRoot": "./plugins"
1111
},
1212
"plugins": [
@@ -38,7 +38,7 @@
3838
"name": "sync",
3939
"source": "./plugins/sync",
4040
"description": "项目配置同步插件,提供 MCP、LSP 和开发环境配置同步功能",
41-
"version": "0.1.20",
41+
"version": "0.1.21",
4242
"author": {
4343
"name": "TapTap AI Team"
4444
},

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# Changelog
22

3+
## 0.1.25 — Codex skills sync
4+
5+
### Sync Plugin (0.1.21)
6+
7+
- Added `ensure-codex-skills.sh` to sync plugin skills to `~/.agents/skills/` for Codex discovery
8+
- Added manifest-based tracking (`~/.cache/codex-skills-sync/managed.txt`) to safely manage symlinks without touching user-created files
9+
- Added migration logic to clean old hardlinks and symlinks from `~/.codex/skills/` and `~/.agents/skills/`
10+
- Added `EXCLUDE_PLUGINS` and `EXCLUDE_SKILLS` config to skip unpublished plugins (e.g., ralph)
11+
- Added marketplace filter (`INCLUDE_MARKETPLACE`) to only sync skills from our own marketplace
12+
- Registered `ensure-codex-skills.sh` as SessionStart hook for automatic sync on session start
13+
14+
### Marketplace
15+
16+
- Bumped version from 0.1.24 to 0.1.25
17+
- Updated sync plugin to version 0.1.21
18+
319
## 0.1.24 — Codex statusline fixes
420

521
### Sync Plugin (0.1.20)

README.en.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ One-click configuration for MCP, auto-update, and Cursor synchronization:
8686
| ------- | ------- | ---------------------------------------------------------------------------------------------------- |
8787
| spec | 0.1.4 | Spec-Driven Development workflow plugin |
8888
| git | 0.1.12 | Git workflow automation plugin (commit/push/MR + dual-mode code review + remote platform ops) |
89-
| sync | 0.1.20 | Dev environment config sync plugin (MCP + LSP + Hooks + Cursor + Claude Skills) |
89+
| sync | 0.1.21 | Dev environment config sync plugin (MCP + LSP + Hooks + Cursor + Claude Skills) |
9090
| quality | 0.0.4 | AI-powered code quality plugin (9 parallel Agents: Bug detection, code quality, security, performance) |
9191

9292

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ mkdir -p .claude && echo '{
8686
| ------- | ----- | ----------------------------------------------------------------- |
8787
| spec | 0.1.4 | Spec-Driven Development 工作流插件 |
8888
| git | 0.1.12 | Git 工作流自动化插件(提交/推送/MR + 自动代码审查 + 远程平台操作) |
89-
| sync | 0.1.20 | 开发环境配置同步插件(MCP + LSP + Hooks + Cursor + Claude Skills) |
89+
| sync | 0.1.21 | 开发环境配置同步插件(MCP + LSP + Hooks + Cursor + Claude Skills) |
9090
| quality | 0.0.4 | AI 驱动的代码质量检查插件(9 个并行 Agent,支持 Bug 检测、代码质量、安全检查、性能分析) |
9191

9292

plugins/sync/.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "sync",
33
"description": "项目配置同步插件,提供 MCP、LSP 和开发环境配置同步功能",
4-
"version": "0.1.20",
4+
"version": "0.1.21",
55
"author": {
66
"name": "TapTap AI Team"
77
}

plugins/sync/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ chmod +x .githooks/pre-commit
344344

345345
## 版本历史
346346

347+
- **v0.1.21** - 新增 ensure-codex-skills.sh 自动同步插件 skills 到 ~/.agents/skills/(Codex 可发现);基于 manifest 跟踪管理的 symlink;迁移清理旧硬链接和非本 marketplace symlink;排除未发布插件(ralph);注册为 SessionStart hook
347348
- **v0.1.20** - 修复 context usage 显示 100% 问题(改用 last_token_usage);修复多实例 context 串扰;修复 tmux 普通模式无 statusline(_is_tmux_cc 区分 -CC 模式);修复 tmux -CC 报错(passthrough 包裹);iTerm2 配置改用 defaults export/import(防止被覆盖);zsh hooks 更新检测改用 hash 比较;新增 /clean-codex-statusline skill
348349
- **v0.1.19** - 新增 codex-statusline(tmux + iTerm2);飞书 MCP 的 Codex 配置改为可选(--with-codex);hooks 迁移至 $HOME 级(Codex 兼容);移除 sequential-thinking MCP;新增 plugin-status skill
349350
- **v0.1.17** - skills-sync 新增 review-rules 模板同步(不覆盖项目已有规则)

plugins/sync/hooks/hooks.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
{
2828
"type": "command",
2929
"command": "(bash ~/.claude/hooks/scripts/ensure-codex-statusline.sh >/dev/null 2>&1 &)"
30+
},
31+
{
32+
"type": "command",
33+
"command": "(bash ~/.claude/hooks/scripts/ensure-codex-skills.sh >/dev/null 2>&1 &)"
3034
}
3135
]
3236
}
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
#!/bin/bash
2+
# ensure-codex-skills.sh - Sync Claude Code plugin skills to ~/.agents/skills/ for Codex
3+
# SessionStart hook: runs in background, idempotent
4+
# Uses manifest to track managed symlinks, never touches user-created files
5+
6+
set +e # Don't exit on errors — background hook must complete gracefully
7+
8+
# ========== Config ==========
9+
10+
AGENTS_SKILLS="$HOME/.agents/skills"
11+
CODEX_SKILLS="$HOME/.codex/skills"
12+
CLAUDE_SKILLS="$HOME/.claude/skills"
13+
MANIFEST_DIR="$HOME/.cache/codex-skills-sync"
14+
MANIFEST_FILE="$MANIFEST_DIR/managed.txt"
15+
16+
# Only sync skills from our own marketplace (taptap-plugins)
17+
# All other marketplaces (claude-plugins-official, pua-skills, etc.) are excluded
18+
INCLUDE_MARKETPLACE="taptap-plugins"
19+
20+
# Excluded plugins within our marketplace (not published, under development)
21+
EXCLUDE_PLUGINS="ralph"
22+
23+
# Excluded skill names (cleaned on every run from both ~/.codex/skills and ~/.agents/skills)
24+
# Covers old hardlinks/real dirs that migration can't detect
25+
EXCLUDE_SKILLS="ralph-loop ralph-pause ralph-resume ralph-status ralph-adjust ralph-decompose ralph-workflow cancel-ralph prd-to-json"
26+
27+
# Log
28+
LOG_DIR="$HOME/.claude/plugins/logs"
29+
mkdir -p "$LOG_DIR"
30+
LOG_FILE="$LOG_DIR/ensure-codex-skills-$(date +%Y-%m-%d).log"
31+
exec >> "$LOG_FILE" 2>&1
32+
echo ""
33+
echo "===== $(date '+%Y-%m-%d %H:%M:%S') ====="
34+
35+
# ========== Step 0: Skip if Codex not installed ==========
36+
37+
if [ ! -d "$CODEX_SKILLS" ] && ! command -v codex >/dev/null 2>&1; then
38+
echo "⏭️ Codex 未安装,跳过"
39+
exit 0
40+
fi
41+
42+
mkdir -p "$AGENTS_SKILLS"
43+
mkdir -p "$MANIFEST_DIR"
44+
45+
# ========== Step 1: Clean excluded skills from both directories ==========
46+
47+
for skill in $EXCLUDE_SKILLS; do
48+
for dir in "$CODEX_SKILLS" "$AGENTS_SKILLS"; do
49+
if [ -e "$dir/$skill" ] || [ -L "$dir/$skill" ]; then
50+
rm -rf "${dir:?}/${skill:?}"
51+
echo "🗑️ 已删除排除 skill: $dir/$skill"
52+
fi
53+
done
54+
done
55+
56+
# ========== Step 2: Clean old managed symlinks from ~/.agents/skills/ ==========
57+
58+
if [ -f "$MANIFEST_FILE" ]; then
59+
while IFS= read -r name; do
60+
[ -z "$name" ] && continue
61+
target="$AGENTS_SKILLS/$name"
62+
# Only remove if it's a symlink (we created it), never remove real dirs
63+
if [ -L "$target" ]; then
64+
rm -f "$target"
65+
fi
66+
done < "$MANIFEST_FILE"
67+
fi
68+
69+
# ========== Step 3: Migration — clean old symlinks from both dirs ==========
70+
71+
MIGRATION_MARKER="$MANIFEST_DIR/.v3_migrated"
72+
if [ ! -f "$MIGRATION_MARKER" ]; then
73+
# Clean symlinks pointing to plugin/marketplace paths from BOTH directories
74+
# In ~/.agents/skills/: only keep symlinks pointing to our marketplace (taptap-plugins)
75+
# In ~/.codex/skills/: remove all symlinks pointing to plugin paths
76+
for dir in "$AGENTS_SKILLS" "$CODEX_SKILLS"; do
77+
[ -d "$dir" ] || continue
78+
for entry in "$dir"/*/; do
79+
[ -e "$entry" ] || [ -L "${entry%/}" ] || continue
80+
skill_name="$(basename "$entry")"
81+
82+
target_path="${dir}/${skill_name}"
83+
if [ -L "$target_path" ]; then
84+
link_target="$(readlink "$target_path" 2>/dev/null || true)"
85+
case "$link_target" in
86+
*/.claude/plugins/*|*/claude-plugins-marketplace/*)
87+
# In agents dir: keep our own marketplace symlinks (will be re-managed)
88+
# In codex dir: remove all plugin symlinks
89+
if [ "$dir" = "$CODEX_SKILLS" ]; then
90+
rm -f "$target_path"
91+
echo "🔗 已清理旧 symlink: $dir/$skill_name"
92+
elif echo "$link_target" | grep -qv "/$INCLUDE_MARKETPLACE/"; then
93+
# agents dir: remove symlinks from other marketplaces
94+
rm -f "$target_path"
95+
echo "🔗 已清理非本 marketplace symlink: $skill_name"
96+
fi
97+
;;
98+
esac
99+
fi
100+
done
101+
done
102+
103+
# Clean hardlinks in ~/.agents/skills/ (same inode as ~/.codex/skills/)
104+
if [ -d "$CODEX_SKILLS" ]; then
105+
for entry in "$AGENTS_SKILLS"/*/; do
106+
[ -d "$entry" ] || continue
107+
skill_name="$(basename "$entry")"
108+
[ -L "$AGENTS_SKILLS/$skill_name" ] && continue
109+
agents_file="$AGENTS_SKILLS/$skill_name/SKILL.md"
110+
codex_file="$CODEX_SKILLS/$skill_name/SKILL.md"
111+
if [ -f "$agents_file" ] && [ -f "$codex_file" ]; then
112+
agents_inode="$(stat -f '%i' "$agents_file" 2>/dev/null || stat -c '%i' "$agents_file" 2>/dev/null)"
113+
codex_inode="$(stat -f '%i' "$codex_file" 2>/dev/null || stat -c '%i' "$codex_file" 2>/dev/null)"
114+
if [ -n "$agents_inode" ] && [ "$agents_inode" = "$codex_inode" ]; then
115+
rm -rf "${AGENTS_SKILLS:?}/${skill_name:?}"
116+
echo "🔗 已清理硬链接: $skill_name"
117+
fi
118+
fi
119+
done
120+
fi
121+
122+
touch "$MIGRATION_MARKER"
123+
echo "✅ 迁移完成(v3)"
124+
fi
125+
126+
# ========== Step 4: Sync plugin skills to ~/.agents/skills/ ==========
127+
128+
new_manifest=""
129+
130+
MP_DIR="$HOME/.claude/plugins/marketplaces/$INCLUDE_MARKETPLACE"
131+
for skill_md in \
132+
"$MP_DIR"/plugins/*/skills/*/SKILL.md \
133+
"$MP_DIR"/.claude/skills/*/SKILL.md; do
134+
[ -f "$skill_md" ] || continue
135+
skill_dir="$(dirname "$skill_md")"
136+
skill_name="$(basename "$skill_dir")"
137+
138+
# Check if plugin is excluded
139+
excluded=false
140+
for ep in $EXCLUDE_PLUGINS; do
141+
if echo "$skill_dir" | grep -q "/plugins/$ep/"; then
142+
excluded=true
143+
break
144+
fi
145+
done
146+
[ "$excluded" = "true" ] && continue
147+
148+
# Check if skill name is excluded
149+
for es in $EXCLUDE_SKILLS; do
150+
if [ "$skill_name" = "$es" ]; then
151+
excluded=true
152+
break
153+
fi
154+
done
155+
[ "$excluded" = "true" ] && continue
156+
157+
# Skip if already exists as a real directory (user-created, not our symlink)
158+
if [ -e "$AGENTS_SKILLS/$skill_name" ] && [ ! -L "$AGENTS_SKILLS/$skill_name" ]; then
159+
continue
160+
fi
161+
162+
# Create symlink in ~/.agents/skills/
163+
ln -sf "$skill_dir" "$AGENTS_SKILLS/$skill_name"
164+
new_manifest="$new_manifest
165+
$skill_name"
166+
done
167+
168+
# ========== Step 5: Sync ~/.claude/skills/ ==========
169+
170+
if [ -d "$CLAUDE_SKILLS" ]; then
171+
for skill_dir in "$CLAUDE_SKILLS"/*/; do
172+
[ -d "$skill_dir" ] || continue
173+
[ -f "$skill_dir/SKILL.md" ] || continue
174+
skill_name="$(basename "$skill_dir")"
175+
176+
# Check exclusions
177+
excluded=false
178+
for es in $EXCLUDE_SKILLS; do
179+
[ "$skill_name" = "$es" ] && excluded=true && break
180+
done
181+
[ "$excluded" = "true" ] && continue
182+
183+
# Skip if already exists (real dir, user symlink, or already managed)
184+
if [ -e "$AGENTS_SKILLS/$skill_name" ] || [ -L "$AGENTS_SKILLS/$skill_name" ]; then
185+
continue
186+
fi
187+
188+
ln -sf "${skill_dir%/}" "$AGENTS_SKILLS/$skill_name"
189+
new_manifest="$new_manifest
190+
$skill_name"
191+
done
192+
fi
193+
194+
# ========== Step 6: Update manifest ==========
195+
196+
echo "$new_manifest" | sed '/^$/d' | sort -u > "$MANIFEST_FILE"
197+
managed_count="$(wc -l < "$MANIFEST_FILE" | tr -d ' ')"
198+
echo "✅ 同步完成: $managed_count 个 managed symlinks in ~/.agents/skills/"
199+
200+
echo "===== 完成 ====="

0 commit comments

Comments
 (0)