@@ -1,7 +1,7 @@
---
name : plugins-install
description : 一次把 JSC 的四 個 plugin( jsc-code/ jsc-doc/ jsc-persona/ jsc-shared )安裝或更新到一個或多個 AI 助理,可同時處理 Claude Code、Codex、GitHub Copilot CLI、Antigravity 四家原生 plugin CLI 與沒有 plugin 匯入指令、但可使用 skill 的助理 ;沒指定時偵測本機裝了哪些 CLI 並讓使用者多選,每個 plugin 先判斷已安裝或未安裝,未安裝就安裝、已安裝就更新到最新。非指令助理先把技能組 clone 到工具專屬資料夾,再依技能組 README.md 將技能匯入到指定位置:已安裝就在 README 指到的路徑就地更新,未安裝才放進工具的預設資料夾 ,最後以「助理 × plugin」的表格回報動作、位置、 結果與版本。當使用者說要安裝所有 jsc plugin、一次更新全部 skill 套件、把 code/ doc/ persona/ shared 都裝起來、要同時更新好幾個 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]"
description : 一次把 JSC 的三 個 plugin( jsc-code/ jsc-doc/ jsc-persona)安裝或更新到一個或多個 AI 助理,可同時處理 Claude Code、Codex、GitHub Copilot CLI、Antigravity 四家原生 plugin CLI 與 OpenCode(複製 skills 目錄) ;沒指定時偵測本機裝了哪些 CLI 並讓使用者多選,每個 plugin 先判斷已安裝或未安裝,未安裝就安裝、已安裝就更新到最新,最後以「助理 × plugin」的表格回報結果與版本。當使用者說要安裝所有 jsc plugin、一次更新全部 skill 套件、把 code/ doc/ persona 都裝起來、要同時更新好幾個 CLI、換新機器要把 plugin 都補齊、或問怎麼一次更新所有 plugin 時觸發。不適用於:移除 plugin(用 /jsc-shared:plugins-uninstall)、只處理單一 plugin(直接照該 plugin README 的安裝章節)、安裝非 JSC 的第三方 plugin。
argument-hint : "[--assistant <助理清單,逗號分隔,或 all>] [--plugins code,doc,persona] [--host <gitea 主機>] [--clone-dir <目錄>] [--yes]"
---
# plugins-install — 一次安裝/更新所有 JSC plugin
@@ -10,9 +10,9 @@ argument-hint: "[--assistant <助理清單,逗號分隔,或 all>] [--plugins
| 階段 | 動作 |
| --- | --- |
| A. 前置設定 | 決定要操作哪些助理(`--assistant` 可帶多個或 all/偵測本機有哪些 CLI/多個就讓使用者多選)→ 決定 gitea 主機 → 決定 plugin 清單(預設 code、doc、persona、shared ) |
| A. 前置設定 | 決定要操作哪些助理(`--assistant` 可帶多個或 all/偵測本機有哪些 CLI/多個就讓使用者多選)→ 決定 gitea 主機 → 決定 plugin 清單(預設 code、doc、persona) |
| B. 現況盤點 | 對每個 plugin 查詢 marketplace 與 plugin 是否已存在,決定「安裝」或「更新」 |
| C. 安裝/更新 | 依助理的原生指令逐一執行;Antigravity 走 clone+本地路徑,預設把本機 clone 收在 `~/.gemini/plugins` (避免共用開發中工作區),沒有 plugin 匯入指令但可使用 skill 的助理則先 clone 技能組到工具專屬資料夾,再依 README.md 匯入到指定位置 |
| C. 安裝/更新 | 依助理的原生指令逐一執行;Antigravity 與 OpenCode 走 clone/複製路徑 |
| D. 回報 | 以表格列出每個 plugin 的動作、結果與版本,並提醒重啟工作階段 |
---
@@ -23,22 +23,22 @@ argument-hint: "[--assistant <助理清單,逗號分隔,或 all>] [--plugins
- `/jsc-shared:spec-output` :繁體中文(台灣用語)、UTF-8(不含 BOM)無亂碼、表格呈現。
- `/jsc-shared:spec-execution` :自動執行原則(必要決策才中斷)、不臆測/需人工確認。
- `/jsc-shared:spec-git-safety` : Antigravity/ 其他 會動到本機 clone 的工具路徑 有未提交變更時不得強制更新。
- `/jsc-shared:spec-git-safety` : Antigravity/ OpenCode 路徑 會動到本機 clone, **工作區 有未提交變更時不得強制更新** 。
本 skill 特有補充:
- **不移除任何東西**。更新時就算需要「先移除再安裝」(Antigravity 沒有 update 子指令),也只針對該 plugin 自己,且移除後必須立刻重裝成功。
- **必要決策**(會中斷詢問):無法判斷目前是哪個助理、指定的助理 CLI 不存在、本機 clone 有未提交變更、安裝失敗且原因需要使用者裁示。
- **可 處理 `jsc-shared` 自己**: 但更新目前正在執行本 skill 的助理時,將 `shared` 放在該助理的最後處理,並在回報中提醒重啟工作階段 。
- **本 skill 不 處理 `jsc-shared` 自己**: 它是本 skill 的所在地,安裝它請直接照 shared 的 README 。
---
## 參數
- `--assistant <清單>` :要操作的助理,**可以多個**,以逗號分隔(`claude,codex,copilot,agy,opencode` ),或用 `all` 代表本機找得到的全部。**省略時**依階段 A1 判斷(只有一個就直接用,多個就讓使用者多選)。
- `--plugins code,doc,persona,shared ` :要處理的 plugin(以逗號分隔,用 repo 短名)。**省略時預設四 個全做**。
- `--plugins code,doc,persona` :要處理的 plugin(以逗號分隔,用 repo 短名)。**省略時預設三 個全做**。
- `--host <gitea 主機>` : gitea 主機,省略時預設 `gitea.jsc.idv.tw` 。
- `--clone-dir <目錄>` : Antigravity/ 其他會用到本機 clone 的工具的根目錄。 `agy` 預設用 `~/.gemini/plugins` , `opencode` 預設用 `~/plugins` ;若兩者同時選中而且要共用同一個 clone root,必須由使用者明確指定 `--clone-dir` 。
- `--clone-dir <目錄>` : Antigravity/ OpenCode 的本機 clone 根目錄,**省略時 預設 `~/plugins` ** 。
- `--yes` :全自動,不做確認式詢問(必要決策仍會中斷)。
---
@@ -49,19 +49,17 @@ argument-hint: "[--assistant <助理清單,逗號分隔,或 all>] [--plugins
| --- | --- | --- | --- | --- |
| `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` |
| `persona` | `jsc-persona` | `jsc-plugins ` | `jsc-persona@jsc-plugins ` | `https://<host>/plugins/persona.git` |
> 指令一律照這張表帶,不要用 repo 短名去猜;若 CLI 回報 marketplace 宣告名稱與表格不一致,先記錄差異,再用 CLI 實際接受的名稱完成同一個 plugin 。
> **`persona` 的 marketplace 名不是 repo 名**(是 `jsc-plugins`)。 指令一律照這張表帶,不要用 repo 短名去猜。
各 plugin 帶入的 skill 目錄(OpenCode 路徑會用到):
| repo 短名 | skill 目錄 |
| --- | --- |
| `code` | `action-composite` 、`action-docker` 、`action-node` 、`image` 、`issues` 、`nuget` 、`review-resolve` 、`sync` 、 `target` |
| `code` | `action-composite` 、`action-docker` 、`action-node` 、`image` 、`issues` 、`nuget` 、`review-resolve` 、`sync` |
| `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` |
---
@@ -80,16 +78,16 @@ argument-hint: "[--assistant <助理清單,逗號分隔,或 all>] [--plugins
- 找到 **多個 ** → 列出來讓使用者**多選**(預設全選)。帶 `--yes` 時不問,直接全做。
3. 一個都沒有 → 回報「找不到任何支援的助理 CLI」並停止。
> 目前正在執行本 skill 的那個助理,如果也在清單裡,**放到最後處理**;該助理內若包含 `shared`,再把 `shared` 放在該助理的最後一個 plugin 處理 ——更新它自己會需要重啟工作階段。
> 目前正在執行本 skill 的那個助理,如果也在清單裡,**放到最後處理**——更新它自己會需要重啟工作階段。
### A2. 決定 gitea 主機與 clone 根目錄
- 主機:`--host` → `$GITEA_HOST` → 預設 `gitea.jsc.idv.tw` 。
- clone 根目錄(只有 `agy` / `opencode` 用得到):`--clone-dir` → `agy` 預設 `~/.gemini/plugins` 、 `opencode` 預設 `~/plugins` 。若兩者同時選中且未指定 `--clone-dir` ,先判斷是否要拆成兩個根目錄;不要默認共用同一份開發工作區 。目錄不存在就建立。
- clone 根目錄(只有 `agy` / `opencode` 用得到):`--clone-dir` → 預設 `~/plugins` 。目錄不存在就建立。
### A3. 決定 plugin 清單
`--plugins` 指定則照它,否則 `code,doc,persona,shared ` 四 個都做。清單中出現對照表以外的名稱 → 回報並略過該項,其餘照做。
`--plugins` 指定則照它,否則 `code,doc,persona` 三 個都做。清單中出現對照表以外的名稱 → 回報並略過該項,其餘照做。
---
@@ -102,8 +100,8 @@ argument-hint: "[--assistant <助理清單,逗號分隔,或 all>] [--plugins
| 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` ,並看 `~/.gemini/plugins/<repo>` 是否存在(除非使用者明確指定 `--clone-dir` ) | 目錄在且已安裝 → 更新;否則安裝 |
| 無 plugin 匯入指令但可使用 skill 的助理 | 先依工具設定或 README.md 找出**所有**候選匯入位置,再看哪個底下 已有該 plugin 的 skill 目錄 | 有 → **更新該位置 ** (重新複製;注意不是覆蓋,見階段 C);都 沒有 → 安裝到工具預設資料夾 |
| Antigravity | `agy plugin list` ,並看 `<clone-dir>/<repo>` 是否存在 | 目錄在且已安裝 → 更新;否則安裝 |
| OpenCode | 看 `~/.config/opencode/skills/` 底下是否 已有該 plugin 的 skill 目錄 | 有 → 更新 (重新複製;注意不是覆蓋,見階段 C);沒有 → 安裝 |
盤點的迴圈是**助理 × plugin**:階段 A1 選定的每個助理,都要對每個 plugin 各判定一次,結果分開記。
@@ -152,15 +150,14 @@ copilot plugin update <token>
### Antigravity( `agy`)
> `agy plugin install <url>` 目前只支援 github.com; gitea 一律走「clone + 本地路徑」。`agy` 沒有 update 子指令,更新=`git pull` 後重裝。**預設 clone root 在 `~/.gemini/plugins`,不要偷用目前工作目錄或 `~/plugins` 的開發工作區。**
> `agy plugin install <url>` 目前只支援 github.com; gitea 一律走「clone + 本地路徑」。`agy` 沒有 update 子指令,更新=`git pull` 後重裝。
``` bash
# 取得或更新本機 clone( 只看 clone root 內的 repo;新 clone 用 master,已存在就把 master 拉到最新 )
# 取得或更新本機 clone( 目錄已存在就 pull,不要無條件 clone )
if [ -d "<clone-dir>/<repo>/.git" ] ; then
git -C <clone-dir>/<repo> switch master
git -C <clone-dir>/<repo> pull --ff-only origin master
git -C <clone-dir>/<repo> pull --ff-only
else
git clone --branch master --single-branch <url> <clone-dir>/<repo>
git clone <url> <clone-dir>/<repo>
fi
# 安裝
@@ -172,47 +169,12 @@ agy plugin install <clone-dir>/<repo>
```
- **不可無條件 `git clone` **:clone 目錄已經存在(很常見——開發者自己就 clone 在那裡)時,`git clone` 會以 `fatal: destination path already exists` 中止。階段 B 的判定只看「有沒有裝進 agy」,所以「目錄在、但 agy 沒裝」這個狀態會落進安裝分支,必須靠上面的 `if` 擋掉。
- `git -C <clone-dir>/<repo> switch master` 或 `git pull --ff-only origin master ` 失敗(本機有未提交變更、 分支分岔,或本機 repo 無法切到 master )→ **停在該 plugin ** ,回報現況讓使用者裁示,不得 `reset --hard` / `clean` ,其餘 plugin 照常繼續。
- **先確認 clone 在哪個分支**:`git -C <clone-dir>/<repo> branch --show-current` 。這裡檢查的是 `clone root` 裡的 repo,不是目前工作目錄的任何專案。 `agy` 的本機 clone 應以 `master` 為準;若不是,先切回 `master` ,再把 `master` 拉到最新 。
- `git pull --ff-only ` 失敗(本機有未提交變更或 分支分岔)→ **停在該 plugin ** ,回報現況讓使用者裁示,不得 `reset --hard` / `clean` ,其餘 plugin 照常繼續。
- **先確認 clone 在哪個分支**:`git -C <clone-dir>/<repo> branch --show-current` 。若不是發佈分支( `master` ),代表要裝進去的是未合併的內容——先告訴使用者,由他決定要換分支還是照裝。預設的 `~/plugins` 很可能就是開發者自己的工作區 。
### 無 plugin 匯入指令但可使用 skill 的助理
### OpenCode
> 這類助理沒有可用的 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. 已安裝 → 到該位置就地更新
> OpenCode 的 plugin 是 npm 套件,不適用 skill 包;改用目錄安裝。OpenCode 只會帶入 `skills/`,安裝前要先告知使用者 。
``` bash
# 取得或更新本機 clone(同 Antigravity,不要無條件 clone)
@@ -222,24 +184,11 @@ else
git clone <url> <clone-dir>/<repo>
fi
# <target> = C-1 / README.md 判定出「已經有這個 plugin」的那個目錄(可能是某個專案下的 skills 目錄)
cp -r <clone-dir>/<repo>/skills/* "<target>/"
mkdir -p ~/.config/opencode/ skills
cp -r <clone-dir>/<repo>/skills/* ~/.config/opencode/skills/
```
- **就地更新,不要另外補一份到全域目錄**:設定或 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`。
> **Windows PowerShell**: `cp -r A B` → `Copy-Item A B -Recurse -Force`、`~` → `$HOME` 。
- **`cp -r` 不是覆蓋,是合併**:同名檔案會更新,但**上游已經刪掉的檔案會原地留著**。所以 skill 改名或移除之後,OpenCode 端會同時留著新舊兩份。要乾淨更新就先刪該 plugin 帶入的目錄再複製一次(刪法見 `/jsc-shared:plugins-uninstall` 的 OpenCode 段)。回報時不要講「已覆蓋」,講「已複製,舊檔可能殘留」。
@@ -249,16 +198,13 @@ cp -r <clone-dir>/<repo>/skills/* "${XDG_CONFIG_HOME:-$HOME/.config}/opencode/sk
以表格回報,**一個「助理 × plugin」一列**:
| 助理 | plugin | 動作 | 位置 | 結果 | 版本 |
| --- | --- | --- | --- | --- | --- |
| Claude Code | `jsc-code` | 安裝/更新/跳過 | CLI 自管快取 | ✅ 成功/⚠ 需處理/❌ 失敗 | 例 `0.0.2` |
| Codex | `jsc-code` | 更新 | CLI 自管快取 | ✅ 成功 | 未知 |
| OpenCode | `jsc-code` | 更新 | `~/work/app/.opencode/skills` | ✅ 成功 | `0.0.2` |
| 助理 | plugin | 動作 | 結果 | 版本 |
| --- | --- | --- | --- | --- |
| Claude Code | `jsc-code` | 安裝/更新/跳過 | ✅ 成功/⚠ 需處理/❌ 失敗 | 例 `0.0.2` |
| Codex | `jsc-code` | 更新 | ✅ 成功 | 未知 |
只處理一個助理時可以省掉「助理」欄。**處理多個時一定要有**,否則使用者看不出哪一格出問題。
- 「位置」欄對**非指令助理必填**(寫出實際複製到的絕對路徑),四家原生 CLI 寫「CLI 自管快取」即可。使用者要知道這次更新的是專案那份還是全域那份。
- 版本取自該 plugin 的 `plugin.json` 。**只有 Antigravity 與 OpenCode 拿得到**(它們有本機 clone 可讀);Claude/ Codex/ Copilot 把 plugin 放在各自 CLI 自管的快取目錄,除非該 CLI 的 `plugin list` 印得出版本,否則一律寫「未知」,不要去猜。
- 有任何一列不是 ✅ → 在表格下方逐項說明原因與建議動作。
- 最後固定提醒:**安裝或更新後要重啟工作階段**才會生效;`jsc-persona` 在 Claude Code 還要用 `/hooks` 確認六個 hook 都在。