sync: SHANGHAI-U9 2026-10-12 tools-sync 增 OpenCode skills 注册(阶段 2.5 + sync_opencode_skills.ps1 + env 模板)
This commit is contained in:
+44
-5
@@ -1,14 +1,14 @@
|
|||||||
---
|
---
|
||||||
name: tools-sync
|
name: tools-sync
|
||||||
description: 在本机统一同步并配置 Claude Code 与 Codex 的 skills(~\.claude\skills / ~\.codex\skills / ~\.agents\skills)、用户级 MCP 注册和开发环境:主副本与 git.rpchannel.com 上的 bowei/skills-win 仓库保持同步(其余目录一律是 junction),审计 skills 中的硬编码参数并迁移到本机 ~\skills_env.md,校验 langgraph conda 环境,双向发现并补齐 Claude Code 与 Codex 的用户 MCP 注册,同时确保 E:\MCP_design 下所有 MCP 均已注册。同步的传输一旦出问题,本 skill 还负责登录 gitea 服务器(上海 mac 的 Docker 容器)诊断并修复,直到同步真正成功。当用户提到“同步skills”、“skills同步”、“tools sync”、“tools-sync”、“同步codex”、“codex 里的 skill 怎么进仓库”、“把 codex 新写的 skill 收进来”、“同步MCP”、“MCP 注册/更新/补齐”、“检查MCP注册”、“codex mcp 没了”、“环境同步”、“skills-win”、“把skills推上去/拉下来”、“新电脑配置claude/codex环境”、“skills_env”、“skills 硬编码路径”,或者 git.rpchannel.com 出现“clone/fetch 失败”、“bad pack header”、“early EOF”、“RPC failed”、“推不上去/拉不下来”、“gitea 坏了/连不上/要修”时,必须使用此技能,即使用户没有明确说“skill”二字。也用于处理 junction 指错、两侧 skill 分叉、以及 skills 里的硬编码路径/密码需要迁进 ~\skills_env.md 的场合。
|
description: 在本机统一同步并配置 Claude Code / Codex / OpenCode 的 skills(~\.claude\skills / ~\.codex\skills / ~\.agents\skills)、用户级 MCP 注册和开发环境:主副本与 git.rpchannel.com 上的 bowei/skills-win 仓库保持同步(其余目录一律是 junction),审计 skills 中的硬编码参数并迁移到本机 ~\skills_env.md,校验 langgraph conda 环境,双向发现并补齐 Claude Code 与 Codex 的用户 MCP 注册,并把 Claude Code / Codex 的 skills 注册进 OpenCode(OpenCode 直接读 ~\.claude\skills 与 ~\.agents\skills,~\.codex\skills 通过 opencode.jsonc 登记),同时确保 E:\MCP_design 下所有 MCP 均已注册。同步的传输一旦出问题,本 skill 还负责登录 gitea 服务器(上海 mac 的 Docker 容器)诊断并修复,直到同步真正成功。当用户提到“同步skills”、“skills同步”、“tools sync”、“tools-sync”、“同步codex”、“codex 里的 skill 怎么进仓库”、“把 codex 新写的 skill 收进来”、“同步MCP”、“MCP 注册/更新/补齐”、“检查MCP注册”、“codex mcp 没了”、“环境同步”、“skills-win”、“把skills推上去/拉下来”、“新电脑配置claude/codex环境”、“skills_env”、“skills 硬编码路径”、“注册opencode skills”、“同步opencode”、“opencode 里没有 codex 的 skill”、“把 skills 注册到 opencode”,或者 git.rpchannel.com 出现“clone/fetch 失败”、“bad pack header”、“early EOF”、“RPC failed”、“推不上去/拉不下来”、“gitea 坏了/连不上/要修”时,必须使用此技能,即使用户没有明确说“skill”二字。也用于处理 junction 指错、两侧 skill 分叉、以及 skills 里的硬编码路径/密码需要迁进 ~\skills_env.md 的场合。
|
||||||
---
|
---
|
||||||
|
|
||||||
# tools-sync:Claude Code / Codex 工具链同步
|
# tools-sync:Claude Code / Codex 工具链同步
|
||||||
|
|
||||||
## 目标与总体思路
|
## 目标与总体思路
|
||||||
|
|
||||||
一台开发机上有两个 AI 编码工具(Claude Code 和 Codex),它们各自有 skills 目录和 MCP
|
一台开发机上有三个 AI 编码工具(Claude Code、Codex 和 OpenCode),它们各自有 skills
|
||||||
注册表。这个 skill 的职责是让它们保持一致,并且可以在一台新电脑上从零复原整套配置:
|
目录和 MCP 注册表。这个 skill 的职责是让它们保持一致,并且可以在一台新电脑上从零复原整套配置:
|
||||||
|
|
||||||
- **skills 的唯一真源**是 `http://git.rpchannel.com/bowei/skills-win.git`(remote 名 `origin`)。
|
- **skills 的唯一真源**是 `http://git.rpchannel.com/bowei/skills-win.git`(remote 名 `origin`)。
|
||||||
`~\.claude\skills` 是唯一的 git 检出(主副本);其余目录里的每个 skill 都是指向主副本
|
`~\.claude\skills` 是唯一的 git 检出(主副本);其余目录里的每个 skill 都是指向主副本
|
||||||
@@ -35,8 +35,9 @@ description: 在本机统一同步并配置 Claude Code 与 Codex 的 skills(~
|
|||||||
只有在新机器首次配置时,才从 `~\skills_env.md` 读取用户名/密码完成首次
|
只有在新机器首次配置时,才从 `~\skills_env.md` 读取用户名/密码完成首次
|
||||||
clone(之后 credential helper 会缓存)。
|
clone(之后 credential helper 会缓存)。
|
||||||
|
|
||||||
完整跑一遍下面 6 个阶段就是一次"同步"。用户只要求其中一部分(比如"把 skills 推上去")
|
完整跑一遍下面各阶段(阶段 2 之后还有 2.5 OpenCode,阶段 5 之后是报告)就是一次
|
||||||
时,跑对应阶段即可,但阶段 0 永远先做。
|
"同步"。用户只要求其中一部分(比如"把 skills 推上去")时,跑对应阶段即可,但
|
||||||
|
阶段 0 永远先做。
|
||||||
|
|
||||||
## 阶段 0 — 读取本机环境档案 ~\skills_env.md
|
## 阶段 0 — 读取本机环境档案 ~\skills_env.md
|
||||||
|
|
||||||
@@ -190,6 +191,41 @@ powershell -File <skill目录>\scripts\gitea_doctor.ps1 -Fix # 检查→登
|
|||||||
校验注册:主副本每个 skill 在镜像 registry 都应有同名 junction 且透出 `SKILL.md`
|
校验注册:主副本每个 skill 在镜像 registry 都应有同名 junction 且透出 `SKILL.md`
|
||||||
(脚本已内置该检查)。提醒用户:Codex 要开新会话才会扫到新 skills。
|
(脚本已内置该检查)。提醒用户:Codex 要开新会话才会扫到新 skills。
|
||||||
|
|
||||||
|
## 阶段 2.5 — OpenCode skills 注册
|
||||||
|
|
||||||
|
OpenCode 的 skill 发现模型和 Claude Code / Codex 不同,而且更省事——它**直接读目录,
|
||||||
|
不需要 junction**(详见 OpenCode 官方 V2 skills 文档的 Discovery 一节):
|
||||||
|
|
||||||
|
- **OpenCode 自动发现 `~\.claude\skills` 和 `~\.agents\skills`**(官方叫 "global
|
||||||
|
compatibility" 源)。也就是说,主副本和 MATLAB / 跨工具别名目录对 OpenCode 是**零
|
||||||
|
junction、零镜像、零额外配置**——阶段 1(clone 主副本)+ 阶段 2(MATLAB junction)
|
||||||
|
做完,OpenCode 就自动拿到了全部 Claude + MATLAB 技能,永远和主副本同步。
|
||||||
|
- **OpenCode 不自动发现 `~\.codex\skills`**。要让 OpenCode 也能看到 Codex 独有的 skill
|
||||||
|
(如工程级 `dpd-ctl-flow`),需要在 OpenCode 全局配置里显式登记这个目录。用
|
||||||
|
`scripts/sync_opencode_skills.ps1` 做,配置落在
|
||||||
|
`~\.config\opencode\opencode.jsonc` 的 `skills` 数组:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 只审计;缺少 ~/.codex/skills 条目时退出码为 2,不改配置
|
||||||
|
powershell -File <skill目录>\scripts\sync_opencode_skills.ps1
|
||||||
|
|
||||||
|
# 补上该条目(幂等,保留 model/plugins/agents/mcp 等其余键,写前自动备份)
|
||||||
|
powershell -File <skill目录>\scripts\sync_opencode_skills.ps1 -Apply
|
||||||
|
```
|
||||||
|
|
||||||
|
脚本只补缺失的 `~/.codex/skills` 条目(`~` 相对主目录,跨机器可移植),其余键原样
|
||||||
|
保留,写前备份 `opencode.jsonc.bak-<时间戳>`。改完 `opencode reload` 或开新会话才生效。
|
||||||
|
- **副作用要知情**:登记 `~\.codex\skills` 时 OpenCode 会递归子目录,把 Codex 自己的
|
||||||
|
`~\.codex\skills\.system\` 内置技能(imagegen / openai-docs / review-agent /
|
||||||
|
skill-creator / skill-installer)也暴露出来。这是接受并已记录的副作用——本 skill 仍然
|
||||||
|
**永不编辑** `.system`(与阶段 2 的规矩一致),只是 OpenCode 会读到它们。若用户不想要
|
||||||
|
这些 Codex 内置技能,用 OpenCode 的 `permissions` 按 id 逐条 deny,或干脆不登记
|
||||||
|
`~\.codex\skills`(代价是 `dpd-ctl-flow` 这类 Codex 独有 skill 对 OpenCode 不可见)。
|
||||||
|
- **OpenCode 自己的全局技能目录** `~\.config\opencode\skills` 若出现真实目录(含 SKILL.md、
|
||||||
|
非 junction),说明有技能是在 OpenCode 侧新建的,应当像 Codex 侧一样 ingest 进主副本。
|
||||||
|
`sync_opencode_skills.ps1` 只报告不动手;真正 ingest 交给阶段 2 的流程。更省事的做法是
|
||||||
|
引导用户直接在 `~\.claude\skills` 里建技能——OpenCode 直接读那里,无需任何额外登记。
|
||||||
|
|
||||||
## 阶段 3 — 硬编码审计与 skills_env.md 回填
|
## 阶段 3 — 硬编码审计与 skills_env.md 回填
|
||||||
|
|
||||||
目的:让仓库里的 skills 在任何一台按 `~\skills_env.md` 配置好的电脑上都能用。
|
目的:让仓库里的 skills 在任何一台按 `~\skills_env.md` 配置好的电脑上都能用。
|
||||||
@@ -399,6 +435,7 @@ setupAgenticToolkit("configure", Agents=["claude-code","codex"], ...
|
|||||||
- 服务端: 传输两面均正常 / 医生修复了 <哪几项> / **仍不可用:<RESULT 行>**
|
- 服务端: 传输两面均正常 / 医生修复了 <哪几项> / **仍不可用:<RESULT 行>**
|
||||||
- 从 registry ingest: <被自动收进主副本的 codex/agents 侧 skill;没有则写"无">
|
- 从 registry ingest: <被自动收进主副本的 codex/agents 侧 skill;没有则写"无">
|
||||||
- junction 对账: <修复的 MISDIRECTED、塌缩的重复、清理的失效链接、镜像新建数>
|
- junction 对账: <修复的 MISDIRECTED、塌缩的重复、清理的失效链接、镜像新建数>
|
||||||
|
- OpenCode: 自动读 ~\.claude\skills 与 ~\.agents\skills / ~\.codex\skills 已登记(或本轮 -Apply 补上)/ OpenCode 自有目录待 ingest 的 skill
|
||||||
## 硬编码审计
|
## 硬编码审计
|
||||||
- 本次修复: <清单>
|
- 本次修复: <清单>
|
||||||
- 遗留待改: <清单>
|
- 遗留待改: <清单>
|
||||||
@@ -420,6 +457,8 @@ setupAgenticToolkit("configure", Agents=["claude-code","codex"], ...
|
|||||||
`~\.claude\skills\.system\`;也不动 `codex plugin` 装的 marketplace 插件。
|
`~\.claude\skills\.system\`;也不动 `codex plugin` 装的 marketplace 插件。
|
||||||
- 修改 `~\.codex\config.toml` 前先备份为 `config.toml.bak-<日期>`,TOML 写坏
|
- 修改 `~\.codex\config.toml` 前先备份为 `config.toml.bak-<日期>`,TOML 写坏
|
||||||
会导致 Codex 起不来。
|
会导致 Codex 起不来。
|
||||||
|
- 修改 `~\.config\opencode\opencode.jsonc` 时用 `sync_opencode_skills.ps1 -Apply`
|
||||||
|
(脚本自己会备份 `opencode.jsonc.bak-<时间戳>`);别手改坏 JSONC 让 OpenCode 起不来。
|
||||||
- **ingest 会 `Move-Item`,`-Force` 会 `Remove-Item -Recurse`。** 先 `-DryRun` 看清单,
|
- **ingest 会 `Move-Item`,`-Force` 会 `Remove-Item -Recurse`。** 先 `-DryRun` 看清单,
|
||||||
确认没有误判再实跑;CONFLICT 项在用户裁决前脚本不会碰。
|
确认没有误判再实跑;CONFLICT 项在用户裁决前脚本不会碰。
|
||||||
- 两个脚本都从 PowerShell 运行,不要用 git-bash(MSYS 会改写参数里的 `/c` 和 Windows 路径)。
|
- 两个脚本都从 PowerShell 运行,不要用 git-bash(MSYS 会改写参数里的 `/c` 和 Windows 路径)。
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ SKILLS_REPO_PASS = <填写,或留空表示已存入 Windows 凭据管理器>
|
|||||||
CLAUDE_SKILLS_DIR = C:\Users\<user>\.claude\skills # 唯一 git 检出(主副本)
|
CLAUDE_SKILLS_DIR = C:\Users\<user>\.claude\skills # 唯一 git 检出(主副本)
|
||||||
CODEX_SKILLS_DIR = C:\Users\<user>\.codex\skills # 全量镜像,全是 junction
|
CODEX_SKILLS_DIR = C:\Users\<user>\.codex\skills # 全量镜像,全是 junction
|
||||||
AGENTS_SKILLS_DIR = C:\Users\<user>\.agents\skills # 跨工具别名目录;只做发现/修复,不全量铺
|
AGENTS_SKILLS_DIR = C:\Users\<user>\.agents\skills # 跨工具别名目录;只做发现/修复,不全量铺
|
||||||
|
OPENCODE_CONFIG_DIR = C:\Users\<user>\.config\opencode # OpenCode 全局配置;skills 数组登记 ~/.codex/skills(sync_opencode_skills.ps1 管理)
|
||||||
```
|
```
|
||||||
|
|
||||||
凭据说明:首次 clone 成功后运行 `git config --global credential.helper manager`,
|
凭据说明:首次 clone 成功后运行 `git config --global credential.helper manager`,
|
||||||
|
|||||||
@@ -0,0 +1,189 @@
|
|||||||
|
# tools-sync: register Claude Code + Codex skill sources with OpenCode.
|
||||||
|
#
|
||||||
|
# OpenCode auto-discovers ~/.claude/skills and ~/.agents/skills as "global
|
||||||
|
# compatibility" sources (see the OpenCode V2 skills doc), so the primary
|
||||||
|
# checkout and the cross-tool / MATLAB skills need NO extra work -- OpenCode is
|
||||||
|
# already in sync with the master repo and the MATLAB junctions.
|
||||||
|
#
|
||||||
|
# ~/.codex/skills is NOT auto-discovered. This script makes sure the OpenCode
|
||||||
|
# global config (~/.config/opencode/opencode.jsonc) lists it in the `skills`
|
||||||
|
# array, which exposes Codex-only skills (e.g. a project-level dpd-ctl-flow)
|
||||||
|
# to OpenCode. NOTE: that also pulls in Codex's own ~/.codex/skills/.system
|
||||||
|
# built-ins (imagegen / openai-docs / review-agent / skill-creator /
|
||||||
|
# skill-installer) because OpenCode recurses into subdirectories. That is an
|
||||||
|
# accepted, documented side effect; tools-sync still never edits .system.
|
||||||
|
#
|
||||||
|
# It also reports on OpenCode's own global skills dir
|
||||||
|
# (~/.config/opencode/skills): a real skill directory created there is
|
||||||
|
# host-owned and must be INGESTED into the primary checkout by phase 2 of the
|
||||||
|
# main sync. This script only reports it, it never moves anything.
|
||||||
|
#
|
||||||
|
# Exit codes: 0 = already registered (or fixed under -Apply), 1 = hard failure,
|
||||||
|
# 2 = not registered (audit mode only, no -Apply given).
|
||||||
|
#
|
||||||
|
# Run from PowerShell. This script is ASCII-only (a literal BOM char in
|
||||||
|
# gitea_doctor.ps1 once silently broke every sync -- see skills_env.md).
|
||||||
|
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[string]$OpencodeConfigDir = "$env:USERPROFILE\.config\opencode",
|
||||||
|
[string]$CodexSkillsDir = "$env:USERPROFILE\.codex\skills",
|
||||||
|
[string]$SkillsEntry = "~/.codex/skills",
|
||||||
|
[switch]$Apply
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
function Normalize-PathEntry([string]$p) {
|
||||||
|
if ($p -eq "~" -or $p.StartsWith("~/")) {
|
||||||
|
$p = $env:USERPROFILE + $p.Substring(1)
|
||||||
|
}
|
||||||
|
$p = $p.Replace("\", "/").TrimEnd("/")
|
||||||
|
return $p.ToLowerInvariant()
|
||||||
|
}
|
||||||
|
|
||||||
|
function ConvertFrom-JsonC([string]$text) {
|
||||||
|
# Minimal JSONC -> JSON: strip // line comments and /* */ block comments
|
||||||
|
# while respecting double-quoted strings (the opencode config is small and
|
||||||
|
# has no escape-heavy strings). Throws on malformed input.
|
||||||
|
$sb = New-Object System.Text.StringBuilder
|
||||||
|
$inString = $false
|
||||||
|
$inLineComment = $false
|
||||||
|
$inBlockComment = $false
|
||||||
|
$i = 0
|
||||||
|
$n = $text.Length
|
||||||
|
while ($i -lt $n) {
|
||||||
|
$c = $text[$i]
|
||||||
|
$next = if ($i + 1 -lt $n) { $text[$i + 1] } else { "" }
|
||||||
|
if ($inLineComment) {
|
||||||
|
if ($c -eq "`n" -or $c -eq "`r") { $inLineComment = $false; [void]$sb.Append($c) }
|
||||||
|
}
|
||||||
|
elseif ($inBlockComment) {
|
||||||
|
if ($c -eq "*" -and $next -eq "/") { $inBlockComment = $false; $i++ }
|
||||||
|
}
|
||||||
|
elseif ($inString) {
|
||||||
|
[void]$sb.Append($c)
|
||||||
|
if ($c -eq "\") { if ($i + 1 -lt $n) { [void]$sb.Append($next); $i++ } }
|
||||||
|
elseif ($c -eq '"') { $inString = $false }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($c -eq '"') { $inString = $true; [void]$sb.Append($c) }
|
||||||
|
elseif ($c -eq "/" -and $next -eq "/") { $inLineComment = $true; $i++ }
|
||||||
|
elseif ($c -eq "/" -and $next -eq "*") { $inBlockComment = $true; $i++ }
|
||||||
|
else { [void]$sb.Append($c) }
|
||||||
|
}
|
||||||
|
$i++
|
||||||
|
}
|
||||||
|
return ($sb.ToString() | ConvertFrom-Json)
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- locate config file (jsonc preferred, json fallback) ---
|
||||||
|
$configPath = Join-Path $OpencodeConfigDir "opencode.jsonc"
|
||||||
|
if (-not (Test-Path $configPath -PathType Leaf)) {
|
||||||
|
$jsonPath = Join-Path $OpencodeConfigDir "opencode.json"
|
||||||
|
if (Test-Path $jsonPath -PathType Leaf) { $configPath = $jsonPath }
|
||||||
|
}
|
||||||
|
|
||||||
|
$target = Normalize-PathEntry $SkillsEntry
|
||||||
|
$codexExists = Test-Path $CodexSkillsDir
|
||||||
|
|
||||||
|
Write-Host "OpenCode config : $configPath"
|
||||||
|
Write-Host "Skills entry : $SkillsEntry"
|
||||||
|
if (-not $codexExists) {
|
||||||
|
Write-Warning "$CodexSkillsDir does not exist; the entry will be registered but resolves to nothing."
|
||||||
|
}
|
||||||
|
|
||||||
|
$configExists = Test-Path $configPath -PathType Leaf
|
||||||
|
$root = $null
|
||||||
|
if ($configExists) {
|
||||||
|
$raw = Get-Content $configPath -Raw
|
||||||
|
if ([string]::IsNullOrWhiteSpace($raw)) {
|
||||||
|
$root = [pscustomobject]@{}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$root = ConvertFrom-JsonC $raw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$root = [pscustomobject]@{}
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- inspect current skills array ---
|
||||||
|
$skills = $root.skills
|
||||||
|
if ($null -eq $skills) {
|
||||||
|
$skillList = @()
|
||||||
|
}
|
||||||
|
elseif ($skills -is [string]) {
|
||||||
|
$skillList = @($skills)
|
||||||
|
}
|
||||||
|
elseif ($skills -is [System.Array]) {
|
||||||
|
$skillList = @($skills)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$skillList = @($skills | ForEach-Object { [string]$_ })
|
||||||
|
}
|
||||||
|
|
||||||
|
$registered = $false
|
||||||
|
foreach ($s in $skillList) {
|
||||||
|
if ((Normalize-PathEntry ([string]$s)) -eq $target) { $registered = $true; break }
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- report on OpenCode's own global skills dir ---
|
||||||
|
$ownDir = Join-Path $OpencodeConfigDir "skills"
|
||||||
|
$ownReal = @()
|
||||||
|
if (Test-Path $ownDir -PathType Container) {
|
||||||
|
$ownReal = Get-ChildItem $ownDir -Directory -Force | Where-Object {
|
||||||
|
$_.Name -notlike ".*" -and (Test-Path (Join-Path $_.FullName "SKILL.md") -PathType Leaf)
|
||||||
|
} | Select-Object -ExpandProperty Name
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($registered) {
|
||||||
|
Write-Host "Result : ~/.codex/skills already registered. Nothing to do."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "Result : ~/.codex/skills NOT registered."
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ownReal.Count -gt 0) {
|
||||||
|
Write-Warning ("OpenCode-owned skills in {0} (not junctions, need ingest into primary checkout): {1}" -f $ownDir, ($ownReal -join ", "))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "Own skills dir : none (or empty) in $ownDir"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($registered) {
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $Apply) {
|
||||||
|
Write-Host "Run with -Apply to add the entry to the config."
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- write back under -Apply ---
|
||||||
|
if (-not (Test-Path $OpencodeConfigDir -PathType Container)) {
|
||||||
|
New-Item -ItemType Directory -Path $OpencodeConfigDir -Force | Out-Null
|
||||||
|
}
|
||||||
|
$backup = "$configPath.bak-" + (Get-Date -Format "yyyyMMdd-HHmmss")
|
||||||
|
if ($configExists) {
|
||||||
|
Copy-Item $configPath $backup -Force
|
||||||
|
Write-Host "Backed up : $backup"
|
||||||
|
}
|
||||||
|
|
||||||
|
$skillList = @($skillList) + @($SkillsEntry)
|
||||||
|
$root | Add-Member -MemberType NoteProperty -Name "skills" -Value $skillList -Force
|
||||||
|
|
||||||
|
# Re-serialize. Preserve any existing top-level keys, keep the published schema,
|
||||||
|
# and prepend a short ASCII header comment documenting who manages the file.
|
||||||
|
$json = $root | ConvertTo-Json -Depth 10
|
||||||
|
$header = @(
|
||||||
|
"// OpenCode skill sources. ~/.claude/skills and ~/.agents/skills are auto-",
|
||||||
|
"// discovered (global compatibility sources); ~/.codex/skills is registered",
|
||||||
|
"// here so Codex-only skills are visible. Managed by tools-sync",
|
||||||
|
"// (scripts/sync_opencode_skills.ps1)."
|
||||||
|
)
|
||||||
|
$out = ($header -join "`n") + "`n" + $json + "`n"
|
||||||
|
Set-Content -Path $configPath -Value $out -Encoding UTF8
|
||||||
|
Write-Host "Written : $configPath (skills now includes $SkillsEntry)"
|
||||||
|
Write-Host "NOTE: restart OpenCode (opencode reload) or start a new session to pick it up."
|
||||||
|
exit 0
|
||||||
Reference in New Issue
Block a user