tools-sync: mirror 阶段只链接含 SKILL.md 的目录

Claude Code 会把账号侧下发的 skills 缓存进 ~\.claude\skills\synced\<guid>\,
它不是 skill(顶层没有 SKILL.md),但内层目录各自带 SKILL.md。旧逻辑无条件
镜像主副本下的每个非点开头目录,于是给 Codex 建了 synced 的 junction —— Codex
递归扫到内层那批,会把账号已经提供的 skills 再注册一遍。

改为以顶层 SKILL.md 作为判据(与脚本自己 '\' 检查、以及 Codex 的注册
规则一致),并把被跳过的目录打印出来。
This commit is contained in:
Myfro9
2026-09-23 17:02:24 +08:00
parent 1cb9a7e2e7
commit 858b7eb6dc
+10 -1
View File
@@ -376,8 +376,17 @@ if ($MirrorRegistry) {
# A primary entry that is itself a link belongs to whichever host installed it (its real home
# is a registry the host already exposes to Codex). Mirroring it would register it twice.
$primarySkills = Get-ChildItem $ClaudeSkills -Directory -Force |
$primaryDirs = Get-ChildItem $ClaudeSkills -Directory -Force |
Where-Object { $_.Name -notlike ".*" -and -not (Test-IsLink $_) }
# A directory without SKILL.md at its top level is not a skill -- e.g. 'synced/', the
# runtime cache of account-side skills Claude Code downloads. Mirroring it is worse than
# useless: its NESTED directories do carry SKILL.md, so Codex would register that whole
# set a second time alongside the ones it already gets from the account.
$primarySkills = $primaryDirs | Where-Object { Test-Path (Join-Path $_.FullName "SKILL.md") }
$notSkills = $primaryDirs | Where-Object { -not (Test-Path (Join-Path $_.FullName "SKILL.md")) }
if ($notSkills) {
Write-Host " not skills (no SKILL.md), not mirrored: $(($notSkills | ForEach-Object Name) -join ', ')"
}
foreach ($d in $primarySkills) {
$link = Join-Path $MirrorRegistry $d.Name
if (Test-Path $link) { continue }