Files
shared/skills/plugins-install/SKILL.md
T

264 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: plugins-install
description: 一次把 JSC 的四個 pluginjsc-codejsc-docjsc-personajsc-shared)安裝或更新到一個或多個 AI 助理,可同時處理 Claude Code、Codex、GitHub Copilot CLI、Antigravity 四家原生 plugin CLI 與沒有 plugin 匯入指令、但可使用 skill 的助理;沒指定時偵測本機裝了哪些 CLI 並讓使用者多選,每個 plugin 先判斷已安裝或未安裝,未安裝就安裝、已安裝就更新到最新。非指令助理先把技能組 clone 到工具專屬資料夾,再依技能組 README.md 將技能匯入到指定位置:已安裝就在 README 指到的路徑就地更新,未安裝才放進工具的預設資料夾,最後以「助理 × plugin」的表格回報動作、位置、結果與版本。當使用者說要安裝所有 jsc plugin、一次更新全部 skill 套件、把 codedocpersonashared 都裝起來、要同時更新好幾個 CLI、換新機器要把 plugin 都補齊、技能匯入到錯的地方、要更新專案自己那份 skills、或問怎麼一次更新所有 plugin 時觸發。不適用於:移除 plugin(用 /jsc-shared:plugins-uninstall)、只處理單一 plugin(直接照該 plugin README 的安裝章節)、安裝非 JSC 的第三方 plugin。
argument-hint: "[--assistant <助理清單,逗號分隔,或 all>] [--plugins code,doc,persona,shared] [--host <gitea 主機>] [--clone-dir <目錄>] [--yes]"
---
# plugins-install — 一次安裝/更新所有 JSC plugin
四階段 skill:先**決定助理與目標清單**,再**逐一判斷已安裝或未安裝**,接著**安裝或更新**,最後**回報結果並提醒重啟工作階段**。
| 階段 | 動作 |
| --- | --- |
| A. 前置設定 | 決定要操作哪些助理(`--assistant` 可帶多個或 all/偵測本機有哪些 CLI/多個就讓使用者多選)→ 決定 gitea 主機 → 決定 plugin 清單(預設 code、doc、persona、shared |
| B. 現況盤點 | 對每個 plugin 查詢 marketplace 與 plugin 是否已存在,決定「安裝」或「更新」 |
| C. 安裝/更新 | 依助理的原生指令逐一執行;Antigravity 走 clone+本地路徑,沒有 plugin 匯入指令但可使用 skill 的助理則先 clone 技能組到工具專屬資料夾,再依 README.md 匯入到指定位置 |
| D. 回報 | 以表格列出每個 plugin 的動作、結果與版本,並提醒重啟工作階段 |
---
## 共用規範(shared plugin,必要前置)
執行本 skill 前,先以 Skill 工具載入下列共用規範並全程遵守:
- `/jsc-shared:spec-output`:繁體中文(台灣用語)、UTF-8(不含 BOM)無亂碼、表格呈現。
- `/jsc-shared:spec-execution`:自動執行原則(必要決策才中斷)、不臆測/需人工確認。
- `/jsc-shared:spec-git-safety`Antigravity/其他會動到本機 clone 的工具路徑有未提交變更時不得強制更新。
本 skill 特有補充:
- **不移除任何東西**。更新時就算需要「先移除再安裝」(Antigravity 沒有 update 子指令),也只針對該 plugin 自己,且移除後必須立刻重裝成功。
- **必要決策**(會中斷詢問):無法判斷目前是哪個助理、指定的助理 CLI 不存在、本機 clone 有未提交變更、安裝失敗且原因需要使用者裁示。
- **可處理 `jsc-shared` 自己**:但更新目前正在執行本 skill 的助理時,將 `shared` 放在該助理的最後處理,並在回報中提醒重啟工作階段。
---
## 參數
- `--assistant <清單>`:要操作的助理,**可以多個**,以逗號分隔(`claude,codex,copilot,agy,opencode`),或用 `all` 代表本機找得到的全部。**省略時**依階段 A1 判斷(只有一個就直接用,多個就讓使用者多選)。
- `--plugins code,doc,persona,shared`:要處理的 plugin(以逗號分隔,用 repo 短名)。**省略時預設四個全做**。
- `--host <gitea 主機>`gitea 主機,省略時預設 `gitea.jsc.idv.tw`
- `--clone-dir <目錄>`Antigravity/其他會用到本機 clone 的工具的根目錄,**省略時預設 `~/plugins`**。
- `--yes`:全自動,不做確認式詢問(必要決策仍會中斷)。
---
## plugin 對照表(安裝識別的唯一依據)
| repo 短名 | plugin 名 | marketplace 名 | 安裝 token | repo 網址 |
| --- | --- | --- | --- | --- |
| `code` | `jsc-code` | `code` | `jsc-code@code` | `https://<host>/plugins/code.git` |
| `doc` | `jsc-doc` | `doc` | `jsc-doc@doc` | `https://<host>/plugins/doc.git` |
| `persona` | `jsc-persona` | `persona` | `jsc-persona@persona` | `https://<host>/plugins/persona.git` |
| `shared` | `jsc-shared` | `shared` | `jsc-shared@shared` | `https://<host>/plugins/shared.git` |
> 指令一律照這張表帶,不要用 repo 短名去猜;若 CLI 回報 marketplace 宣告名稱與表格不一致,先記錄差異,再用 CLI 實際接受的名稱完成同一個 plugin。
各 plugin 帶入的 skill 目錄(OpenCode 路徑會用到):
| repo 短名 | skill 目錄 |
| --- | --- |
| `code` | `action-composite``action-docker``action-node``image``issues``nuget``review-resolve``sync``target` |
| `doc` | `docker``funcs``issues-analyze``issues-analyze-to-file``issues-sync``worklog` |
| `persona` | `persona-anime``persona-chat``persona-create``persona-icon``persona-invite``persona-memory``persona-relation``persona-sleep``persona-status``persona-sync``persona-therapist``persona-transfer` |
| `shared` | `plugins-install``plugins-uninstall``spec-action-params``spec-doc-funcs-handoff``spec-dockerfile``spec-execution``spec-git-safety``spec-gitea``spec-output``spec-plugin-version``spec-project-board``spec-time-log` |
---
## 階段 A:前置設定
### A1. 決定助理(可以一次多個)
`--assistant` 收的是**清單**,不是單一值:`--assistant claude,codex,copilot`、或 `--assistant all`
最終得到的是一組助理,後面每個階段都對**這組的每一個**各跑一遍。
依序判斷,**第一個成立的就採用**:
1. 有帶 `--assistant` → 照它。`all` 代表「本機找得到的全部」(等同下面第 3 點的偵測結果)。
2. 沒帶 → 逐一檢查哪些 CLI 存在(`command -v claude codex copilot agy opencode`):
- 找到 **1 個** → 直接用它。
- 找到 **多個** → 列出來讓使用者**多選**(預設全選)。帶 `--yes` 時不問,直接全做。
3. 一個都沒有 → 回報「找不到任何支援的助理 CLI」並停止。
> 目前正在執行本 skill 的那個助理,如果也在清單裡,**放到最後處理**;該助理內若包含 `shared`,再把 `shared` 放在該助理的最後一個 plugin 處理——更新它自己會需要重啟工作階段。
### A2. 決定 gitea 主機與 clone 根目錄
- 主機:`--host``$GITEA_HOST` → 預設 `gitea.jsc.idv.tw`
- clone 根目錄(只有 `agy``opencode` 用得到):`--clone-dir` → 預設 `~/plugins`。目錄不存在就建立。
### A3. 決定 plugin 清單
`--plugins` 指定則照它,否則 `code,doc,persona,shared` 四個都做。清單中出現對照表以外的名稱 → 回報並略過該項,其餘照做。
---
## 階段 B:現況盤點
對清單中每個 plugin,先查現況再決定動作(**先查再做,不要盲目重裝**):
| 助理 | 查詢指令 | 判定 |
| --- | --- | --- |
| Claude Code | `claude plugin marketplace list``claude plugin list` | 兩者都有 → 更新;缺 marketplace → 先 add;缺 plugin → install |
| Codex | `codex plugin marketplace list``codex plugin list` | 同上 |
| GitHub Copilot CLI | `copilot plugin marketplace list``copilot plugin list` | 同上 |
| Antigravity | `agy plugin list`,並看 `<clone-dir>/<repo>` 是否存在 | 目錄在且已安裝 → 更新;否則安裝 |
| 無 plugin 匯入指令但可使用 skill 的助理 | 先依工具設定或 README.md 找出**所有**候選匯入位置,再看哪個底下已有該 plugin 的 skill 目錄 | 有 → **更新該位置**(重新複製;注意不是覆蓋,見階段 C);都沒有 → 安裝到工具預設資料夾 |
盤點的迴圈是**助理 × plugin**:階段 A1 選定的每個助理,都要對每個 plugin 各判定一次,結果分開記。
指令不存在或子指令不被支援(舊版 CLI)時,**不要中斷整批**:記下那一格為「跳過(CLI 不支援)」,繼續下一個,最後在階段 D 一起回報。同一個助理連續失敗(例如 CLI 存在但每個子指令都不支援)就整個助理標記為跳過,換下一個助理,不要卡住整批。
---
## 階段 C:安裝/更新
以下 `<url>``<plugin>``<marketplace>``<token>` 一律取自對照表。
### Claude Code
```bash
# 安裝(marketplace 尚未加入)
claude plugin marketplace add <url>
claude plugin install <token>
# 更新(已安裝)
claude plugin marketplace update <marketplace>
claude plugin update <token>
```
### Codex
```bash
# 安裝
codex plugin marketplace add <url>
codex plugin add <token>
# 更新(重新抓取 marketplace 的 git 快照)
codex plugin marketplace upgrade <marketplace>
```
### GitHub Copilot CLI
```bash
# 安裝
copilot plugin marketplace add <url>
copilot plugin install <token>
# 更新
copilot plugin marketplace update <marketplace>
copilot plugin update <token>
```
### Antigravity`agy`
> `agy plugin install <url>` 目前只支援 github.comgitea 一律走「clone + 本地路徑」。`agy` 沒有 update 子指令,更新=`git pull` 後重裝。
```bash
# 取得或更新本機 clone(目錄已存在就 pull,不要無條件 clone)
if [ -d "<clone-dir>/<repo>/.git" ]; then
git -C <clone-dir>/<repo> pull --ff-only
else
git clone <url> <clone-dir>/<repo>
fi
# 安裝
agy plugin install <clone-dir>/<repo>
# 更新(agy 沒有 update 子指令,只能重裝)
agy plugin uninstall <plugin>
agy plugin install <clone-dir>/<repo>
```
- **不可無條件 `git clone`**:clone 目錄已經存在(很常見——開發者自己就 clone 在那裡)時,`git clone` 會以 `fatal: destination path already exists` 中止。階段 B 的判定只看「有沒有裝進 agy」,所以「目錄在、但 agy 沒裝」這個狀態會落進安裝分支,必須靠上面的 `if` 擋掉。
- `git pull --ff-only` 失敗(本機有未提交變更或分支分岔)→ **停在該 plugin**,回報現況讓使用者裁示,不得 `reset --hard``clean`,其餘 plugin 照常繼續。
- **先確認 clone 在哪個分支**:`git -C <clone-dir>/<repo> branch --show-current`。若不是發佈分支(`master`),代表要裝進去的是未合併的內容——先告訴使用者,由他決定要換分支還是照裝。預設的 `~/plugins` 很可能就是開發者自己的工作區。
### 無 plugin 匯入指令但可使用 skill 的助理
> 這類助理沒有可用的 plugin 匯入指令,但可以使用 skill,因此改用**目錄安裝**。先把技能組 clone 到工具專屬資料夾,再依技能組 `README.md` 的匯入說明,把技能放到指定位置。
> 這類助理**沒有 plugin CLI 可查安裝清單**,所以不能像四家原生 CLI 那樣「問 CLI 裝了沒」,也**不可預設就往全域目錄倒**——先讀設定或 README.md 找出它實際掛在哪,再決定要更新誰。
#### C-1. 先判定安裝位置(讀設定,不要臆測)
候選位置由近到遠如下,**只有實際存在於磁碟的才納入候選**:
| 順位 | 候選 skills 目錄 | 判定依據 |
| --- | --- | --- |
| 1 | `<專案根>/.opencode/skills/` | 從目前工作目錄往上找到第一個含 `opencode.json``opencode.jsonc``.opencode/` 的目錄,即為專案根 |
| 2 | `${XDG_CONFIG_HOME:-$HOME/.config}/opencode/skills/` | 工具全域資料夾(**未安裝時的預設安裝目標**) |
| 3 | `$HOME/.claude/skills/``$HOME/.agents/skills/` | OpenCode 也會讀的相容來源 |
```bash
# 全域設定目錄(工具資料夾)
OC_HOME="${XDG_CONFIG_HOME:-$HOME/.config}/opencode"
# 從目前工作目錄往上找專案根
proj=""; d="$PWD"
while [ "$d" != "/" ]; do
if [ -f "$d/opencode.json" ] || [ -f "$d/opencode.jsonc" ] || [ -d "$d/.opencode" ]; then proj="$d"; break; fi
d="$(dirname "$d")"
done
# 列出實際存在的候選 skills 目錄
for c in ${proj:+"$proj/.opencode/skills"} "$OC_HOME/skills" "$HOME/.claude/skills" "$HOME/.agents/skills"; do
[ -d "$c" ] && echo "$c"
done
```
判定「這個 plugin 有沒有裝在某個候選位置」,用**對照表列出的 skill 目錄名**去看:候選底下只要出現該 plugin 的任一個 skill 目錄,就算已安裝在那裡。
- 設定檔存在但**內容看不懂或解析失敗** → 不猜。記為「需人工確認」,非 `--yes` 時先問使用者要更新哪個位置。
- 若設定把 skills 指到上表以外的自訂路徑,**以設定為準**,不要改回預設目錄。
#### C-2. 已安裝 → 到該位置就地更新
```bash
# 取得或更新本機 clone(同 Antigravity,不要無條件 clone
if [ -d "<clone-dir>/<repo>/.git" ]; then
git -C <clone-dir>/<repo> pull --ff-only
else
git clone <url> <clone-dir>/<repo>
fi
# <target> = C-1 / README.md 判定出「已經有這個 plugin」的那個目錄(可能是某個專案下的 skills 目錄)
cp -r <clone-dir>/<repo>/skills/* "<target>/"
```
- **就地更新,不要另外補一份到全域目錄**:設定或 README.md 指到專案路徑就更新專案路徑;多倒一份到其他位置會造成同名 skill 兩份、之後每次更新都要記得更兩邊。
- **多個候選位置都已安裝** → 全部更新,並在階段 D **逐列列出各自的位置**,同時提醒使用者這個 plugin 被重複安裝了,建議留一份。
- **目標在某個 git 專案內** → 複製後會產生未提交變更。依 `/jsc-shared:spec-git-safety`:只回報「該專案有新增/異動檔案待處理」,**不代為 commit、不動既有變更**。
#### C-3. 未安裝 → 放進工具的資料夾
```bash
mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/opencode/skills"
cp -r <clone-dir>/<repo>/skills/* "${XDG_CONFIG_HOME:-$HOME/.config}/opencode/skills/"
```
四個候選位置都沒有這個 plugin 時,才裝進工具的全域資料夾;**不要因為當下剛好在某個專案目錄,就自作主張裝進那個專案**。
> **Windows PowerShell**`cp -r A B` → `Copy-Item A B -Recurse -Force`、`~` → `$HOME`、`${XDG_CONFIG_HOME:-$HOME/.config}` → `$env:XDG_CONFIG_HOME` 沒設就用 `$HOME\.config`。
- **`cp -r` 不是覆蓋,是合併**:同名檔案會更新,但**上游已經刪掉的檔案會原地留著**。所以 skill 改名或移除之後,OpenCode 端會同時留著新舊兩份。要乾淨更新就先刪該 plugin 帶入的目錄再複製一次(刪法見 `/jsc-shared:plugins-uninstall` 的 OpenCode 段)。回報時不要講「已覆蓋」,講「已複製,舊檔可能殘留」。
---
## 階段 D:回報
以表格回報,**一個「助理 × plugin」一列**:
| 助理 | plugin | 動作 | 位置 | 結果 | 版本 |
| --- | --- | --- | --- | --- | --- |
| Claude Code | `jsc-code` | 安裝/更新/跳過 | CLI 自管快取 | ✅ 成功/⚠ 需處理/❌ 失敗 | 例 `0.0.2` |
| Codex | `jsc-code` | 更新 | CLI 自管快取 | ✅ 成功 | 未知 |
| OpenCode | `jsc-code` | 更新 | `~/work/app/.opencode/skills` | ✅ 成功 | `0.0.2` |
只處理一個助理時可以省掉「助理」欄。**處理多個時一定要有**,否則使用者看不出哪一格出問題。
- 「位置」欄對**非指令助理必填**(寫出實際複製到的絕對路徑),四家原生 CLI 寫「CLI 自管快取」即可。使用者要知道這次更新的是專案那份還是全域那份。
- 版本取自該 plugin 的 `plugin.json`。**只有 Antigravity 與 OpenCode 拿得到**(它們有本機 clone 可讀);ClaudeCodexCopilot 把 plugin 放在各自 CLI 自管的快取目錄,除非該 CLI 的 `plugin list` 印得出版本,否則一律寫「未知」,不要去猜。
- 有任何一列不是 ✅ → 在表格下方逐項說明原因與建議動作。
- 最後固定提醒:**安裝或更新後要重啟工作階段**才會生效;`jsc-persona` 在 Claude Code 還要用 `/hooks` 確認六個 hook 都在。